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 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 = BD_ADDR_TYPE_LE_PUBLIC, 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 bool is_zero_bd_addr( bd_addr_t address ) { 423 int sum = 0; 424 for( int i=0; i<6; ++i ) { 425 sum += address[i]; 426 } 427 return (sum>0)?false:true; 428 } 429 430 static void setup_advertising() { 431 bd_addr_t local_addr; 432 gap_local_bd_addr(local_addr); 433 bool local_address_invalid = is_zero_bd_addr( local_addr ); 434 if( local_address_invalid ) { 435 extended_params.own_address_type = BD_ADDR_TYPE_LE_RANDOM; 436 } 437 gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 438 if( local_address_invalid ) { 439 bd_addr_t random_address = { 0xC1, 0x01, 0x01, 0x01, 0x01, 0x01 }; 440 gap_extended_advertising_set_random_address( adv_handle, random_address ); 441 } 442 gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 443 gap_periodic_advertising_set_params(adv_handle, &periodic_params); 444 gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data); 445 gap_periodic_advertising_start(adv_handle, 0); 446 gap_extended_advertising_start(adv_handle, 0, 0); 447 } 448 449 static void setup_big(void){ 450 // Create BIG 451 big_params.big_handle = 0; 452 big_params.advertising_handle = adv_handle; 453 big_params.num_bis = num_bis; 454 big_params.max_sdu = octets_per_frame; 455 big_params.max_transport_latency_ms = 31; 456 big_params.rtn = 2; 457 big_params.phy = 2; 458 big_params.packing = 0; 459 big_params.encryption = encryption; 460 if (encryption) { 461 memcpy(big_params.broadcast_code, &broadcast_code[0], 16); 462 } else { 463 memset(big_params.broadcast_code, 0, 16); 464 } 465 if (sampling_frequency_hz == 44100){ 466 // same config as for 48k -> frame is longer by 48/44.1 467 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 468 big_params.framing = 1; 469 } else { 470 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 471 big_params.framing = 0; 472 } 473 app_state = APP_W4_CREATE_BIG_COMPLETE; 474 gap_big_create(&big_storage, &big_params); 475 } 476 477 478 static void start_broadcast() {// use values from table 479 sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 480 octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 481 frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 482 483 // get num samples per frame 484 setup_lc3_encoder(); 485 486 // setup base 487 uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 }; 488 uint8_t subgroup_codec_specific_configuration[] = { 489 0x02, 0x01, 0x01, 490 0x02, 0x02, 0x01, 491 0x03, 0x04, 0x1E, 0x00, 492 }; 493 subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index; 494 subgroup_codec_specific_configuration[5] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;; 495 uint8_t subgroup_metadata[] = { 496 0x03, 0x02, 0x04, 0x00, // Metadata[i] 497 }; 498 little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame); 499 uint8_t bis_codec_specific_configuration_1[] = { 500 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 501 }; 502 uint8_t bis_codec_specific_configuration_2[] = { 503 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 504 }; 505 le_audio_base_builder_t builder; 506 le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40); 507 le_audio_base_builder_add_subgroup(&builder, codec_id, 508 sizeof(subgroup_codec_specific_configuration), 509 subgroup_codec_specific_configuration, 510 sizeof(subgroup_metadata), subgroup_metadata); 511 le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1), 512 bis_codec_specific_configuration_1); 513 if (num_bis == 2){ 514 le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2), 515 bis_codec_specific_configuration_2); 516 } 517 period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder); 518 519 // setup mod player 520 setup_mod_player(); 521 522 // setup sine generator 523 if (sampling_frequency_hz == 44100){ 524 sine_step = 2; 525 } else { 526 sine_step = 96000 / sampling_frequency_hz; 527 } 528 529 // setup extended and periodic advertising 530 setup_advertising(); 531 532 // setup big 533 setup_big(); 534 } 535 536 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 537 UNUSED(channel); 538 if (packet_type != HCI_EVENT_PACKET) return; 539 uint8_t bis_index; 540 541 switch (packet[0]) { 542 case BTSTACK_EVENT_STATE: 543 switch(btstack_event_state_get_state(packet)) { 544 case HCI_STATE_WORKING: 545 #ifdef ENABLE_DEMO_MODE 546 // start broadcast automatically, mod player, 48_5_1 547 num_bis = 1; 548 menu_sampling_frequency = 5; 549 menu_variant = 4; 550 start_broadcast(); 551 #else 552 show_usage(); 553 printf("Please select sample frequency and variation, then start broadcast\n"); 554 #endif 555 break; 556 case HCI_STATE_OFF: 557 printf("Goodbye\n"); 558 exit(0); 559 break; 560 default: 561 break; 562 } 563 break; 564 case HCI_EVENT_META_GAP: 565 switch (hci_event_gap_meta_get_subevent_code(packet)){ 566 case GAP_SUBEVENT_BIG_CREATED: 567 printf("BIG Created with BIS Connection handles: \n"); 568 for (bis_index=0;bis_index<num_bis;bis_index++){ 569 bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index); 570 printf("0x%04x ", bis_con_handles[bis_index]); 571 } 572 573 app_state = APP_STREAMING; 574 printf("Start streaming\n"); 575 generate_audio_and_encode(); 576 hci_request_bis_can_send_now_events(big_params.big_handle); 577 break; 578 default: 579 break; 580 } 581 break; 582 case HCI_EVENT_BIS_CAN_SEND_NOW: 583 bis_index = hci_event_bis_can_send_now_get_bis_index(packet); 584 send_iso_packet(bis_index); 585 bis_index++; 586 if (bis_index == num_bis){ 587 generate_audio_and_encode(); 588 hci_request_bis_can_send_now_events(big_params.big_handle); 589 } 590 break; 591 default: 592 break; 593 } 594 } 595 596 static void show_usage(void){ 597 printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 598 print_config(); 599 printf("---\n"); 600 printf("c - toggle channels\n"); 601 printf("e - toggle encryption\n"); 602 printf("f - next sampling frequency\n"); 603 printf("v - next codec variant\n"); 604 printf("t - toggle sine / modplayer\n"); 605 printf("s - start broadcast\n"); 606 printf("---\n"); 607 } 608 static void stdin_process(char c){ 609 switch (c){ 610 case 'c': 611 if (app_state != APP_IDLE){ 612 printf("Codec configuration can only be changed in idle state\n"); 613 break; 614 } 615 num_bis = 3 - num_bis; 616 print_config(); 617 break; 618 case 'e': 619 if (app_state != APP_IDLE){ 620 printf("Encryption can only be changed in idle state\n"); 621 break; 622 } 623 encryption = 1 - encryption; 624 print_config(); 625 break; 626 case 'f': 627 if (app_state != APP_IDLE){ 628 printf("Codec configuration can only be changed in idle state\n"); 629 break; 630 } 631 menu_sampling_frequency++; 632 if (menu_sampling_frequency >= 6){ 633 menu_sampling_frequency = 0; 634 } 635 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 636 menu_variant = 0; 637 } 638 print_config(); 639 break; 640 case 'v': 641 if (app_state != APP_IDLE){ 642 printf("Codec configuration can only be changed in idle state\n"); 643 break; 644 } 645 menu_variant++; 646 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 647 menu_variant = 0; 648 } 649 print_config(); 650 break; 651 case 's': 652 if (app_state != APP_IDLE){ 653 printf("Cannot start broadcast - not in idle state\n"); 654 break; 655 } 656 start_broadcast(); 657 break; 658 case 't': 659 audio_source = 1 - audio_source; 660 print_config(); 661 break; 662 case '\n': 663 case '\r': 664 break; 665 default: 666 show_usage(); 667 break; 668 } 669 } 670 671 int btstack_main(int argc, const char * argv[]); 672 int btstack_main(int argc, const char * argv[]){ 673 (void) argv; 674 (void) argc; 675 676 // register for HCI events 677 hci_event_callback_registration.callback = &packet_handler; 678 hci_add_event_handler(&hci_event_callback_registration); 679 680 // turn on! 681 hci_power_control(HCI_POWER_ON); 682 683 btstack_stdin_setup(stdin_process); 684 return 0; 685 } 686