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_state = APP_IDLE; 226 227 // enumerate default codec configs 228 static struct { 229 uint16_t samplingrate_hz; 230 uint8_t samplingrate_index; 231 uint8_t num_variants; 232 struct { 233 const char * name; 234 btstack_lc3_frame_duration_t frame_duration; 235 uint16_t octets_per_frame; 236 } variants[6]; 237 } codec_configurations[] = { 238 { 239 8000, 0x01, 2, 240 { 241 { "8_1", BTSTACK_LC3_FRAME_DURATION_7500US, 26}, 242 { "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30} 243 } 244 }, 245 { 246 16000, 0x03, 2, 247 { 248 { "16_1", BTSTACK_LC3_FRAME_DURATION_7500US, 30}, 249 { "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40} 250 } 251 }, 252 { 253 24000, 0x05, 2, 254 { 255 { "24_1", BTSTACK_LC3_FRAME_DURATION_7500US, 45}, 256 { "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60} 257 } 258 }, 259 { 260 32000, 0x06, 2, 261 { 262 { "32_1", BTSTACK_LC3_FRAME_DURATION_7500US, 60}, 263 { "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80} 264 } 265 }, 266 { 267 44100, 0x07, 2, 268 { 269 { "441_1", BTSTACK_LC3_FRAME_DURATION_7500US, 97}, 270 { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130} 271 } 272 }, 273 { 274 48000, 0x08, 6, 275 { 276 { "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75}, 277 { "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100}, 278 { "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90}, 279 { "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120}, 280 { "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117}, 281 { "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155} 282 } 283 }, 284 }; 285 286 static void show_usage(void); 287 288 static void print_config(void) { 289 printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n", 290 codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 291 num_bis, 292 codec_configurations[menu_sampling_frequency].samplingrate_hz, 293 codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 294 codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 295 audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : ""); 296 } 297 298 static void setup_lc3_encoder(void){ 299 uint8_t channel; 300 for (channel = 0 ; channel < num_bis ; channel++){ 301 btstack_lc3_encoder_google_t * context = &encoder_contexts[channel]; 302 lc3_encoder = btstack_lc3_encoder_google_init_instance(context); 303 lc3_encoder->configure(context, sampling_frequency_hz, frame_duration, octets_per_frame); 304 } 305 number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration); 306 btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 307 printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 308 sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 309 number_samples_per_frame, octets_per_frame); 310 } 311 312 static void setup_mod_player(void){ 313 if (!hxcmod_initialized) { 314 hxcmod_initialized = hxcmod_init(&mod_context); 315 btstack_assert(hxcmod_initialized != 0); 316 } 317 hxcmod_unload(&mod_context); 318 hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 319 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 320 } 321 322 static void generate_audio(void){ 323 uint32_t start_ms = btstack_run_loop_get_time_ms(); 324 uint16_t sample; 325 switch (audio_source) { 326 case AUDIO_SOURCE_SINE: 327 // generate sine wave for all channels 328 for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 329 uint8_t channel; 330 for (channel = 0; channel < num_bis; channel++) { 331 int16_t value = sine_int16[sine_phases[channel]] / 4; 332 pcm[sample * num_bis + channel] = value; 333 sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 334 if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 335 sine_phases[channel] = 0; 336 } 337 } 338 } 339 break; 340 case AUDIO_SOURCE_MODPLAYER: 341 // mod player configured for stereo 342 hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf); 343 if (num_bis == 1) { 344 // stereo -> mono 345 uint16_t i; 346 for (i=0;i<number_samples_per_frame;i++){ 347 pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2); 348 } 349 } 350 break; 351 default: 352 btstack_unreachable(); 353 break; 354 } 355 time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 356 iso_frame_counter++; 357 } 358 359 static void encode(uint8_t bis_index){ 360 // encode as lc3 361 lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES]); 362 } 363 364 365 static void send_iso_packet(uint8_t bis_index) { 366 367 #ifdef COUNT_MODE 368 if (bis_index == 0) { 369 uint32_t now = btstack_run_loop_get_time_ms(); 370 if (send_last_ms != 0) { 371 uint16_t send_interval_ms = now - send_last_ms; 372 if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 373 printf("ERROR: send interval %u\n", send_interval_ms); 374 } else { 375 send_time_bins[send_interval_ms]++; 376 } 377 } 378 send_last_ms = now; 379 } 380 #endif 381 bool ok = hci_reserve_packet_buffer(); 382 btstack_assert(ok); 383 uint8_t * buffer = hci_get_outgoing_packet_buffer(); 384 // complete SDU, no TimeStamp 385 little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 386 // len 387 little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 388 // TimeStamp if TS flag is set 389 // packet seq nr 390 little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 391 // iso sdu len 392 little_endian_store_16(buffer, 6, octets_per_frame); 393 #ifdef COUNT_MODE 394 // test data: bis_index, counter 395 buffer[8] = bis_index; 396 memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 397 #else 398 // copy encoded payload 399 memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 400 #endif 401 // send 402 hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 403 404 #ifdef HAVE_POSIX_FILE_IO 405 if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 406 printf("Encoding time: %u\n", time_generation_ms); 407 } 408 #endif 409 410 packet_sequence_numbers[bis_index]++; 411 } 412 413 static void generate_audio_and_encode(void){ 414 uint8_t i; 415 generate_audio(); 416 for (i = 0; i < num_bis; i++) { 417 encode(i); 418 bis_has_data[i] = true; 419 } 420 } 421 422 static void setup_advertising() { 423 gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 424 gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 425 gap_periodic_advertising_set_params(adv_handle, &periodic_params); 426 gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data); 427 gap_periodic_advertising_start(adv_handle, 0); 428 gap_extended_advertising_start(adv_handle, 0, 0); 429 } 430 431 static void setup_big(void){ 432 // Create BIG 433 big_params.big_handle = 0; 434 big_params.advertising_handle = adv_handle; 435 big_params.num_bis = num_bis; 436 big_params.max_sdu = octets_per_frame; 437 big_params.max_transport_latency_ms = 31; 438 big_params.rtn = 2; 439 big_params.phy = 2; 440 big_params.packing = 0; 441 big_params.encryption = encryption; 442 if (encryption) { 443 memcpy(big_params.broadcast_code, &broadcast_code[0], 16); 444 } else { 445 memset(big_params.broadcast_code, 0, 16); 446 } 447 if (sampling_frequency_hz == 44100){ 448 // same config as for 48k -> frame is longer by 48/44.1 449 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 450 big_params.framing = 1; 451 } else { 452 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 453 big_params.framing = 0; 454 } 455 app_state = APP_W4_CREATE_BIG_COMPLETE; 456 gap_big_create(&big_storage, &big_params); 457 } 458 459 460 static void start_broadcast() {// use values from table 461 sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 462 octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 463 frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 464 465 // get num samples per frame 466 setup_lc3_encoder(); 467 468 // setup base 469 uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 }; 470 uint8_t subgroup_codec_specific_configuration[] = { 471 0x02, 0x01, 0x01, 472 0x02, 0x02, 0x01, 473 0x03, 0x04, 0x1E, 0x00, 474 }; 475 subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index; 476 subgroup_codec_specific_configuration[5] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;; 477 uint8_t subgroup_metadata[] = { 478 0x03, 0x02, 0x04, 0x00, // Metadata[i] 479 }; 480 little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame); 481 uint8_t bis_codec_specific_configuration_1[] = { 482 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 483 }; 484 uint8_t bis_codec_specific_configuration_2[] = { 485 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 486 }; 487 le_audio_base_builder_t builder; 488 le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40); 489 le_audio_base_builder_add_subgroup(&builder, codec_id, 490 sizeof(subgroup_codec_specific_configuration), 491 subgroup_codec_specific_configuration, 492 sizeof(subgroup_metadata), subgroup_metadata); 493 le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1), 494 bis_codec_specific_configuration_1); 495 if (num_bis == 2){ 496 le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2), 497 bis_codec_specific_configuration_2); 498 } 499 period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder); 500 501 // setup mod player 502 setup_mod_player(); 503 504 // setup sine generator 505 if (sampling_frequency_hz == 44100){ 506 sine_step = 2; 507 } else { 508 sine_step = 96000 / sampling_frequency_hz; 509 } 510 511 // setup extended and periodic advertising 512 setup_advertising(); 513 514 // setup big 515 setup_big(); 516 } 517 518 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 519 UNUSED(channel); 520 if (packet_type != HCI_EVENT_PACKET) return; 521 uint8_t bis_index; 522 523 switch (packet[0]) { 524 case BTSTACK_EVENT_STATE: 525 switch(btstack_event_state_get_state(packet)) { 526 case HCI_STATE_WORKING: 527 #ifdef ENABLE_DEMO_MODE 528 // start broadcast automatically, mod player, 48_5_1 529 num_bis = 1; 530 menu_sampling_frequency = 5; 531 menu_variant = 4; 532 start_broadcast(); 533 #else 534 show_usage(); 535 printf("Please select sample frequency and variation, then start broadcast\n"); 536 #endif 537 break; 538 case HCI_STATE_OFF: 539 printf("Goodbye\n"); 540 exit(0); 541 break; 542 default: 543 break; 544 } 545 break; 546 case HCI_EVENT_META_GAP: 547 switch (hci_event_gap_meta_get_subevent_code(packet)){ 548 case GAP_SUBEVENT_BIG_CREATED: 549 printf("BIG Created with BIS Connection handles: \n"); 550 for (bis_index=0;bis_index<num_bis;bis_index++){ 551 bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index); 552 printf("0x%04x ", bis_con_handles[bis_index]); 553 } 554 555 app_state = APP_STREAMING; 556 printf("Start streaming\n"); 557 generate_audio_and_encode(); 558 hci_request_bis_can_send_now_events(big_params.big_handle); 559 break; 560 default: 561 break; 562 } 563 break; 564 case HCI_EVENT_BIS_CAN_SEND_NOW: 565 bis_index = hci_event_bis_can_send_now_get_bis_index(packet); 566 send_iso_packet(bis_index); 567 bis_index++; 568 if (bis_index == num_bis){ 569 generate_audio_and_encode(); 570 hci_request_bis_can_send_now_events(big_params.big_handle); 571 } 572 break; 573 default: 574 break; 575 } 576 } 577 578 static void show_usage(void){ 579 printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 580 print_config(); 581 printf("---\n"); 582 printf("c - toggle channels\n"); 583 printf("e - toggle encryption\n"); 584 printf("f - next sampling frequency\n"); 585 printf("v - next codec variant\n"); 586 printf("t - toggle sine / modplayer\n"); 587 printf("s - start broadcast\n"); 588 printf("---\n"); 589 } 590 static void stdin_process(char c){ 591 switch (c){ 592 case 'c': 593 if (app_state != APP_IDLE){ 594 printf("Codec configuration can only be changed in idle state\n"); 595 break; 596 } 597 num_bis = 3 - num_bis; 598 print_config(); 599 break; 600 case 'e': 601 if (app_state != APP_IDLE){ 602 printf("Encryption can only be changed in idle state\n"); 603 break; 604 } 605 encryption = 1 - encryption; 606 print_config(); 607 break; 608 case 'f': 609 if (app_state != APP_IDLE){ 610 printf("Codec configuration can only be changed in idle state\n"); 611 break; 612 } 613 menu_sampling_frequency++; 614 if (menu_sampling_frequency >= 6){ 615 menu_sampling_frequency = 0; 616 } 617 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 618 menu_variant = 0; 619 } 620 print_config(); 621 break; 622 case 'v': 623 if (app_state != APP_IDLE){ 624 printf("Codec configuration can only be changed in idle state\n"); 625 break; 626 } 627 menu_variant++; 628 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 629 menu_variant = 0; 630 } 631 print_config(); 632 break; 633 case 's': 634 if (app_state != APP_IDLE){ 635 printf("Cannot start broadcast - not in idle state\n"); 636 break; 637 } 638 start_broadcast(); 639 break; 640 case 't': 641 audio_source = 1 - audio_source; 642 print_config(); 643 break; 644 case '\n': 645 case '\r': 646 break; 647 default: 648 show_usage(); 649 break; 650 } 651 } 652 653 int btstack_main(int argc, const char * argv[]); 654 int btstack_main(int argc, const char * argv[]){ 655 (void) argv; 656 (void) argc; 657 658 // register for HCI events 659 hci_event_callback_registration.callback = &packet_handler; 660 hci_add_event_handler(&hci_event_callback_registration); 661 662 // turn on! 663 hci_power_control(HCI_POWER_ON); 664 665 btstack_stdin_setup(stdin_process); 666 return 0; 667 } 668