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 60 #include "hxcmod.h" 61 #include "mods/mod.h" 62 63 // PTS mode 64 // #define PTS_MODE 65 66 // Count mode - send packet count as test data for manual analysis 67 // #define COUNT_MODE 68 69 // max config 70 #define MAX_NUM_BIS 2 71 #define MAX_SAMPLES_PER_FRAME 480 72 #define MAX_LC3_FRAME_BYTES 155 73 74 static const uint8_t adv_sid = 0; 75 76 static le_advertising_set_t le_advertising_set; 77 78 static const le_extended_advertising_parameters_t extended_params = { 79 .advertising_event_properties = 0, 80 .primary_advertising_interval_min = 0x4b0, // 750 ms 81 .primary_advertising_interval_max = 0x4b0, // 750 ms 82 .primary_advertising_channel_map = 7, 83 .own_address_type = 0, 84 .peer_address_type = 0, 85 .peer_address = { 0 }, 86 .advertising_filter_policy = 0, 87 .advertising_tx_power = 10, // 10 dBm 88 .primary_advertising_phy = 1, // LE 1M PHY 89 .secondary_advertising_max_skip = 0, 90 .secondary_advertising_phy = 1, // LE 1M PHY 91 .advertising_sid = adv_sid, 92 .scan_request_notification_enable = 0, 93 }; 94 95 static const uint8_t extended_adv_data[] = { 96 // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID 97 6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18, 0x30, 0x5d, 0x9b, 98 // name 99 #ifdef PTS_MODE 100 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x' 101 #elif defined(COUNT_MODE) 102 6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T' 103 #else 104 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e' 105 #endif 106 }; 107 108 static const le_periodic_advertising_parameters_t periodic_params = { 109 .periodic_advertising_interval_min = 0x258, // 375 ms 110 .periodic_advertising_interval_max = 0x258, // 375 ms 111 .periodic_advertising_properties = 0 112 }; 113 114 static uint8_t periodic_adv_data_1[] = { 115 // 16 bit service data 116 37, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 117 // Level 1 - BIG Parameters (common to all BISes) 118 0x51, 0x18, // Basic Audio Announcement Service UUID 119 0x28, 0x00, 0x00, // Presentation Delay 3 120 0x01, // Num_Subgroups 121 // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 122 // offset 8 123 0x01, // The number of BISes in this subgroup 124 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 125 10, // Codec_Specific_Configuration_Length[i] 126 // Codec_Specific_Configuration[i] = 8_2 127 // offset 15 128 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 129 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 130 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 131 4, // Metadata_Length[i] 132 0x03, 0x02, 0x04, 0x00, // Metadata[i] 133 // Level 3 - Specific BIS Parameters (if required, for individual BISes) 134 0x01, // BIS_index[i[k]] 135 6, // Codec_Specific_Configuration_Length[i[k]] 136 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 137 }; 138 139 static uint8_t periodic_adv_data_2[] = { 140 // 16 bit service data 141 37+8, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 142 // Level 1 - BIG Parameters (common to all BISes) 143 0x51, 0x18, // Basic Audio Announcement Service UUID 144 0x28, 0x00, 0x00, // Presentation Delay 3 145 0x01, // Num_Subgroups 146 // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 147 // offset 8 148 0x02, // The number of BISes in this subgroup 149 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 150 10, // Codec_Specific_Configuration_Length[i] 151 // Codec_Specific_Configuration[0] = 8_2 152 // offset 15 153 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 154 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 155 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 156 4, // Metadata_Length[i] 157 0x03, 0x02, 0x04, 0x00, // Metadata[0] 158 // Level 3 - Specific BIS Parameters (if required, for individual BISes) 159 0x01, // BIS_index[i[k]] 160 6, // Codec_Specific_Configuration_Length[i[k]] 161 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, // Codec_Specific_Configuration[i[k]] 162 // Level 3 - Specific BIS Parameters (if required, for individual BISes) 163 0x02, // BIS_index[i[k]] 164 6, // Codec_Specific_Configuration_Length[i[k]] 165 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 166 }; 167 168 // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz 169 static const int16_t sine_int16[] = { 170 0, 643, 1286, 1929, 2571, 3212, 3851, 4489, 5126, 5760, 171 6393, 7022, 7649, 8273, 8894, 9512, 10126, 10735, 11341, 11943, 172 12539, 13131, 13718, 14300, 14876, 15446, 16011, 16569, 17121, 17666, 173 18204, 18736, 19260, 19777, 20286, 20787, 21280, 21766, 22242, 22710, 174 23170, 23620, 24062, 24494, 24916, 25329, 25732, 26126, 26509, 26882, 175 27245, 27597, 27938, 28269, 28589, 28898, 29196, 29482, 29757, 30021, 176 30273, 30513, 30742, 30958, 31163, 31356, 31537, 31705, 31862, 32006, 177 32137, 32257, 32364, 32458, 32540, 32609, 32666, 32710, 32742, 32761, 178 32767, 32761, 32742, 32710, 32666, 32609, 32540, 32458, 32364, 32257, 179 32137, 32006, 31862, 31705, 31537, 31356, 31163, 30958, 30742, 30513, 180 30273, 30021, 29757, 29482, 29196, 28898, 28589, 28269, 27938, 27597, 181 27245, 26882, 26509, 26126, 25732, 25329, 24916, 24494, 24062, 23620, 182 23170, 22710, 22242, 21766, 21280, 20787, 20286, 19777, 19260, 18736, 183 18204, 17666, 17121, 16569, 16011, 15446, 14876, 14300, 13718, 13131, 184 12539, 11943, 11341, 10735, 10126, 9512, 8894, 8273, 7649, 7022, 185 6393, 5760, 5126, 4489, 3851, 3212, 2571, 1929, 1286, 643, 186 0, -643, -1286, -1929, -2571, -3212, -3851, -4489, -5126, -5760, 187 -6393, -7022, -7649, -8273, -8894, -9512, -10126, -10735, -11341, -11943, 188 -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666, 189 -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710, 190 -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882, 191 -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021, 192 -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006, 193 -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761, 194 -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257, 195 -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513, 196 -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597, 197 -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620, 198 -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736, 199 -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131, 200 -12539, -11943, -11341, -10735, -10126, -9512, -8894, -8273, -7649, -7022, 201 -6393, -5760, -5126, -4489, -3851, -3212, -2571, -1929, -1286, -643, 202 }; 203 204 static bd_addr_t remote; 205 static const char * remote_addr_string = "00:1B:DC:08:E2:72"; 206 207 static btstack_packet_callback_registration_t hci_event_callback_registration; 208 209 static uint8_t adv_handle = 0; 210 static unsigned int next_bis_index; 211 static hci_con_handle_t bis_con_handles[MAX_NUM_BIS]; 212 static uint16_t packet_sequence_numbers[MAX_NUM_BIS]; 213 static uint8_t framed_pdus; 214 static bool bis_can_send[MAX_NUM_BIS]; 215 static bool bis_has_data[MAX_NUM_BIS]; 216 static uint8_t iso_frame_counter; 217 static uint16_t frame_duration_us; 218 219 static le_audio_big_t big_storage; 220 static le_audio_big_params_t big_params; 221 222 // time stamping 223 #ifdef COUNT_MODE 224 #define MAX_PACKET_INTERVAL_BINS_MS 50 225 static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS]; 226 static uint32_t send_last_ms; 227 #endif 228 229 // lc3 codec config 230 static uint16_t sampling_frequency_hz; 231 static btstack_lc3_frame_duration_t frame_duration; 232 static uint16_t number_samples_per_frame; 233 static uint16_t octets_per_frame; 234 static uint8_t num_bis = 1; 235 236 // lc3 encoder 237 static const btstack_lc3_encoder_t * lc3_encoder; 238 static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS]; 239 static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 240 static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES]; 241 static uint32_t time_generation_ms; 242 243 // codec menu 244 static uint8_t menu_sampling_frequency; 245 static uint8_t menu_variant; 246 247 // mod player 248 static int hxcmod_initialized; 249 static modcontext mod_context; 250 static tracker_buffer_state trkbuf; 251 252 // sine generator 253 static uint8_t sine_step; 254 static uint16_t sine_phases[MAX_NUM_BIS]; 255 256 // audio producer 257 static enum { 258 AUDIO_SOURCE_SINE, 259 AUDIO_SOURCE_MODPLAYER 260 } audio_source = AUDIO_SOURCE_MODPLAYER; 261 262 static enum { 263 APP_IDLE, 264 APP_W4_CREATE_BIG_COMPLETE, 265 APP_STREAMING, 266 APP_W4_POWER_OFF, 267 } app_state = APP_IDLE; 268 269 // enumerate default codec configs 270 static struct { 271 uint16_t samplingrate_hz; 272 uint8_t samplingrate_index; 273 uint8_t num_variants; 274 struct { 275 const char * name; 276 btstack_lc3_frame_duration_t frame_duration; 277 uint16_t octets_per_frame; 278 } variants[6]; 279 } codec_configurations[] = { 280 { 281 8000, 0x01, 2, 282 { 283 { "8_1", BTSTACK_LC3_FRAME_DURATION_7500US, 26}, 284 { "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30} 285 } 286 }, 287 { 288 16000, 0x03, 2, 289 { 290 { "16_1", BTSTACK_LC3_FRAME_DURATION_7500US, 30}, 291 { "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40} 292 } 293 }, 294 { 295 24000, 0x05, 2, 296 { 297 { "24_1", BTSTACK_LC3_FRAME_DURATION_7500US, 45}, 298 { "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60} 299 } 300 }, 301 { 302 32000, 0x06, 2, 303 { 304 { "32_1", BTSTACK_LC3_FRAME_DURATION_7500US, 60}, 305 { "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80} 306 } 307 }, 308 { 309 44100, 0x07, 2, 310 { 311 { "441_1", BTSTACK_LC3_FRAME_DURATION_7500US, 97}, 312 { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130} 313 } 314 }, 315 { 316 48000, 0x08, 6, 317 { 318 { "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75}, 319 { "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100}, 320 { "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90}, 321 { "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120}, 322 { "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117}, 323 { "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155} 324 } 325 }, 326 }; 327 328 static void show_usage(void); 329 330 static void print_config(void) { 331 printf("Config '%s_%u': %u, %s ms, %u octets - %s\n", 332 codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 333 num_bis, 334 codec_configurations[menu_sampling_frequency].samplingrate_hz, 335 codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 336 codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 337 audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer"); 338 } 339 340 static void setup_lc3_encoder(void){ 341 uint8_t channel; 342 for (channel = 0 ; channel < num_bis ; channel++){ 343 btstack_lc3_encoder_google_t * context = &encoder_contexts[channel]; 344 lc3_encoder = btstack_lc3_encoder_google_init_instance(context); 345 lc3_encoder->configure(context, sampling_frequency_hz, frame_duration); 346 } 347 number_samples_per_frame = lc3_encoder->get_number_samples_per_frame(&encoder_contexts[0]); 348 btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 349 printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 350 sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 351 number_samples_per_frame, octets_per_frame); 352 } 353 354 static void setup_mod_player(void){ 355 if (!hxcmod_initialized) { 356 hxcmod_initialized = hxcmod_init(&mod_context); 357 btstack_assert(hxcmod_initialized != 0); 358 } 359 hxcmod_unload(&mod_context); 360 hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 361 hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 362 } 363 364 static void generate_audio(void){ 365 uint32_t start_ms = btstack_run_loop_get_time_ms(); 366 uint16_t sample; 367 switch (audio_source) { 368 case AUDIO_SOURCE_SINE: 369 // generate sine wave for all channels 370 for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 371 uint8_t channel; 372 for (channel = 0; channel < num_bis; channel++) { 373 int16_t value = sine_int16[sine_phases[channel]] / 4; 374 pcm[sample * num_bis + channel] = value; 375 sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 376 if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 377 sine_phases[channel] = 0; 378 } 379 } 380 } 381 break; 382 case AUDIO_SOURCE_MODPLAYER: 383 // mod player configured for stereo 384 hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf); 385 if (num_bis == 1) { 386 // stereo -> mono 387 uint16_t i; 388 for (i=0;i<number_samples_per_frame;i++){ 389 pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2); 390 } 391 } 392 break; 393 default: 394 btstack_unreachable(); 395 break; 396 } 397 time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 398 iso_frame_counter++; 399 } 400 401 static void encode(uint8_t bis_index){ 402 // encode as lc3 403 lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 404 } 405 406 407 static void send_iso_packet(uint8_t bis_index) { 408 409 #ifdef COUNT_MODE 410 if (bis_index == 0) { 411 uint32_t now = btstack_run_loop_get_time_ms(); 412 if (send_last_ms != 0) { 413 uint16_t send_interval_ms = now - send_last_ms; 414 if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 415 printf("ERROR: send interval %u\n", send_interval_ms); 416 } else { 417 send_time_bins[send_interval_ms]++; 418 } 419 } 420 send_last_ms = now; 421 } 422 #endif 423 bool ok = hci_reserve_packet_buffer(); 424 btstack_assert(ok); 425 uint8_t * buffer = hci_get_outgoing_packet_buffer(); 426 // complete SDU, no TimeStamp 427 little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 428 // len 429 little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 430 // TimeStamp if TS flag is set 431 // packet seq nr 432 little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 433 // iso sdu len 434 little_endian_store_16(buffer, 6, octets_per_frame); 435 #ifdef COUNT_MODE 436 // test data: bis_index, counter 437 buffer[8] = bis_index; 438 memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 439 #else 440 // copy encoded payload 441 memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 442 #endif 443 // send 444 hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 445 446 #ifdef HAVE_POSIX_FILE_IO 447 if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 448 printf("Encoding time: %u\n", time_generation_ms); 449 } 450 #endif 451 452 packet_sequence_numbers[bis_index]++; 453 } 454 455 static void generate_audio_and_encode(void){ 456 uint8_t i; 457 generate_audio(); 458 for (i = 0; i < num_bis; i++) { 459 encode(i); 460 bis_has_data[i] = true; 461 } 462 } 463 464 static void setup_advertising() { 465 gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 466 gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 467 gap_periodic_advertising_set_params(adv_handle, &periodic_params); 468 switch(num_bis){ 469 case 1: 470 gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1); 471 printf("BASE: "); 472 printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1)); 473 break; 474 case 2: 475 gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2); 476 printf("BASE: "); 477 printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2)); 478 break; 479 default: 480 btstack_unreachable(); 481 break; 482 } 483 gap_periodic_advertising_start(adv_handle, 0); 484 gap_extended_advertising_start(adv_handle, 0, 0); 485 } 486 487 static void setup_big(void){ 488 // Create BIG 489 big_params.big_handle = 0; 490 big_params.advertising_handle = adv_handle; 491 big_params.num_bis = num_bis; 492 big_params.max_sdu = octets_per_frame; 493 big_params.max_transport_latency_ms = 31; 494 big_params.rtn = 2; 495 big_params.phy = 2; 496 big_params.packing = 0; 497 big_params.encryption = 0; 498 memset(big_params.broadcast_code, 0, 16); 499 if (sampling_frequency_hz == 44100){ 500 // same config as for 48k -> frame is longer by 48/44.1 501 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 502 big_params.framing = 1; 503 } else { 504 big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 505 big_params.framing = 0; 506 } 507 app_state = APP_W4_CREATE_BIG_COMPLETE; 508 gap_big_create(&big_storage, &big_params); 509 } 510 511 512 static void start_broadcast() {// use values from table 513 sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 514 octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 515 frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 516 517 // get num samples per frame 518 setup_lc3_encoder(); 519 520 // update BASEs 521 periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 522 periodic_adv_data_1[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 523 little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame); 524 525 periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 526 periodic_adv_data_2[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 527 little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame); 528 529 // setup mod player 530 setup_mod_player(); 531 532 // setup sine generator 533 if (sampling_frequency_hz == 44100){ 534 sine_step = 2; 535 } else { 536 sine_step = 96000 / sampling_frequency_hz; 537 } 538 539 // setup extended and periodic advertising 540 setup_advertising(); 541 542 // setup big 543 setup_big(); 544 } 545 546 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 547 UNUSED(channel); 548 if (packet_type != HCI_EVENT_PACKET) return; 549 uint8_t bis_index; 550 551 switch (packet[0]) { 552 case BTSTACK_EVENT_STATE: 553 switch(btstack_event_state_get_state(packet)) { 554 case HCI_STATE_WORKING: 555 #ifdef ENABLE_DEMO_MODE 556 // start broadcast automatically, mod player, 48_5_1 557 num_bis = 1; 558 menu_sampling_frequency = 5; 559 menu_variant = 4; 560 start_broadcast(); 561 #else 562 show_usage(); 563 printf("Please select sample frequency and variation, then start broadcast\n"); 564 #endif 565 break; 566 case HCI_STATE_OFF: 567 printf("Goodbye\n"); 568 exit(0); 569 break; 570 default: 571 break; 572 } 573 break; 574 case HCI_EVENT_META_GAP: 575 switch (hci_event_gap_meta_get_subevent_code(packet)){ 576 case GAP_SUBEVENT_BIG_CREATED: 577 printf("BIG Created with BIS Connection handles: \n"); 578 for (bis_index=0;bis_index<num_bis;bis_index++){ 579 bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index); 580 printf("0x%04x ", bis_con_handles[bis_index]); 581 } 582 583 app_state = APP_STREAMING; 584 printf("Start streaming\n"); 585 generate_audio_and_encode(); 586 hci_request_bis_can_send_now_events(big_params.big_handle); 587 break; 588 default: 589 break; 590 } 591 break; 592 case HCI_EVENT_BIS_CAN_SEND_NOW: 593 bis_index = hci_event_bis_can_send_now_get_bis_index(packet); 594 send_iso_packet(bis_index); 595 bis_index++; 596 if (bis_index == num_bis){ 597 generate_audio_and_encode(); 598 hci_request_bis_can_send_now_events(big_params.big_handle); 599 } 600 break; 601 default: 602 break; 603 } 604 } 605 606 static void show_usage(void){ 607 printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 608 print_config(); 609 printf("---\n"); 610 printf("c - toggle channels\n"); 611 printf("f - next sampling frequency\n"); 612 printf("v - next codec variant\n"); 613 printf("t - toggle sine / modplayer\n"); 614 printf("s - start broadcast\n"); 615 printf("x - shutdown\n"); 616 printf("---\n"); 617 } 618 static void stdin_process(char c){ 619 switch (c){ 620 case 'c': 621 if (app_state != APP_IDLE){ 622 printf("Codec configuration can only be changed in idle state\n"); 623 break; 624 } 625 num_bis = 3 - num_bis; 626 print_config(); 627 break; 628 case 'f': 629 if (app_state != APP_IDLE){ 630 printf("Codec configuration can only be changed in idle state\n"); 631 break; 632 } 633 menu_sampling_frequency++; 634 if (menu_sampling_frequency >= 6){ 635 menu_sampling_frequency = 0; 636 } 637 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 638 menu_variant = 0; 639 } 640 print_config(); 641 break; 642 case 'v': 643 if (app_state != APP_IDLE){ 644 printf("Codec configuration can only be changed in idle state\n"); 645 break; 646 } 647 menu_variant++; 648 if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 649 menu_variant = 0; 650 } 651 print_config(); 652 break; 653 case 'x': 654 #ifdef COUNT_MODE 655 printf("Send statistic:\n"); 656 { 657 uint16_t i; 658 for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){ 659 printf("%2u: %5u\n", i, send_time_bins[i]); 660 } 661 } 662 #endif 663 printf("Shutdown...\n"); 664 app_state = APP_W4_POWER_OFF; 665 hci_power_control(HCI_POWER_OFF); 666 break; 667 case 's': 668 if (app_state != APP_IDLE){ 669 printf("Cannot start broadcast - not in idle state\n"); 670 break; 671 } 672 start_broadcast(); 673 break; 674 case 't': 675 audio_source = 1 - audio_source; 676 print_config(); 677 break; 678 case '\n': 679 case '\r': 680 break; 681 default: 682 show_usage(); 683 break; 684 } 685 } 686 687 int btstack_main(int argc, const char * argv[]); 688 int btstack_main(int argc, const char * argv[]){ 689 (void) argv; 690 (void) argc; 691 692 // register for HCI events 693 hci_event_callback_registration.callback = &packet_handler; 694 hci_add_event_handler(&hci_event_callback_registration); 695 696 // turn on! 697 hci_power_control(HCI_POWER_ON); 698 699 btstack_stdin_setup(stdin_process); 700 return 0; 701 } 702