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