xref: /btstack/test/le_audio/le_audio_broadcast_source.c (revision 166aee1908314fa80844e0b7bd13d514f96df013)
110277393SMatthias Ringwald /*
210277393SMatthias Ringwald  * Copyright (C) 2022 BlueKitchen GmbH
310277393SMatthias Ringwald  *
410277393SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
510277393SMatthias Ringwald  * modification, are permitted provided that the following conditions
610277393SMatthias Ringwald  * are met:
710277393SMatthias Ringwald  *
810277393SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
910277393SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1010277393SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1110277393SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1210277393SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1310277393SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1410277393SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1510277393SMatthias Ringwald  *    from this software without specific prior written permission.
1610277393SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
1710277393SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
1810277393SMatthias Ringwald  *    monetary gain.
1910277393SMatthias Ringwald  *
2010277393SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2110277393SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2210277393SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2310277393SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
2410277393SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2510277393SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2610277393SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2710277393SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2810277393SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2910277393SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3010277393SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3110277393SMatthias Ringwald  * SUCH DAMAGE.
3210277393SMatthias Ringwald  *
3310277393SMatthias Ringwald  * Please inquire about commercial licensing options at
3410277393SMatthias Ringwald  * [email protected]
3510277393SMatthias Ringwald  *
3610277393SMatthias Ringwald  */
3710277393SMatthias Ringwald 
3810277393SMatthias Ringwald #define BTSTACK_FILE__ "le_audio_broadcast_source.c"
3910277393SMatthias Ringwald 
4010277393SMatthias Ringwald /*
4110277393SMatthias Ringwald  * LE Audio Broadcast Source
4210277393SMatthias Ringwald  */
4310277393SMatthias Ringwald 
4410277393SMatthias Ringwald #include <stdint.h>
4510277393SMatthias Ringwald #include <stdio.h>
4610277393SMatthias Ringwald #include <string.h>
4710277393SMatthias Ringwald #include <btstack_debug.h>
4810277393SMatthias Ringwald 
4910277393SMatthias Ringwald #include "bluetooth_data_types.h"
5010277393SMatthias Ringwald #include "btstack_stdin.h"
5110277393SMatthias Ringwald #include "btstack_event.h"
5210277393SMatthias Ringwald #include "btstack_run_loop.h"
5310277393SMatthias Ringwald #include "gap.h"
5410277393SMatthias Ringwald #include "hci.h"
5510277393SMatthias Ringwald #include "hci_cmd.h"
5610277393SMatthias Ringwald #include "hci_dump.h"
572fd68da2SMatthias Ringwald #include "btstack_lc3.h"
58e40ee29aSMatthias Ringwald #include "btstack_lc3_google.h"
5910277393SMatthias Ringwald 
6010277393SMatthias Ringwald #include "hxcmod.h"
6110277393SMatthias Ringwald #include "mods/mod.h"
6210277393SMatthias Ringwald 
6310277393SMatthias Ringwald // PTS mode
6410277393SMatthias Ringwald // #define PTS_MODE
6510277393SMatthias Ringwald 
6610277393SMatthias Ringwald // Count mode - send packet count as test data for manual analysis
6710277393SMatthias Ringwald // #define COUNT_MODE
6810277393SMatthias Ringwald 
6910277393SMatthias Ringwald // max config
7010277393SMatthias Ringwald #define MAX_NUM_BIS 2
7110277393SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480
723f485d09SMatthias Ringwald #define MAX_LC3_FRAME_BYTES   155
7310277393SMatthias Ringwald 
7410277393SMatthias Ringwald static const uint8_t adv_sid = 0;
7510277393SMatthias Ringwald 
7610277393SMatthias Ringwald static le_advertising_set_t le_advertising_set;
7710277393SMatthias Ringwald 
7810277393SMatthias Ringwald static const le_extended_advertising_parameters_t extended_params = {
7910277393SMatthias Ringwald         .advertising_event_properties = 0,
8010277393SMatthias Ringwald         .primary_advertising_interval_min = 0x4b0, // 750 ms
8110277393SMatthias Ringwald         .primary_advertising_interval_max = 0x4b0, // 750 ms
8210277393SMatthias Ringwald         .primary_advertising_channel_map = 7,
8310277393SMatthias Ringwald         .own_address_type = 0,
8410277393SMatthias Ringwald         .peer_address_type = 0,
85c52eeb3dSMatthias Ringwald         .peer_address =  { 0 },
8610277393SMatthias Ringwald         .advertising_filter_policy = 0,
8710277393SMatthias Ringwald         .advertising_tx_power = 10, // 10 dBm
8810277393SMatthias Ringwald         .primary_advertising_phy = 1, // LE 1M PHY
8910277393SMatthias Ringwald         .secondary_advertising_max_skip = 0,
9010277393SMatthias Ringwald         .secondary_advertising_phy = 1, // LE 1M PHY
9110277393SMatthias Ringwald         .advertising_sid = adv_sid,
9210277393SMatthias Ringwald         .scan_request_notification_enable = 0,
9310277393SMatthias Ringwald };
9410277393SMatthias Ringwald 
9570718632SMatthias Ringwald // Random Broadcast ID, valid for lifetime of BIG
9670718632SMatthias Ringwald #define BROADCAST_ID (0x112233u)
9770718632SMatthias Ringwald 
9810277393SMatthias Ringwald static const uint8_t extended_adv_data[] = {
9910277393SMatthias Ringwald         // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID
10070718632SMatthias Ringwald         6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18,
10170718632SMatthias Ringwald         BROADCAST_ID >> 16,
10270718632SMatthias Ringwald         (BROADCAST_ID >> 8) & 0xff,
10370718632SMatthias Ringwald         BROADCAST_ID & 0xff,
10410277393SMatthias Ringwald         // name
10510277393SMatthias Ringwald #ifdef PTS_MODE
10610277393SMatthias Ringwald         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x'
10710277393SMatthias Ringwald #elif defined(COUNT_MODE)
10810277393SMatthias Ringwald         6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T'
10910277393SMatthias Ringwald #else
11010277393SMatthias Ringwald         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e'
11110277393SMatthias Ringwald #endif
11210277393SMatthias Ringwald };
11310277393SMatthias Ringwald 
11410277393SMatthias Ringwald static const le_periodic_advertising_parameters_t periodic_params = {
11510277393SMatthias Ringwald         .periodic_advertising_interval_min = 0x258, // 375 ms
11610277393SMatthias Ringwald         .periodic_advertising_interval_max = 0x258, // 375 ms
11710277393SMatthias Ringwald         .periodic_advertising_properties = 0
11810277393SMatthias Ringwald };
11910277393SMatthias Ringwald 
12010277393SMatthias Ringwald static uint8_t periodic_adv_data_1[] = {
12110277393SMatthias Ringwald     // 16 bit service data
12210277393SMatthias Ringwald     37, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID,
12310277393SMatthias Ringwald         // Level 1 - BIG Parameters (common to all BISes)
12410277393SMatthias Ringwald         0x51, 0x18,         // Basic Audio Announcement Service UUID
12510277393SMatthias Ringwald         0x28, 0x00, 0x00,   // Presentation Delay 3
12610277393SMatthias Ringwald         0x01,               // Num_Subgroups
12710277393SMatthias Ringwald         // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes)
12810277393SMatthias Ringwald         // offset 8
12910277393SMatthias Ringwald         0x01,               // The number of BISes in this subgroup
13010277393SMatthias Ringwald         0x06, 0x00, 0x00, 0x00, 0x00,  // 0x06 = LC3, vendor id + codec id = 0
13110277393SMatthias Ringwald         10,                 // Codec_Specific_Configuration_Length[i]
13210277393SMatthias Ringwald         // Codec_Specific_Configuration[i] = 8_2
13310277393SMatthias Ringwald         // offset 15
13410277393SMatthias Ringwald         0x02, 0x01, 0x01,       // Sampling frequency 0x01 = 0x01 / 8 kHz
13510277393SMatthias Ringwald         0x02, 0x02, 0x01,       // Frame Duration     0x02 = 0x01 / 10 ms
13610277393SMatthias Ringwald         0x03, 0x04, 0x1E, 0x00, // Octets per Frame   0x04 = 0x1e / 30
13710277393SMatthias Ringwald         4,                  // Metadata_Length[i]
13810277393SMatthias Ringwald         0x03, 0x02, 0x04, 0x00, // Metadata[i]
13910277393SMatthias Ringwald         // Level 3 - Specific BIS Parameters (if required, for individual BISes)
14010277393SMatthias Ringwald         0x01,               // BIS_index[i[k]]
14110277393SMatthias Ringwald         6,                  // Codec_Specific_Configuration_Length[i[k]]
14210277393SMatthias Ringwald         0x05, 0x03, 0x01, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]]
14310277393SMatthias Ringwald };
14410277393SMatthias Ringwald 
14510277393SMatthias Ringwald static uint8_t periodic_adv_data_2[] = {
14610277393SMatthias Ringwald     // 16 bit service data
14710277393SMatthias Ringwald     37+8, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID,
14810277393SMatthias Ringwald         // Level 1 - BIG Parameters (common to all BISes)
14910277393SMatthias Ringwald         0x51, 0x18,         // Basic Audio Announcement Service UUID
15010277393SMatthias Ringwald         0x28, 0x00, 0x00,   // Presentation Delay 3
15110277393SMatthias Ringwald         0x01,               // Num_Subgroups
15210277393SMatthias Ringwald         // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes)
15310277393SMatthias Ringwald         // offset 8
15410277393SMatthias Ringwald         0x02,               // The number of BISes in this subgroup
15510277393SMatthias Ringwald         0x06, 0x00, 0x00, 0x00, 0x00,  // 0x06 = LC3, vendor id + codec id = 0
15610277393SMatthias Ringwald         10,                 // Codec_Specific_Configuration_Length[i]
15710277393SMatthias Ringwald         // Codec_Specific_Configuration[0] = 8_2
15810277393SMatthias Ringwald         // offset 15
15910277393SMatthias Ringwald         0x02, 0x01, 0x01,       // Sampling frequency 0x01 = 0x01 / 8 kHz
16010277393SMatthias Ringwald         0x02, 0x02, 0x01,       // Frame Duration     0x02 = 0x01 / 10 ms
16110277393SMatthias Ringwald         0x03, 0x04, 0x1E, 0x00, // Octets per Frame   0x04 = 0x1e / 30
16210277393SMatthias Ringwald         4,                  // Metadata_Length[i]
16310277393SMatthias Ringwald         0x03, 0x02, 0x04, 0x00, // Metadata[0]
16410277393SMatthias Ringwald         // Level 3 - Specific BIS Parameters (if required, for individual BISes)
16510277393SMatthias Ringwald         0x01,               // BIS_index[i[k]]
16610277393SMatthias Ringwald         6,                  // Codec_Specific_Configuration_Length[i[k]]
16710277393SMatthias Ringwald         0x05, 0x03, 0x01, 0x00, 0x00, 0x00, // Codec_Specific_Configuration[i[k]]
16810277393SMatthias Ringwald         // Level 3 - Specific BIS Parameters (if required, for individual BISes)
16910277393SMatthias Ringwald         0x02,               // BIS_index[i[k]]
17010277393SMatthias Ringwald         6,                  // Codec_Specific_Configuration_Length[i[k]]
17110277393SMatthias Ringwald         0x05, 0x03, 0x02, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]]
17210277393SMatthias Ringwald };
17310277393SMatthias Ringwald 
17410277393SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz
17510277393SMatthias Ringwald static const int16_t sine_int16[] = {
17610277393SMatthias Ringwald         0,    643,   1286,   1929,   2571,   3212,   3851,   4489,   5126,   5760,
17710277393SMatthias Ringwald         6393,   7022,   7649,   8273,   8894,   9512,  10126,  10735,  11341,  11943,
17810277393SMatthias Ringwald         12539,  13131,  13718,  14300,  14876,  15446,  16011,  16569,  17121,  17666,
17910277393SMatthias Ringwald         18204,  18736,  19260,  19777,  20286,  20787,  21280,  21766,  22242,  22710,
18010277393SMatthias Ringwald         23170,  23620,  24062,  24494,  24916,  25329,  25732,  26126,  26509,  26882,
18110277393SMatthias Ringwald         27245,  27597,  27938,  28269,  28589,  28898,  29196,  29482,  29757,  30021,
18210277393SMatthias Ringwald         30273,  30513,  30742,  30958,  31163,  31356,  31537,  31705,  31862,  32006,
18310277393SMatthias Ringwald         32137,  32257,  32364,  32458,  32540,  32609,  32666,  32710,  32742,  32761,
18410277393SMatthias Ringwald         32767,  32761,  32742,  32710,  32666,  32609,  32540,  32458,  32364,  32257,
18510277393SMatthias Ringwald         32137,  32006,  31862,  31705,  31537,  31356,  31163,  30958,  30742,  30513,
18610277393SMatthias Ringwald         30273,  30021,  29757,  29482,  29196,  28898,  28589,  28269,  27938,  27597,
18710277393SMatthias Ringwald         27245,  26882,  26509,  26126,  25732,  25329,  24916,  24494,  24062,  23620,
18810277393SMatthias Ringwald         23170,  22710,  22242,  21766,  21280,  20787,  20286,  19777,  19260,  18736,
18910277393SMatthias Ringwald         18204,  17666,  17121,  16569,  16011,  15446,  14876,  14300,  13718,  13131,
19010277393SMatthias Ringwald         12539,  11943,  11341,  10735,  10126,   9512,   8894,   8273,   7649,   7022,
19110277393SMatthias Ringwald         6393,   5760,   5126,   4489,   3851,   3212,   2571,   1929,   1286,    643,
19210277393SMatthias Ringwald         0,   -643,  -1286,  -1929,  -2571,  -3212,  -3851,  -4489,  -5126,  -5760,
19310277393SMatthias Ringwald         -6393,  -7022,  -7649,  -8273,  -8894,  -9512, -10126, -10735, -11341, -11943,
19410277393SMatthias Ringwald         -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666,
19510277393SMatthias Ringwald         -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710,
19610277393SMatthias Ringwald         -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882,
19710277393SMatthias Ringwald         -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021,
19810277393SMatthias Ringwald         -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006,
19910277393SMatthias Ringwald         -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761,
20010277393SMatthias Ringwald         -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257,
20110277393SMatthias Ringwald         -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513,
20210277393SMatthias Ringwald         -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597,
20310277393SMatthias Ringwald         -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620,
20410277393SMatthias Ringwald         -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736,
20510277393SMatthias Ringwald         -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131,
20610277393SMatthias Ringwald         -12539, -11943, -11341, -10735, -10126,  -9512,  -8894,  -8273,  -7649,  -7022,
20710277393SMatthias Ringwald         -6393,  -5760,  -5126,  -4489,  -3851,  -3212,  -2571,  -1929,  -1286,   -643,
20810277393SMatthias Ringwald };
20910277393SMatthias Ringwald 
21010277393SMatthias Ringwald static bd_addr_t remote;
21110277393SMatthias Ringwald static const char * remote_addr_string = "00:1B:DC:08:E2:72";
21210277393SMatthias Ringwald 
21310277393SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
21410277393SMatthias Ringwald 
21510277393SMatthias Ringwald static uint8_t adv_handle = 0;
21610277393SMatthias Ringwald static unsigned int     next_bis_index;
21710277393SMatthias Ringwald static hci_con_handle_t bis_con_handles[MAX_NUM_BIS];
21810277393SMatthias Ringwald static uint16_t packet_sequence_numbers[MAX_NUM_BIS];
21910277393SMatthias Ringwald static uint8_t framed_pdus;
22010277393SMatthias Ringwald static bool bis_can_send[MAX_NUM_BIS];
22110277393SMatthias Ringwald static bool bis_has_data[MAX_NUM_BIS];
22210277393SMatthias Ringwald static uint8_t iso_frame_counter;
22310277393SMatthias Ringwald static uint16_t frame_duration_us;
22410277393SMatthias Ringwald 
225cd0bedb1SMatthias Ringwald static le_audio_big_t big_storage;
226cd0bedb1SMatthias Ringwald static le_audio_big_params_t big_params;
227cd0bedb1SMatthias Ringwald 
22810277393SMatthias Ringwald // time stamping
22910277393SMatthias Ringwald #ifdef COUNT_MODE
23010277393SMatthias Ringwald #define MAX_PACKET_INTERVAL_BINS_MS 50
23110277393SMatthias Ringwald static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS];
23210277393SMatthias Ringwald static uint32_t send_last_ms;
23310277393SMatthias Ringwald #endif
23410277393SMatthias Ringwald 
23510277393SMatthias Ringwald // lc3 codec config
236c52eeb3dSMatthias Ringwald static uint16_t sampling_frequency_hz;
2372fd68da2SMatthias Ringwald static btstack_lc3_frame_duration_t frame_duration;
23810277393SMatthias Ringwald static uint16_t number_samples_per_frame;
23910277393SMatthias Ringwald static uint16_t octets_per_frame;
24010277393SMatthias Ringwald static uint8_t  num_bis = 1;
24110277393SMatthias Ringwald 
24210277393SMatthias Ringwald // lc3 encoder
2432fd68da2SMatthias Ringwald static const btstack_lc3_encoder_t * lc3_encoder;
244e40ee29aSMatthias Ringwald static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS];
24510277393SMatthias Ringwald static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME];
2463f485d09SMatthias Ringwald static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES];
24710277393SMatthias Ringwald static uint32_t time_generation_ms;
24810277393SMatthias Ringwald 
24910277393SMatthias Ringwald // codec menu
25010277393SMatthias Ringwald static uint8_t menu_sampling_frequency;
25110277393SMatthias Ringwald static uint8_t menu_variant;
25210277393SMatthias Ringwald 
25310277393SMatthias Ringwald // mod player
25410277393SMatthias Ringwald static int hxcmod_initialized;
25510277393SMatthias Ringwald static modcontext mod_context;
25610277393SMatthias Ringwald static tracker_buffer_state trkbuf;
25710277393SMatthias Ringwald 
25810277393SMatthias Ringwald // sine generator
25910277393SMatthias Ringwald static uint8_t  sine_step;
26010277393SMatthias Ringwald static uint16_t sine_phases[MAX_NUM_BIS];
26110277393SMatthias Ringwald 
262ac95ea81SMatthias Ringwald // encryption
263ac95ea81SMatthias Ringwald static uint8_t encryption = 0;
264*166aee19SMatthias Ringwald static uint8_t broadcast_code [] = {0x01, 0x02, 0x68, 0x05, 0x53, 0xF1, 0x41, 0x5A, 0xA2, 0x65, 0xBB, 0xAF, 0xC6, 0xEA, 0x03, 0xB8, };
265ac95ea81SMatthias Ringwald 
26610277393SMatthias Ringwald // audio producer
26710277393SMatthias Ringwald static enum {
26810277393SMatthias Ringwald     AUDIO_SOURCE_SINE,
26910277393SMatthias Ringwald     AUDIO_SOURCE_MODPLAYER
27010277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER;
27110277393SMatthias Ringwald 
27210277393SMatthias Ringwald static enum {
27310277393SMatthias Ringwald     APP_IDLE,
27410277393SMatthias Ringwald     APP_W4_CREATE_BIG_COMPLETE,
275b9b9e477SMatthias Ringwald     APP_STREAMING,
276b9b9e477SMatthias Ringwald     APP_W4_POWER_OFF,
27710277393SMatthias Ringwald } app_state = APP_IDLE;
27810277393SMatthias Ringwald 
27910277393SMatthias Ringwald // enumerate default codec configs
28010277393SMatthias Ringwald static struct {
281c52eeb3dSMatthias Ringwald     uint16_t samplingrate_hz;
28210277393SMatthias Ringwald     uint8_t  samplingrate_index;
28310277393SMatthias Ringwald     uint8_t  num_variants;
28410277393SMatthias Ringwald     struct {
28510277393SMatthias Ringwald         const char * name;
2862fd68da2SMatthias Ringwald         btstack_lc3_frame_duration_t frame_duration;
28710277393SMatthias Ringwald         uint16_t octets_per_frame;
28810277393SMatthias Ringwald     } variants[6];
28910277393SMatthias Ringwald } codec_configurations[] = {
29010277393SMatthias Ringwald     {
29110277393SMatthias Ringwald         8000, 0x01, 2,
29210277393SMatthias Ringwald         {
2932fd68da2SMatthias Ringwald             {  "8_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 26},
2942fd68da2SMatthias Ringwald             {  "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30}
29510277393SMatthias Ringwald         }
29610277393SMatthias Ringwald     },
29710277393SMatthias Ringwald     {
29810277393SMatthias Ringwald        16000, 0x03, 2,
29910277393SMatthias Ringwald        {
3002fd68da2SMatthias Ringwald             {  "16_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 30},
3012fd68da2SMatthias Ringwald             {  "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40}
30210277393SMatthias Ringwald        }
30310277393SMatthias Ringwald     },
30410277393SMatthias Ringwald     {
30510277393SMatthias Ringwald         24000, 0x05, 2,
30610277393SMatthias Ringwald         {
3072fd68da2SMatthias Ringwald             {  "24_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 45},
3082fd68da2SMatthias Ringwald             {  "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60}
30910277393SMatthias Ringwald        }
31010277393SMatthias Ringwald     },
31110277393SMatthias Ringwald     {
31210277393SMatthias Ringwald         32000, 0x06, 2,
31310277393SMatthias Ringwald         {
3142fd68da2SMatthias Ringwald             {  "32_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 60},
3152fd68da2SMatthias Ringwald             {  "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80}
31610277393SMatthias Ringwald         }
31710277393SMatthias Ringwald     },
31810277393SMatthias Ringwald     {
31910277393SMatthias Ringwald         44100, 0x07, 2,
32010277393SMatthias Ringwald         {
3212fd68da2SMatthias Ringwald             { "441_1",  BTSTACK_LC3_FRAME_DURATION_7500US,  97},
3222fd68da2SMatthias Ringwald             { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130}
32310277393SMatthias Ringwald         }
32410277393SMatthias Ringwald     },
32510277393SMatthias Ringwald     {
32610277393SMatthias Ringwald         48000, 0x08, 6,
32710277393SMatthias Ringwald         {
3282fd68da2SMatthias Ringwald             {  "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75},
3292fd68da2SMatthias Ringwald             {  "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100},
3302fd68da2SMatthias Ringwald             {  "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90},
3312fd68da2SMatthias Ringwald             {  "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120},
3322fd68da2SMatthias Ringwald             {  "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117},
3332fd68da2SMatthias Ringwald             {  "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155}
33410277393SMatthias Ringwald         }
33510277393SMatthias Ringwald     },
33610277393SMatthias Ringwald };
33710277393SMatthias Ringwald 
33810277393SMatthias Ringwald static void show_usage(void);
33910277393SMatthias Ringwald 
34010277393SMatthias Ringwald static void print_config(void) {
341ac95ea81SMatthias Ringwald     printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n",
34210277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].name,
34310277393SMatthias Ringwald            num_bis,
34410277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].samplingrate_hz,
3452fd68da2SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
34610277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame,
347ac95ea81SMatthias Ringwald            audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : "");
34810277393SMatthias Ringwald }
34910277393SMatthias Ringwald 
35010277393SMatthias Ringwald static void setup_lc3_encoder(void){
35110277393SMatthias Ringwald     uint8_t channel;
35210277393SMatthias Ringwald     for (channel = 0 ; channel < num_bis ; channel++){
353e40ee29aSMatthias Ringwald         btstack_lc3_encoder_google_t * context = &encoder_contexts[channel];
354e40ee29aSMatthias Ringwald         lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
355da364eecSMatthias Ringwald         lc3_encoder->configure(context, sampling_frequency_hz, frame_duration, octets_per_frame);
35610277393SMatthias Ringwald     }
357dc0d751cSMatthias Ringwald     number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration);
35810277393SMatthias Ringwald     btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
35910277393SMatthias Ringwald     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
3602fd68da2SMatthias Ringwald            sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
36110277393SMatthias Ringwald            number_samples_per_frame, octets_per_frame);
36210277393SMatthias Ringwald }
36310277393SMatthias Ringwald 
36410277393SMatthias Ringwald static void setup_mod_player(void){
36510277393SMatthias Ringwald     if (!hxcmod_initialized) {
36610277393SMatthias Ringwald         hxcmod_initialized = hxcmod_init(&mod_context);
36710277393SMatthias Ringwald         btstack_assert(hxcmod_initialized != 0);
36810277393SMatthias Ringwald     }
36910277393SMatthias Ringwald     hxcmod_unload(&mod_context);
37010277393SMatthias Ringwald     hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1);
37110277393SMatthias Ringwald     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
37210277393SMatthias Ringwald }
37310277393SMatthias Ringwald 
37410277393SMatthias Ringwald static void generate_audio(void){
37510277393SMatthias Ringwald     uint32_t start_ms = btstack_run_loop_get_time_ms();
37610277393SMatthias Ringwald     uint16_t sample;
37710277393SMatthias Ringwald     switch (audio_source) {
37810277393SMatthias Ringwald         case AUDIO_SOURCE_SINE:
37910277393SMatthias Ringwald             // generate sine wave for all channels
38010277393SMatthias Ringwald             for (sample = 0 ; sample < number_samples_per_frame ; sample++){
38110277393SMatthias Ringwald                 uint8_t channel;
38210277393SMatthias Ringwald                 for (channel = 0; channel < num_bis; channel++) {
38310277393SMatthias Ringwald                     int16_t value = sine_int16[sine_phases[channel]] / 4;
384c3e2434dSMatthias Ringwald                     pcm[sample * num_bis + channel] = value;
38510277393SMatthias Ringwald                     sine_phases[channel] += sine_step * (1+channel);    // second channel, double frequency
38610277393SMatthias Ringwald                     if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) {
38710277393SMatthias Ringwald                         sine_phases[channel] = 0;
38810277393SMatthias Ringwald                     }
38910277393SMatthias Ringwald                 }
39010277393SMatthias Ringwald             }
39110277393SMatthias Ringwald             break;
39210277393SMatthias Ringwald         case AUDIO_SOURCE_MODPLAYER:
39310277393SMatthias Ringwald             // mod player configured for stereo
394c3e2434dSMatthias Ringwald             hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf);
39510277393SMatthias Ringwald             if (num_bis == 1) {
39610277393SMatthias Ringwald                 // stereo -> mono
397c3e2434dSMatthias Ringwald                 uint16_t i;
39810277393SMatthias Ringwald                 for (i=0;i<number_samples_per_frame;i++){
399c3e2434dSMatthias Ringwald                     pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2);
40010277393SMatthias Ringwald                 }
40110277393SMatthias Ringwald             }
40210277393SMatthias Ringwald             break;
40310277393SMatthias Ringwald         default:
40410277393SMatthias Ringwald             btstack_unreachable();
40510277393SMatthias Ringwald             break;
40610277393SMatthias Ringwald     }
40710277393SMatthias Ringwald     time_generation_ms = btstack_run_loop_get_time_ms() - start_ms;
40810277393SMatthias Ringwald     iso_frame_counter++;
40910277393SMatthias Ringwald }
41010277393SMatthias Ringwald 
4113f485d09SMatthias Ringwald static void encode(uint8_t bis_index){
4123f485d09SMatthias Ringwald     // encode as lc3
413da364eecSMatthias Ringwald     lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES]);
4143f485d09SMatthias Ringwald }
4153f485d09SMatthias Ringwald 
4163f485d09SMatthias Ringwald 
4173f485d09SMatthias Ringwald static void send_iso_packet(uint8_t bis_index) {
41810277393SMatthias Ringwald 
41910277393SMatthias Ringwald #ifdef COUNT_MODE
42010277393SMatthias Ringwald     if (bis_index == 0) {
42110277393SMatthias Ringwald         uint32_t now = btstack_run_loop_get_time_ms();
42210277393SMatthias Ringwald         if (send_last_ms != 0) {
42310277393SMatthias Ringwald             uint16_t send_interval_ms = now - send_last_ms;
42410277393SMatthias Ringwald             if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) {
42510277393SMatthias Ringwald                 printf("ERROR: send interval %u\n", send_interval_ms);
42610277393SMatthias Ringwald             } else {
42710277393SMatthias Ringwald                 send_time_bins[send_interval_ms]++;
42810277393SMatthias Ringwald             }
42910277393SMatthias Ringwald         }
43010277393SMatthias Ringwald         send_last_ms = now;
43110277393SMatthias Ringwald     }
43210277393SMatthias Ringwald #endif
43310277393SMatthias Ringwald     bool ok = hci_reserve_packet_buffer();
43410277393SMatthias Ringwald     btstack_assert(ok);
43510277393SMatthias Ringwald     uint8_t * buffer = hci_get_outgoing_packet_buffer();
43610277393SMatthias Ringwald     // complete SDU, no TimeStamp
43710277393SMatthias Ringwald     little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12));
43810277393SMatthias Ringwald     // len
43910277393SMatthias Ringwald     little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame);
44010277393SMatthias Ringwald     // TimeStamp if TS flag is set
44110277393SMatthias Ringwald     // packet seq nr
44210277393SMatthias Ringwald     little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]);
44310277393SMatthias Ringwald     // iso sdu len
44410277393SMatthias Ringwald     little_endian_store_16(buffer, 6, octets_per_frame);
44510277393SMatthias Ringwald #ifdef COUNT_MODE
44610277393SMatthias Ringwald     // test data: bis_index, counter
44710277393SMatthias Ringwald     buffer[8] = bis_index;
44810277393SMatthias Ringwald     memset(&buffer[9], iso_frame_counter, octets_per_frame - 1);
44910277393SMatthias Ringwald #else
4503f485d09SMatthias Ringwald     // copy encoded payload
4513f485d09SMatthias Ringwald     memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame);
45210277393SMatthias Ringwald #endif
45310277393SMatthias Ringwald     // send
45410277393SMatthias Ringwald     hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame);
45510277393SMatthias Ringwald 
4563f485d09SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO
45710277393SMatthias Ringwald     if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) {
45810277393SMatthias Ringwald         printf("Encoding time: %u\n", time_generation_ms);
45910277393SMatthias Ringwald     }
4603f485d09SMatthias Ringwald #endif
46110277393SMatthias Ringwald 
46210277393SMatthias Ringwald     packet_sequence_numbers[bis_index]++;
46310277393SMatthias Ringwald }
46410277393SMatthias Ringwald 
4650be46310SMatthias Ringwald static void generate_audio_and_encode(void){
46610277393SMatthias Ringwald     uint8_t i;
46710277393SMatthias Ringwald     generate_audio();
46810277393SMatthias Ringwald     for (i = 0; i < num_bis; i++) {
4690be46310SMatthias Ringwald         encode(i);
47010277393SMatthias Ringwald         bis_has_data[i] = true;
47110277393SMatthias Ringwald     }
47210277393SMatthias Ringwald }
47310277393SMatthias Ringwald 
47444959aebSMatthias Ringwald static void setup_advertising() {
47544959aebSMatthias Ringwald     gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle);
47644959aebSMatthias Ringwald     gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data);
47744959aebSMatthias Ringwald     gap_periodic_advertising_set_params(adv_handle, &periodic_params);
47844959aebSMatthias Ringwald     switch(num_bis){
47944959aebSMatthias Ringwald         case 1:
48044959aebSMatthias Ringwald             gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1);
48144959aebSMatthias Ringwald             printf("BASE: ");
48244959aebSMatthias Ringwald             printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1));
48344959aebSMatthias Ringwald             break;
48444959aebSMatthias Ringwald         case 2:
48544959aebSMatthias Ringwald             gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2);
48644959aebSMatthias Ringwald             printf("BASE: ");
48744959aebSMatthias Ringwald             printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2));
48844959aebSMatthias Ringwald             break;
48944959aebSMatthias Ringwald         default:
49044959aebSMatthias Ringwald             btstack_unreachable();
49144959aebSMatthias Ringwald             break;
49244959aebSMatthias Ringwald     }
49344959aebSMatthias Ringwald     gap_periodic_advertising_start(adv_handle, 0);
49444959aebSMatthias Ringwald     gap_extended_advertising_start(adv_handle, 0, 0);
49544959aebSMatthias Ringwald }
49644959aebSMatthias Ringwald 
49744959aebSMatthias Ringwald static void setup_big(void){
498cd0bedb1SMatthias Ringwald     // Create BIG
499cd0bedb1SMatthias Ringwald     big_params.big_handle = 0;
500cd0bedb1SMatthias Ringwald     big_params.advertising_handle = adv_handle;
501cd0bedb1SMatthias Ringwald     big_params.num_bis = num_bis;
502cd0bedb1SMatthias Ringwald     big_params.max_sdu = octets_per_frame;
503cd0bedb1SMatthias Ringwald     big_params.max_transport_latency_ms = 31;
504cd0bedb1SMatthias Ringwald     big_params.rtn = 2;
505cd0bedb1SMatthias Ringwald     big_params.phy = 2;
506cd0bedb1SMatthias Ringwald     big_params.packing = 0;
507ac95ea81SMatthias Ringwald     big_params.encryption = encryption;
508ac95ea81SMatthias Ringwald     if (encryption) {
509ac95ea81SMatthias Ringwald         memcpy(big_params.broadcast_code, &broadcast_code[0], 16);
510ac95ea81SMatthias Ringwald     } else {
511cd0bedb1SMatthias Ringwald         memset(big_params.broadcast_code, 0, 16);
512ac95ea81SMatthias Ringwald     }
513cd0bedb1SMatthias Ringwald     if (sampling_frequency_hz == 44100){
514cd0bedb1SMatthias Ringwald         // same config as for 48k -> frame is longer by 48/44.1
515cd0bedb1SMatthias Ringwald         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884;
516cd0bedb1SMatthias Ringwald         big_params.framing = 1;
517cd0bedb1SMatthias Ringwald     } else {
518cd0bedb1SMatthias Ringwald         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000;
519cd0bedb1SMatthias Ringwald         big_params.framing = 0;
520cd0bedb1SMatthias Ringwald     }
521cd0bedb1SMatthias Ringwald     app_state = APP_W4_CREATE_BIG_COMPLETE;
522cd0bedb1SMatthias Ringwald     gap_big_create(&big_storage, &big_params);
523cd0bedb1SMatthias Ringwald }
524cd0bedb1SMatthias Ringwald 
52556c77a86SMatthias Ringwald 
52656c77a86SMatthias Ringwald static void start_broadcast() {// use values from table
52756c77a86SMatthias Ringwald     sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz;
52856c77a86SMatthias Ringwald     octets_per_frame      = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame;
52956c77a86SMatthias Ringwald     frame_duration        = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration;
53056c77a86SMatthias Ringwald 
53156c77a86SMatthias Ringwald     // get num samples per frame
53256c77a86SMatthias Ringwald     setup_lc3_encoder();
53356c77a86SMatthias Ringwald 
53456c77a86SMatthias Ringwald     // update BASEs
53556c77a86SMatthias Ringwald     periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index;
53656c77a86SMatthias Ringwald     periodic_adv_data_1[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;
53756c77a86SMatthias Ringwald     little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame);
53856c77a86SMatthias Ringwald 
53956c77a86SMatthias Ringwald     periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index;
54056c77a86SMatthias Ringwald     periodic_adv_data_2[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;
54156c77a86SMatthias Ringwald     little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame);
54256c77a86SMatthias Ringwald 
54356c77a86SMatthias Ringwald     // setup mod player
54456c77a86SMatthias Ringwald     setup_mod_player();
54556c77a86SMatthias Ringwald 
54656c77a86SMatthias Ringwald     // setup sine generator
54756c77a86SMatthias Ringwald     if (sampling_frequency_hz == 44100){
54856c77a86SMatthias Ringwald         sine_step = 2;
54956c77a86SMatthias Ringwald     } else {
55056c77a86SMatthias Ringwald         sine_step = 96000 / sampling_frequency_hz;
55156c77a86SMatthias Ringwald     }
55256c77a86SMatthias Ringwald 
55356c77a86SMatthias Ringwald     // setup extended and periodic advertising
55456c77a86SMatthias Ringwald     setup_advertising();
55556c77a86SMatthias Ringwald 
55656c77a86SMatthias Ringwald     // setup big
55756c77a86SMatthias Ringwald     setup_big();
55856c77a86SMatthias Ringwald }
55956c77a86SMatthias Ringwald 
56010277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
56110277393SMatthias Ringwald     UNUSED(channel);
56210277393SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
5630be46310SMatthias Ringwald     uint8_t bis_index;
56410277393SMatthias Ringwald 
56510277393SMatthias Ringwald     switch (packet[0]) {
56610277393SMatthias Ringwald         case BTSTACK_EVENT_STATE:
56710277393SMatthias Ringwald             switch(btstack_event_state_get_state(packet)) {
56810277393SMatthias Ringwald                 case HCI_STATE_WORKING:
56956c77a86SMatthias Ringwald #ifdef ENABLE_DEMO_MODE
57056c77a86SMatthias Ringwald                     // start broadcast automatically, mod player, 48_5_1
57156c77a86SMatthias Ringwald                     num_bis = 1;
57256c77a86SMatthias Ringwald                     menu_sampling_frequency = 5;
57356c77a86SMatthias Ringwald                     menu_variant = 4;
57456c77a86SMatthias Ringwald                     start_broadcast();
57556c77a86SMatthias Ringwald #else
57610277393SMatthias Ringwald                     show_usage();
57710277393SMatthias Ringwald                     printf("Please select sample frequency and variation, then start broadcast\n");
57856c77a86SMatthias Ringwald #endif
57910277393SMatthias Ringwald                     break;
58010277393SMatthias Ringwald                 case HCI_STATE_OFF:
58110277393SMatthias Ringwald                     printf("Goodbye\n");
58210277393SMatthias Ringwald                     exit(0);
58310277393SMatthias Ringwald                     break;
58410277393SMatthias Ringwald                 default:
58510277393SMatthias Ringwald                     break;
58610277393SMatthias Ringwald             }
58710277393SMatthias Ringwald             break;
588cd0bedb1SMatthias Ringwald         case HCI_EVENT_META_GAP:
589cd0bedb1SMatthias Ringwald             switch (hci_event_gap_meta_get_subevent_code(packet)){
5900be46310SMatthias Ringwald                 case GAP_SUBEVENT_BIG_CREATED:
591cd0bedb1SMatthias Ringwald                     printf("BIG Created with BIS Connection handles: \n");
5920be46310SMatthias Ringwald                     for (bis_index=0;bis_index<num_bis;bis_index++){
5930be46310SMatthias Ringwald                         bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index);
5940be46310SMatthias Ringwald                         printf("0x%04x ", bis_con_handles[bis_index]);
59510277393SMatthias Ringwald                     }
59644959aebSMatthias Ringwald 
597cd0bedb1SMatthias Ringwald                     app_state = APP_STREAMING;
59810277393SMatthias Ringwald                     printf("Start streaming\n");
5990be46310SMatthias Ringwald                     generate_audio_and_encode();
6000be46310SMatthias Ringwald                     hci_request_bis_can_send_now_events(big_params.big_handle);
60110277393SMatthias Ringwald                     break;
60210277393SMatthias Ringwald                 default:
60310277393SMatthias Ringwald                     break;
60410277393SMatthias Ringwald             }
60510277393SMatthias Ringwald             break;
6060be46310SMatthias Ringwald         case HCI_EVENT_BIS_CAN_SEND_NOW:
6070d718107SMatthias Ringwald             bis_index = hci_event_bis_can_send_now_get_bis_index(packet);
6080d718107SMatthias Ringwald             send_iso_packet(bis_index);
6090be46310SMatthias Ringwald             bis_index++;
6100be46310SMatthias Ringwald             if (bis_index == num_bis){
6110be46310SMatthias Ringwald                 generate_audio_and_encode();
6120be46310SMatthias Ringwald                 hci_request_bis_can_send_now_events(big_params.big_handle);
61310277393SMatthias Ringwald             }
61410277393SMatthias Ringwald             break;
61510277393SMatthias Ringwald         default:
61610277393SMatthias Ringwald             break;
61710277393SMatthias Ringwald     }
61810277393SMatthias Ringwald }
61910277393SMatthias Ringwald 
62010277393SMatthias Ringwald static void show_usage(void){
62110277393SMatthias Ringwald     printf("\n--- LE Audio Broadcast Source Test Console ---\n");
62210277393SMatthias Ringwald     print_config();
62310277393SMatthias Ringwald     printf("---\n");
62410277393SMatthias Ringwald     printf("c - toggle channels\n");
625ac95ea81SMatthias Ringwald     printf("e - toggle encryption\n");
62610277393SMatthias Ringwald     printf("f - next sampling frequency\n");
62710277393SMatthias Ringwald     printf("v - next codec variant\n");
62810277393SMatthias Ringwald     printf("t - toggle sine / modplayer\n");
62910277393SMatthias Ringwald     printf("s - start broadcast\n");
63010277393SMatthias Ringwald     printf("x - shutdown\n");
63110277393SMatthias Ringwald     printf("---\n");
63210277393SMatthias Ringwald }
63310277393SMatthias Ringwald static void stdin_process(char c){
63410277393SMatthias Ringwald     switch (c){
63510277393SMatthias Ringwald         case 'c':
63610277393SMatthias Ringwald             if (app_state != APP_IDLE){
63710277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
63810277393SMatthias Ringwald                 break;
63910277393SMatthias Ringwald             }
64010277393SMatthias Ringwald             num_bis = 3 - num_bis;
64110277393SMatthias Ringwald             print_config();
64210277393SMatthias Ringwald             break;
643ac95ea81SMatthias Ringwald         case 'e':
644ac95ea81SMatthias Ringwald             if (app_state != APP_IDLE){
645ac95ea81SMatthias Ringwald                 printf("Encryption can only be changed in idle state\n");
646ac95ea81SMatthias Ringwald                 break;
647ac95ea81SMatthias Ringwald             }
648ac95ea81SMatthias Ringwald             encryption = 1 - encryption;
649ac95ea81SMatthias Ringwald             print_config();
650ac95ea81SMatthias Ringwald             break;
65110277393SMatthias Ringwald         case 'f':
65210277393SMatthias Ringwald             if (app_state != APP_IDLE){
65310277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
65410277393SMatthias Ringwald                 break;
65510277393SMatthias Ringwald             }
65610277393SMatthias Ringwald             menu_sampling_frequency++;
65710277393SMatthias Ringwald             if (menu_sampling_frequency >= 6){
65810277393SMatthias Ringwald                 menu_sampling_frequency = 0;
65910277393SMatthias Ringwald             }
66010277393SMatthias Ringwald             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
66110277393SMatthias Ringwald                 menu_variant = 0;
66210277393SMatthias Ringwald             }
66310277393SMatthias Ringwald             print_config();
66410277393SMatthias Ringwald             break;
66510277393SMatthias Ringwald         case 'v':
66610277393SMatthias Ringwald             if (app_state != APP_IDLE){
66710277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
66810277393SMatthias Ringwald                 break;
66910277393SMatthias Ringwald             }
67010277393SMatthias Ringwald             menu_variant++;
67110277393SMatthias Ringwald             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
67210277393SMatthias Ringwald                 menu_variant = 0;
67310277393SMatthias Ringwald             }
67410277393SMatthias Ringwald             print_config();
67510277393SMatthias Ringwald             break;
67610277393SMatthias Ringwald         case 'x':
67710277393SMatthias Ringwald #ifdef COUNT_MODE
67810277393SMatthias Ringwald             printf("Send statistic:\n");
67910277393SMatthias Ringwald             {
68010277393SMatthias Ringwald                 uint16_t i;
68110277393SMatthias Ringwald                 for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){
68210277393SMatthias Ringwald                     printf("%2u: %5u\n", i, send_time_bins[i]);
68310277393SMatthias Ringwald                 }
68410277393SMatthias Ringwald             }
68510277393SMatthias Ringwald #endif
68610277393SMatthias Ringwald             printf("Shutdown...\n");
687b9b9e477SMatthias Ringwald             app_state = APP_W4_POWER_OFF;
68810277393SMatthias Ringwald             hci_power_control(HCI_POWER_OFF);
68910277393SMatthias Ringwald             break;
69010277393SMatthias Ringwald         case 's':
69110277393SMatthias Ringwald             if (app_state != APP_IDLE){
69210277393SMatthias Ringwald                 printf("Cannot start broadcast - not in idle state\n");
69310277393SMatthias Ringwald                 break;
69410277393SMatthias Ringwald             }
69556c77a86SMatthias Ringwald             start_broadcast();
69610277393SMatthias Ringwald             break;
69710277393SMatthias Ringwald         case 't':
69810277393SMatthias Ringwald             audio_source = 1 - audio_source;
69910277393SMatthias Ringwald             print_config();
70010277393SMatthias Ringwald             break;
70110277393SMatthias Ringwald         case '\n':
70210277393SMatthias Ringwald         case '\r':
70310277393SMatthias Ringwald             break;
70410277393SMatthias Ringwald         default:
70510277393SMatthias Ringwald             show_usage();
70610277393SMatthias Ringwald             break;
70710277393SMatthias Ringwald     }
70810277393SMatthias Ringwald }
70910277393SMatthias Ringwald 
71010277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]);
71110277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){
71210277393SMatthias Ringwald     (void) argv;
71310277393SMatthias Ringwald     (void) argc;
71410277393SMatthias Ringwald 
71510277393SMatthias Ringwald     // register for HCI events
71610277393SMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
71710277393SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
71810277393SMatthias Ringwald 
71910277393SMatthias Ringwald     // turn on!
72010277393SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
72110277393SMatthias Ringwald 
72210277393SMatthias Ringwald     btstack_stdin_setup(stdin_process);
72310277393SMatthias Ringwald     return 0;
72410277393SMatthias Ringwald }
725