xref: /btstack/test/le_audio/le_audio_broadcast_source.c (revision 4a06e23f2ef7514b1ba30fc33934c68296d62919)
1 /*
2  * Copyright (C) 2022 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "le_audio_broadcast_source.c"
39 
40 /*
41  * LE Audio Broadcast Source
42  */
43 
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <btstack_debug.h>
48 
49 #include "bluetooth_data_types.h"
50 #include "btstack_stdin.h"
51 #include "btstack_event.h"
52 #include "btstack_run_loop.h"
53 #include "gap.h"
54 #include "hci.h"
55 #include "hci_cmd.h"
56 #include "hci_dump.h"
57 #include "btstack_lc3.h"
58 #include "btstack_lc3_google.h"
59 #include "le-audio/le_audio_base_builder.h"
60 
61 #include "hxcmod.h"
62 #include "mods/mod.h"
63 
64 // PTS mode
65 // #define PTS_MODE
66 
67 // Count mode - send packet count as test data for manual analysis
68 // #define COUNT_MODE
69 
70 // max config
71 #define MAX_NUM_BIS 2
72 #define MAX_SAMPLES_PER_FRAME 480
73 #define MAX_LC3_FRAME_BYTES   155
74 
75 static const uint8_t adv_sid = 0;
76 
77 static le_advertising_set_t le_advertising_set;
78 
79 static const le_extended_advertising_parameters_t extended_params = {
80         .advertising_event_properties = 0,
81         .primary_advertising_interval_min = 0x4b0, // 750 ms
82         .primary_advertising_interval_max = 0x4b0, // 750 ms
83         .primary_advertising_channel_map = 7,
84         .own_address_type = 0,
85         .peer_address_type = 0,
86         .peer_address =  { 0 },
87         .advertising_filter_policy = 0,
88         .advertising_tx_power = 10, // 10 dBm
89         .primary_advertising_phy = 1, // LE 1M PHY
90         .secondary_advertising_max_skip = 0,
91         .secondary_advertising_phy = 1, // LE 1M PHY
92         .advertising_sid = adv_sid,
93         .scan_request_notification_enable = 0,
94 };
95 
96 // Random Broadcast ID, valid for lifetime of BIG
97 #define BROADCAST_ID (0x112233u)
98 
99 static const uint8_t extended_adv_data[] = {
100         // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID
101         6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18,
102         BROADCAST_ID >> 16,
103         (BROADCAST_ID >> 8) & 0xff,
104         BROADCAST_ID & 0xff,
105         // name
106 #ifdef PTS_MODE
107         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x'
108 #elif defined(COUNT_MODE)
109         6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T'
110 #else
111         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e'
112 #endif
113 };
114 
115 static const le_periodic_advertising_parameters_t periodic_params = {
116         .periodic_advertising_interval_min = 0x258, // 375 ms
117         .periodic_advertising_interval_max = 0x258, // 375 ms
118         .periodic_advertising_properties = 0
119 };
120 
121 // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz
122 static const int16_t sine_int16[] = {
123         0,    643,   1286,   1929,   2571,   3212,   3851,   4489,   5126,   5760,
124         6393,   7022,   7649,   8273,   8894,   9512,  10126,  10735,  11341,  11943,
125         12539,  13131,  13718,  14300,  14876,  15446,  16011,  16569,  17121,  17666,
126         18204,  18736,  19260,  19777,  20286,  20787,  21280,  21766,  22242,  22710,
127         23170,  23620,  24062,  24494,  24916,  25329,  25732,  26126,  26509,  26882,
128         27245,  27597,  27938,  28269,  28589,  28898,  29196,  29482,  29757,  30021,
129         30273,  30513,  30742,  30958,  31163,  31356,  31537,  31705,  31862,  32006,
130         32137,  32257,  32364,  32458,  32540,  32609,  32666,  32710,  32742,  32761,
131         32767,  32761,  32742,  32710,  32666,  32609,  32540,  32458,  32364,  32257,
132         32137,  32006,  31862,  31705,  31537,  31356,  31163,  30958,  30742,  30513,
133         30273,  30021,  29757,  29482,  29196,  28898,  28589,  28269,  27938,  27597,
134         27245,  26882,  26509,  26126,  25732,  25329,  24916,  24494,  24062,  23620,
135         23170,  22710,  22242,  21766,  21280,  20787,  20286,  19777,  19260,  18736,
136         18204,  17666,  17121,  16569,  16011,  15446,  14876,  14300,  13718,  13131,
137         12539,  11943,  11341,  10735,  10126,   9512,   8894,   8273,   7649,   7022,
138         6393,   5760,   5126,   4489,   3851,   3212,   2571,   1929,   1286,    643,
139         0,   -643,  -1286,  -1929,  -2571,  -3212,  -3851,  -4489,  -5126,  -5760,
140         -6393,  -7022,  -7649,  -8273,  -8894,  -9512, -10126, -10735, -11341, -11943,
141         -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666,
142         -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710,
143         -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882,
144         -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021,
145         -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006,
146         -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761,
147         -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257,
148         -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513,
149         -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597,
150         -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620,
151         -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736,
152         -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131,
153         -12539, -11943, -11341, -10735, -10126,  -9512,  -8894,  -8273,  -7649,  -7022,
154         -6393,  -5760,  -5126,  -4489,  -3851,  -3212,  -2571,  -1929,  -1286,   -643,
155 };
156 
157 static bd_addr_t remote;
158 static const char * remote_addr_string = "00:1B:DC:08:E2:72";
159 
160 static btstack_packet_callback_registration_t hci_event_callback_registration;
161 static uint8_t period_adv_data[255];
162 static uint16_t period_adv_data_len;
163 
164 static uint8_t adv_handle = 0;
165 static unsigned int     next_bis_index;
166 static hci_con_handle_t bis_con_handles[MAX_NUM_BIS];
167 static uint16_t packet_sequence_numbers[MAX_NUM_BIS];
168 static uint8_t framed_pdus;
169 static bool bis_can_send[MAX_NUM_BIS];
170 static bool bis_has_data[MAX_NUM_BIS];
171 static uint8_t iso_frame_counter;
172 static uint16_t frame_duration_us;
173 
174 static le_audio_big_t big_storage;
175 static le_audio_big_params_t big_params;
176 
177 // time stamping
178 #ifdef COUNT_MODE
179 #define MAX_PACKET_INTERVAL_BINS_MS 50
180 static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS];
181 static uint32_t send_last_ms;
182 #endif
183 
184 // lc3 codec config
185 static uint16_t sampling_frequency_hz;
186 static btstack_lc3_frame_duration_t frame_duration;
187 static uint16_t number_samples_per_frame;
188 static uint16_t octets_per_frame;
189 static uint8_t  num_bis = 1;
190 
191 // lc3 encoder
192 static const btstack_lc3_encoder_t * lc3_encoder;
193 static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS];
194 static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME];
195 static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES];
196 static uint32_t time_generation_ms;
197 
198 // codec menu
199 static uint8_t menu_sampling_frequency;
200 static uint8_t menu_variant;
201 
202 // mod player
203 static int hxcmod_initialized;
204 static modcontext mod_context;
205 static tracker_buffer_state trkbuf;
206 
207 // sine generator
208 static uint8_t  sine_step;
209 static uint16_t sine_phases[MAX_NUM_BIS];
210 
211 // encryption
212 static uint8_t encryption = 0;
213 static uint8_t broadcast_code [] = {0x01, 0x02, 0x68, 0x05, 0x53, 0xF1, 0x41, 0x5A, 0xA2, 0x65, 0xBB, 0xAF, 0xC6, 0xEA, 0x03, 0xB8, };
214 
215 // audio producer
216 static enum {
217     AUDIO_SOURCE_SINE,
218     AUDIO_SOURCE_MODPLAYER
219 } audio_source = AUDIO_SOURCE_MODPLAYER;
220 
221 static enum {
222     APP_IDLE,
223     APP_W4_CREATE_BIG_COMPLETE,
224     APP_STREAMING,
225     APP_W4_POWER_OFF,
226 } app_state = APP_IDLE;
227 
228 // enumerate default codec configs
229 static struct {
230     uint16_t samplingrate_hz;
231     uint8_t  samplingrate_index;
232     uint8_t  num_variants;
233     struct {
234         const char * name;
235         btstack_lc3_frame_duration_t frame_duration;
236         uint16_t octets_per_frame;
237     } variants[6];
238 } codec_configurations[] = {
239     {
240         8000, 0x01, 2,
241         {
242             {  "8_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 26},
243             {  "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30}
244         }
245     },
246     {
247        16000, 0x03, 2,
248        {
249             {  "16_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 30},
250             {  "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40}
251        }
252     },
253     {
254         24000, 0x05, 2,
255         {
256             {  "24_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 45},
257             {  "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60}
258        }
259     },
260     {
261         32000, 0x06, 2,
262         {
263             {  "32_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 60},
264             {  "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80}
265         }
266     },
267     {
268         44100, 0x07, 2,
269         {
270             { "441_1",  BTSTACK_LC3_FRAME_DURATION_7500US,  97},
271             { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130}
272         }
273     },
274     {
275         48000, 0x08, 6,
276         {
277             {  "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75},
278             {  "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100},
279             {  "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90},
280             {  "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120},
281             {  "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117},
282             {  "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155}
283         }
284     },
285 };
286 
287 static void show_usage(void);
288 
289 static void print_config(void) {
290     printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n",
291            codec_configurations[menu_sampling_frequency].variants[menu_variant].name,
292            num_bis,
293            codec_configurations[menu_sampling_frequency].samplingrate_hz,
294            codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
295            codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame,
296            audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : "");
297 }
298 
299 static void setup_lc3_encoder(void){
300     uint8_t channel;
301     for (channel = 0 ; channel < num_bis ; channel++){
302         btstack_lc3_encoder_google_t * context = &encoder_contexts[channel];
303         lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
304         lc3_encoder->configure(context, sampling_frequency_hz, frame_duration, octets_per_frame);
305     }
306     number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration);
307     btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
308     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
309            sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
310            number_samples_per_frame, octets_per_frame);
311 }
312 
313 static void setup_mod_player(void){
314     if (!hxcmod_initialized) {
315         hxcmod_initialized = hxcmod_init(&mod_context);
316         btstack_assert(hxcmod_initialized != 0);
317     }
318     hxcmod_unload(&mod_context);
319     hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1);
320     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
321 }
322 
323 static void generate_audio(void){
324     uint32_t start_ms = btstack_run_loop_get_time_ms();
325     uint16_t sample;
326     switch (audio_source) {
327         case AUDIO_SOURCE_SINE:
328             // generate sine wave for all channels
329             for (sample = 0 ; sample < number_samples_per_frame ; sample++){
330                 uint8_t channel;
331                 for (channel = 0; channel < num_bis; channel++) {
332                     int16_t value = sine_int16[sine_phases[channel]] / 4;
333                     pcm[sample * num_bis + channel] = value;
334                     sine_phases[channel] += sine_step * (1+channel);    // second channel, double frequency
335                     if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) {
336                         sine_phases[channel] = 0;
337                     }
338                 }
339             }
340             break;
341         case AUDIO_SOURCE_MODPLAYER:
342             // mod player configured for stereo
343             hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf);
344             if (num_bis == 1) {
345                 // stereo -> mono
346                 uint16_t i;
347                 for (i=0;i<number_samples_per_frame;i++){
348                     pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2);
349                 }
350             }
351             break;
352         default:
353             btstack_unreachable();
354             break;
355     }
356     time_generation_ms = btstack_run_loop_get_time_ms() - start_ms;
357     iso_frame_counter++;
358 }
359 
360 static void encode(uint8_t bis_index){
361     // encode as lc3
362     lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES]);
363 }
364 
365 
366 static void send_iso_packet(uint8_t bis_index) {
367 
368 #ifdef COUNT_MODE
369     if (bis_index == 0) {
370         uint32_t now = btstack_run_loop_get_time_ms();
371         if (send_last_ms != 0) {
372             uint16_t send_interval_ms = now - send_last_ms;
373             if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) {
374                 printf("ERROR: send interval %u\n", send_interval_ms);
375             } else {
376                 send_time_bins[send_interval_ms]++;
377             }
378         }
379         send_last_ms = now;
380     }
381 #endif
382     bool ok = hci_reserve_packet_buffer();
383     btstack_assert(ok);
384     uint8_t * buffer = hci_get_outgoing_packet_buffer();
385     // complete SDU, no TimeStamp
386     little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12));
387     // len
388     little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame);
389     // TimeStamp if TS flag is set
390     // packet seq nr
391     little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]);
392     // iso sdu len
393     little_endian_store_16(buffer, 6, octets_per_frame);
394 #ifdef COUNT_MODE
395     // test data: bis_index, counter
396     buffer[8] = bis_index;
397     memset(&buffer[9], iso_frame_counter, octets_per_frame - 1);
398 #else
399     // copy encoded payload
400     memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame);
401 #endif
402     // send
403     hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame);
404 
405 #ifdef HAVE_POSIX_FILE_IO
406     if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) {
407         printf("Encoding time: %u\n", time_generation_ms);
408     }
409 #endif
410 
411     packet_sequence_numbers[bis_index]++;
412 }
413 
414 static void generate_audio_and_encode(void){
415     uint8_t i;
416     generate_audio();
417     for (i = 0; i < num_bis; i++) {
418         encode(i);
419         bis_has_data[i] = true;
420     }
421 }
422 
423 static void setup_advertising() {
424     gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle);
425     gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data);
426     gap_periodic_advertising_set_params(adv_handle, &periodic_params);
427     gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data);
428     gap_periodic_advertising_start(adv_handle, 0);
429     gap_extended_advertising_start(adv_handle, 0, 0);
430 }
431 
432 static void setup_big(void){
433     // Create BIG
434     big_params.big_handle = 0;
435     big_params.advertising_handle = adv_handle;
436     big_params.num_bis = num_bis;
437     big_params.max_sdu = octets_per_frame;
438     big_params.max_transport_latency_ms = 31;
439     big_params.rtn = 2;
440     big_params.phy = 2;
441     big_params.packing = 0;
442     big_params.encryption = encryption;
443     if (encryption) {
444         memcpy(big_params.broadcast_code, &broadcast_code[0], 16);
445     } else {
446         memset(big_params.broadcast_code, 0, 16);
447     }
448     if (sampling_frequency_hz == 44100){
449         // same config as for 48k -> frame is longer by 48/44.1
450         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884;
451         big_params.framing = 1;
452     } else {
453         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000;
454         big_params.framing = 0;
455     }
456     app_state = APP_W4_CREATE_BIG_COMPLETE;
457     gap_big_create(&big_storage, &big_params);
458 }
459 
460 
461 static void start_broadcast() {// use values from table
462     sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz;
463     octets_per_frame      = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame;
464     frame_duration        = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration;
465 
466     // get num samples per frame
467     setup_lc3_encoder();
468 
469     // setup base
470     uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 };
471     uint8_t subgroup_codec_specific_configuration[] = {
472             0x02, 0x01, 0x01,
473             0x02, 0x02, 0x01,
474             0x03, 0x04, 0x1E, 0x00,
475     };
476     subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index;
477     subgroup_codec_specific_configuration[5] =  (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;;
478     uint8_t subgroup_metadata[] = {
479             0x03, 0x02, 0x04, 0x00, // Metadata[i]
480     };
481     little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame);
482     uint8_t bis_codec_specific_configuration_1[] = {
483             0x05, 0x03, 0x01, 0x00, 0x00, 0x00
484     };
485     uint8_t bis_codec_specific_configuration_2[] = {
486             0x05, 0x03, 0x02, 0x00, 0x00, 0x00
487     };
488     base_builder_t builder;
489     le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40);
490     le_audio_base_builder_add_subgroup(&builder, codec_id,
491                                        sizeof(subgroup_codec_specific_configuration),
492                                        subgroup_codec_specific_configuration,
493                                        sizeof(subgroup_metadata), subgroup_metadata);
494     le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1),
495                                   bis_codec_specific_configuration_1);
496     if (num_bis == 2){
497         le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2),
498                                       bis_codec_specific_configuration_2);
499     }
500     period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder);
501 
502     // setup mod player
503     setup_mod_player();
504 
505     // setup sine generator
506     if (sampling_frequency_hz == 44100){
507         sine_step = 2;
508     } else {
509         sine_step = 96000 / sampling_frequency_hz;
510     }
511 
512     // setup extended and periodic advertising
513     setup_advertising();
514 
515     // setup big
516     setup_big();
517 }
518 
519 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
520     UNUSED(channel);
521     if (packet_type != HCI_EVENT_PACKET) return;
522     uint8_t bis_index;
523 
524     switch (packet[0]) {
525         case BTSTACK_EVENT_STATE:
526             switch(btstack_event_state_get_state(packet)) {
527                 case HCI_STATE_WORKING:
528 #ifdef ENABLE_DEMO_MODE
529                     // start broadcast automatically, mod player, 48_5_1
530                     num_bis = 1;
531                     menu_sampling_frequency = 5;
532                     menu_variant = 4;
533                     start_broadcast();
534 #else
535                     show_usage();
536                     printf("Please select sample frequency and variation, then start broadcast\n");
537 #endif
538                     break;
539                 case HCI_STATE_OFF:
540                     printf("Goodbye\n");
541                     exit(0);
542                     break;
543                 default:
544                     break;
545             }
546             break;
547         case HCI_EVENT_META_GAP:
548             switch (hci_event_gap_meta_get_subevent_code(packet)){
549                 case GAP_SUBEVENT_BIG_CREATED:
550                     printf("BIG Created with BIS Connection handles: \n");
551                     for (bis_index=0;bis_index<num_bis;bis_index++){
552                         bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index);
553                         printf("0x%04x ", bis_con_handles[bis_index]);
554                     }
555 
556                     app_state = APP_STREAMING;
557                     printf("Start streaming\n");
558                     generate_audio_and_encode();
559                     hci_request_bis_can_send_now_events(big_params.big_handle);
560                     break;
561                 default:
562                     break;
563             }
564             break;
565         case HCI_EVENT_BIS_CAN_SEND_NOW:
566             bis_index = hci_event_bis_can_send_now_get_bis_index(packet);
567             send_iso_packet(bis_index);
568             bis_index++;
569             if (bis_index == num_bis){
570                 generate_audio_and_encode();
571                 hci_request_bis_can_send_now_events(big_params.big_handle);
572             }
573             break;
574         default:
575             break;
576     }
577 }
578 
579 static void show_usage(void){
580     printf("\n--- LE Audio Broadcast Source Test Console ---\n");
581     print_config();
582     printf("---\n");
583     printf("c - toggle channels\n");
584     printf("e - toggle encryption\n");
585     printf("f - next sampling frequency\n");
586     printf("v - next codec variant\n");
587     printf("t - toggle sine / modplayer\n");
588     printf("s - start broadcast\n");
589     printf("x - shutdown\n");
590     printf("---\n");
591 }
592 static void stdin_process(char c){
593     switch (c){
594         case 'c':
595             if (app_state != APP_IDLE){
596                 printf("Codec configuration can only be changed in idle state\n");
597                 break;
598             }
599             num_bis = 3 - num_bis;
600             print_config();
601             break;
602         case 'e':
603             if (app_state != APP_IDLE){
604                 printf("Encryption can only be changed in idle state\n");
605                 break;
606             }
607             encryption = 1 - encryption;
608             print_config();
609             break;
610         case 'f':
611             if (app_state != APP_IDLE){
612                 printf("Codec configuration can only be changed in idle state\n");
613                 break;
614             }
615             menu_sampling_frequency++;
616             if (menu_sampling_frequency >= 6){
617                 menu_sampling_frequency = 0;
618             }
619             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
620                 menu_variant = 0;
621             }
622             print_config();
623             break;
624         case 'v':
625             if (app_state != APP_IDLE){
626                 printf("Codec configuration can only be changed in idle state\n");
627                 break;
628             }
629             menu_variant++;
630             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
631                 menu_variant = 0;
632             }
633             print_config();
634             break;
635         case 'x':
636 #ifdef COUNT_MODE
637             printf("Send statistic:\n");
638             {
639                 uint16_t i;
640                 for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){
641                     printf("%2u: %5u\n", i, send_time_bins[i]);
642                 }
643             }
644 #endif
645             printf("Shutdown...\n");
646             app_state = APP_W4_POWER_OFF;
647             hci_power_control(HCI_POWER_OFF);
648             break;
649         case 's':
650             if (app_state != APP_IDLE){
651                 printf("Cannot start broadcast - not in idle state\n");
652                 break;
653             }
654             start_broadcast();
655             break;
656         case 't':
657             audio_source = 1 - audio_source;
658             print_config();
659             break;
660         case '\n':
661         case '\r':
662             break;
663         default:
664             show_usage();
665             break;
666     }
667 }
668 
669 int btstack_main(int argc, const char * argv[]);
670 int btstack_main(int argc, const char * argv[]){
671     (void) argv;
672     (void) argc;
673 
674     // register for HCI events
675     hci_event_callback_registration.callback = &packet_handler;
676     hci_add_event_handler(&hci_event_callback_registration);
677 
678     // turn on!
679     hci_power_control(HCI_POWER_ON);
680 
681     btstack_stdin_setup(stdin_process);
682     return 0;
683 }
684