1*10277393SMatthias Ringwald /* 2*10277393SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 3*10277393SMatthias Ringwald * 4*10277393SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*10277393SMatthias Ringwald * modification, are permitted provided that the following conditions 6*10277393SMatthias Ringwald * are met: 7*10277393SMatthias Ringwald * 8*10277393SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*10277393SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*10277393SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*10277393SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*10277393SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*10277393SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*10277393SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*10277393SMatthias Ringwald * from this software without specific prior written permission. 16*10277393SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*10277393SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*10277393SMatthias Ringwald * monetary gain. 19*10277393SMatthias Ringwald * 20*10277393SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*10277393SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*10277393SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*10277393SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*10277393SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*10277393SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*10277393SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*10277393SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*10277393SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*10277393SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*10277393SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*10277393SMatthias Ringwald * SUCH DAMAGE. 32*10277393SMatthias Ringwald * 33*10277393SMatthias Ringwald * Please inquire about commercial licensing options at 34*10277393SMatthias Ringwald * [email protected] 35*10277393SMatthias Ringwald * 36*10277393SMatthias Ringwald */ 37*10277393SMatthias Ringwald 38*10277393SMatthias Ringwald #define BTSTACK_FILE__ "le_audio_broadcast_source.c" 39*10277393SMatthias Ringwald 40*10277393SMatthias Ringwald /* 41*10277393SMatthias Ringwald * LE Audio Broadcast Source 42*10277393SMatthias Ringwald */ 43*10277393SMatthias Ringwald 44*10277393SMatthias Ringwald #include <stdint.h> 45*10277393SMatthias Ringwald #include <stdio.h> 46*10277393SMatthias Ringwald #include <string.h> 47*10277393SMatthias Ringwald #include <btstack_debug.h> 48*10277393SMatthias Ringwald 49*10277393SMatthias Ringwald #include "bluetooth_data_types.h" 50*10277393SMatthias Ringwald #include "btstack_stdin.h" 51*10277393SMatthias Ringwald #include "btstack_event.h" 52*10277393SMatthias Ringwald #include "btstack_run_loop.h" 53*10277393SMatthias Ringwald #include "gap.h" 54*10277393SMatthias Ringwald #include "hci.h" 55*10277393SMatthias Ringwald #include "hci_cmd.h" 56*10277393SMatthias Ringwald #include "hci_dump.h" 57*10277393SMatthias Ringwald #include "lc3.h" 58*10277393SMatthias Ringwald #include "lc3_ehima.h" 59*10277393SMatthias Ringwald 60*10277393SMatthias Ringwald #include "hxcmod.h" 61*10277393SMatthias Ringwald #include "mods/mod.h" 62*10277393SMatthias Ringwald 63*10277393SMatthias Ringwald // PTS mode 64*10277393SMatthias Ringwald // #define PTS_MODE 65*10277393SMatthias Ringwald 66*10277393SMatthias Ringwald // Count mode - send packet count as test data for manual analysis 67*10277393SMatthias Ringwald // #define COUNT_MODE 68*10277393SMatthias Ringwald 69*10277393SMatthias Ringwald // create audio based on timer instead of num completed packets 70*10277393SMatthias Ringwald // #define GENERATE_AUDIO_WITH_TIMER 71*10277393SMatthias Ringwald 72*10277393SMatthias Ringwald // max config 73*10277393SMatthias Ringwald #define MAX_NUM_BIS 2 74*10277393SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 75*10277393SMatthias Ringwald 76*10277393SMatthias Ringwald static const uint8_t adv_sid = 0; 77*10277393SMatthias Ringwald 78*10277393SMatthias Ringwald static le_advertising_set_t le_advertising_set; 79*10277393SMatthias Ringwald 80*10277393SMatthias Ringwald static const le_extended_advertising_parameters_t extended_params = { 81*10277393SMatthias Ringwald .advertising_event_properties = 0, 82*10277393SMatthias Ringwald .primary_advertising_interval_min = 0x4b0, // 750 ms 83*10277393SMatthias Ringwald .primary_advertising_interval_max = 0x4b0, // 750 ms 84*10277393SMatthias Ringwald .primary_advertising_channel_map = 7, 85*10277393SMatthias Ringwald .own_address_type = 0, 86*10277393SMatthias Ringwald .peer_address_type = 0, 87*10277393SMatthias Ringwald .peer_address = 0, 88*10277393SMatthias Ringwald .advertising_filter_policy = 0, 89*10277393SMatthias Ringwald .advertising_tx_power = 10, // 10 dBm 90*10277393SMatthias Ringwald .primary_advertising_phy = 1, // LE 1M PHY 91*10277393SMatthias Ringwald .secondary_advertising_max_skip = 0, 92*10277393SMatthias Ringwald .secondary_advertising_phy = 1, // LE 1M PHY 93*10277393SMatthias Ringwald .advertising_sid = adv_sid, 94*10277393SMatthias Ringwald .scan_request_notification_enable = 0, 95*10277393SMatthias Ringwald }; 96*10277393SMatthias Ringwald 97*10277393SMatthias Ringwald static const uint8_t extended_adv_data[] = { 98*10277393SMatthias Ringwald // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID 99*10277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18, 0x30, 0x5d, 0x9b, 100*10277393SMatthias Ringwald // name 101*10277393SMatthias Ringwald #ifdef PTS_MODE 102*10277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x' 103*10277393SMatthias Ringwald #elif defined(COUNT_MODE) 104*10277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T' 105*10277393SMatthias Ringwald #else 106*10277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e' 107*10277393SMatthias Ringwald #endif 108*10277393SMatthias Ringwald }; 109*10277393SMatthias Ringwald 110*10277393SMatthias Ringwald static const le_periodic_advertising_parameters_t periodic_params = { 111*10277393SMatthias Ringwald .periodic_advertising_interval_min = 0x258, // 375 ms 112*10277393SMatthias Ringwald .periodic_advertising_interval_max = 0x258, // 375 ms 113*10277393SMatthias Ringwald .periodic_advertising_properties = 0 114*10277393SMatthias Ringwald }; 115*10277393SMatthias Ringwald 116*10277393SMatthias Ringwald static uint8_t periodic_adv_data_1[] = { 117*10277393SMatthias Ringwald // 16 bit service data 118*10277393SMatthias Ringwald 37, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 119*10277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 120*10277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 121*10277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 122*10277393SMatthias Ringwald 0x01, // Num_Subgroups 123*10277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 124*10277393SMatthias Ringwald // offset 8 125*10277393SMatthias Ringwald 0x01, // The number of BISes in this subgroup 126*10277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 127*10277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 128*10277393SMatthias Ringwald // Codec_Specific_Configuration[i] = 8_2 129*10277393SMatthias Ringwald // offset 15 130*10277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 131*10277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 132*10277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 133*10277393SMatthias Ringwald 4, // Metadata_Length[i] 134*10277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[i] 135*10277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 136*10277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 137*10277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 138*10277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 139*10277393SMatthias Ringwald }; 140*10277393SMatthias Ringwald 141*10277393SMatthias Ringwald static uint8_t periodic_adv_data_2[] = { 142*10277393SMatthias Ringwald // 16 bit service data 143*10277393SMatthias Ringwald 37+8, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 144*10277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 145*10277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 146*10277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 147*10277393SMatthias Ringwald 0x01, // Num_Subgroups 148*10277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 149*10277393SMatthias Ringwald // offset 8 150*10277393SMatthias Ringwald 0x02, // The number of BISes in this subgroup 151*10277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 152*10277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 153*10277393SMatthias Ringwald // Codec_Specific_Configuration[0] = 8_2 154*10277393SMatthias Ringwald // offset 15 155*10277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 156*10277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 157*10277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 158*10277393SMatthias Ringwald 4, // Metadata_Length[i] 159*10277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[0] 160*10277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 161*10277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 162*10277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 163*10277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, // Codec_Specific_Configuration[i[k]] 164*10277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 165*10277393SMatthias Ringwald 0x02, // BIS_index[i[k]] 166*10277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 167*10277393SMatthias Ringwald 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 168*10277393SMatthias Ringwald }; 169*10277393SMatthias Ringwald 170*10277393SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz 171*10277393SMatthias Ringwald static const int16_t sine_int16[] = { 172*10277393SMatthias Ringwald 0, 643, 1286, 1929, 2571, 3212, 3851, 4489, 5126, 5760, 173*10277393SMatthias Ringwald 6393, 7022, 7649, 8273, 8894, 9512, 10126, 10735, 11341, 11943, 174*10277393SMatthias Ringwald 12539, 13131, 13718, 14300, 14876, 15446, 16011, 16569, 17121, 17666, 175*10277393SMatthias Ringwald 18204, 18736, 19260, 19777, 20286, 20787, 21280, 21766, 22242, 22710, 176*10277393SMatthias Ringwald 23170, 23620, 24062, 24494, 24916, 25329, 25732, 26126, 26509, 26882, 177*10277393SMatthias Ringwald 27245, 27597, 27938, 28269, 28589, 28898, 29196, 29482, 29757, 30021, 178*10277393SMatthias Ringwald 30273, 30513, 30742, 30958, 31163, 31356, 31537, 31705, 31862, 32006, 179*10277393SMatthias Ringwald 32137, 32257, 32364, 32458, 32540, 32609, 32666, 32710, 32742, 32761, 180*10277393SMatthias Ringwald 32767, 32761, 32742, 32710, 32666, 32609, 32540, 32458, 32364, 32257, 181*10277393SMatthias Ringwald 32137, 32006, 31862, 31705, 31537, 31356, 31163, 30958, 30742, 30513, 182*10277393SMatthias Ringwald 30273, 30021, 29757, 29482, 29196, 28898, 28589, 28269, 27938, 27597, 183*10277393SMatthias Ringwald 27245, 26882, 26509, 26126, 25732, 25329, 24916, 24494, 24062, 23620, 184*10277393SMatthias Ringwald 23170, 22710, 22242, 21766, 21280, 20787, 20286, 19777, 19260, 18736, 185*10277393SMatthias Ringwald 18204, 17666, 17121, 16569, 16011, 15446, 14876, 14300, 13718, 13131, 186*10277393SMatthias Ringwald 12539, 11943, 11341, 10735, 10126, 9512, 8894, 8273, 7649, 7022, 187*10277393SMatthias Ringwald 6393, 5760, 5126, 4489, 3851, 3212, 2571, 1929, 1286, 643, 188*10277393SMatthias Ringwald 0, -643, -1286, -1929, -2571, -3212, -3851, -4489, -5126, -5760, 189*10277393SMatthias Ringwald -6393, -7022, -7649, -8273, -8894, -9512, -10126, -10735, -11341, -11943, 190*10277393SMatthias Ringwald -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666, 191*10277393SMatthias Ringwald -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710, 192*10277393SMatthias Ringwald -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882, 193*10277393SMatthias Ringwald -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021, 194*10277393SMatthias Ringwald -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006, 195*10277393SMatthias Ringwald -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761, 196*10277393SMatthias Ringwald -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257, 197*10277393SMatthias Ringwald -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513, 198*10277393SMatthias Ringwald -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597, 199*10277393SMatthias Ringwald -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620, 200*10277393SMatthias Ringwald -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736, 201*10277393SMatthias Ringwald -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131, 202*10277393SMatthias Ringwald -12539, -11943, -11341, -10735, -10126, -9512, -8894, -8273, -7649, -7022, 203*10277393SMatthias Ringwald -6393, -5760, -5126, -4489, -3851, -3212, -2571, -1929, -1286, -643, 204*10277393SMatthias Ringwald }; 205*10277393SMatthias Ringwald 206*10277393SMatthias Ringwald static bd_addr_t remote; 207*10277393SMatthias Ringwald static const char * remote_addr_string = "00:1B:DC:08:E2:72"; 208*10277393SMatthias Ringwald 209*10277393SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 210*10277393SMatthias Ringwald 211*10277393SMatthias Ringwald static uint8_t adv_handle = 0; 212*10277393SMatthias Ringwald static unsigned int next_bis_index; 213*10277393SMatthias Ringwald static hci_con_handle_t bis_con_handles[MAX_NUM_BIS]; 214*10277393SMatthias Ringwald static uint16_t packet_sequence_numbers[MAX_NUM_BIS]; 215*10277393SMatthias Ringwald static uint8_t framed_pdus; 216*10277393SMatthias Ringwald static bool bis_can_send[MAX_NUM_BIS]; 217*10277393SMatthias Ringwald static bool bis_has_data[MAX_NUM_BIS]; 218*10277393SMatthias Ringwald static uint8_t iso_frame_counter; 219*10277393SMatthias Ringwald static uint16_t frame_duration_us; 220*10277393SMatthias Ringwald 221*10277393SMatthias Ringwald // time stamping 222*10277393SMatthias Ringwald #ifdef COUNT_MODE 223*10277393SMatthias Ringwald #define MAX_PACKET_INTERVAL_BINS_MS 50 224*10277393SMatthias Ringwald static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS]; 225*10277393SMatthias Ringwald static uint32_t send_last_ms; 226*10277393SMatthias Ringwald #endif 227*10277393SMatthias Ringwald 228*10277393SMatthias Ringwald // time based sender 229*10277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 230*10277393SMatthias Ringwald static uint32_t next_send_time_ms; 231*10277393SMatthias Ringwald static uint32_t next_send_time_additional_us; 232*10277393SMatthias Ringwald static btstack_timer_source_t send_timer; 233*10277393SMatthias Ringwald #endif 234*10277393SMatthias Ringwald 235*10277393SMatthias Ringwald // lc3 codec config 236*10277393SMatthias Ringwald static uint32_t sampling_frequency_hz; 237*10277393SMatthias Ringwald static lc3_frame_duration_t frame_duration; 238*10277393SMatthias Ringwald static uint16_t number_samples_per_frame; 239*10277393SMatthias Ringwald static uint16_t octets_per_frame; 240*10277393SMatthias Ringwald static uint8_t num_bis = 1; 241*10277393SMatthias Ringwald 242*10277393SMatthias Ringwald // lc3 encoder 243*10277393SMatthias Ringwald static const lc3_encoder_t * lc3_encoder; 244*10277393SMatthias Ringwald static lc3_encoder_ehima_t encoder_contexts[MAX_NUM_BIS]; 245*10277393SMatthias Ringwald static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 246*10277393SMatthias Ringwald static uint32_t time_generation_ms; 247*10277393SMatthias Ringwald 248*10277393SMatthias Ringwald // codec menu 249*10277393SMatthias Ringwald static uint8_t menu_sampling_frequency; 250*10277393SMatthias Ringwald static uint8_t menu_variant; 251*10277393SMatthias Ringwald 252*10277393SMatthias Ringwald // mod player 253*10277393SMatthias Ringwald static int hxcmod_initialized; 254*10277393SMatthias Ringwald static modcontext mod_context; 255*10277393SMatthias Ringwald static tracker_buffer_state trkbuf; 256*10277393SMatthias Ringwald static int16_t mod_pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 257*10277393SMatthias Ringwald 258*10277393SMatthias Ringwald // sine generator 259*10277393SMatthias Ringwald static uint8_t sine_step; 260*10277393SMatthias Ringwald static uint16_t sine_phases[MAX_NUM_BIS]; 261*10277393SMatthias Ringwald 262*10277393SMatthias Ringwald // audio producer 263*10277393SMatthias Ringwald static enum { 264*10277393SMatthias Ringwald AUDIO_SOURCE_SINE, 265*10277393SMatthias Ringwald AUDIO_SOURCE_MODPLAYER 266*10277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER; 267*10277393SMatthias Ringwald 268*10277393SMatthias Ringwald static enum { 269*10277393SMatthias Ringwald APP_IDLE, 270*10277393SMatthias Ringwald APP_W4_PERIODIC_ENABLED, 271*10277393SMatthias Ringwald APP_CREATE_BIG, 272*10277393SMatthias Ringwald APP_W4_CREATE_BIG_COMPLETE, 273*10277393SMatthias Ringwald APP_SET_ISO_PATH, 274*10277393SMatthias Ringwald APP_STREAMING 275*10277393SMatthias Ringwald } app_state = APP_IDLE; 276*10277393SMatthias Ringwald 277*10277393SMatthias Ringwald // enumerate default codec configs 278*10277393SMatthias Ringwald static struct { 279*10277393SMatthias Ringwald uint32_t samplingrate_hz; 280*10277393SMatthias Ringwald uint8_t samplingrate_index; 281*10277393SMatthias Ringwald uint8_t num_variants; 282*10277393SMatthias Ringwald struct { 283*10277393SMatthias Ringwald const char * name; 284*10277393SMatthias Ringwald lc3_frame_duration_t frame_duration; 285*10277393SMatthias Ringwald uint16_t octets_per_frame; 286*10277393SMatthias Ringwald } variants[6]; 287*10277393SMatthias Ringwald } codec_configurations[] = { 288*10277393SMatthias Ringwald { 289*10277393SMatthias Ringwald 8000, 0x01, 2, 290*10277393SMatthias Ringwald { 291*10277393SMatthias Ringwald { "8_1", LC3_FRAME_DURATION_7500US, 26}, 292*10277393SMatthias Ringwald { "8_2", LC3_FRAME_DURATION_10000US, 30} 293*10277393SMatthias Ringwald } 294*10277393SMatthias Ringwald }, 295*10277393SMatthias Ringwald { 296*10277393SMatthias Ringwald 16000, 0x03, 2, 297*10277393SMatthias Ringwald { 298*10277393SMatthias Ringwald { "16_1", LC3_FRAME_DURATION_7500US, 30}, 299*10277393SMatthias Ringwald { "16_2", LC3_FRAME_DURATION_10000US, 40} 300*10277393SMatthias Ringwald } 301*10277393SMatthias Ringwald }, 302*10277393SMatthias Ringwald { 303*10277393SMatthias Ringwald 24000, 0x05, 2, 304*10277393SMatthias Ringwald { 305*10277393SMatthias Ringwald { "24_1", LC3_FRAME_DURATION_7500US, 45}, 306*10277393SMatthias Ringwald { "24_2", LC3_FRAME_DURATION_10000US, 60} 307*10277393SMatthias Ringwald } 308*10277393SMatthias Ringwald }, 309*10277393SMatthias Ringwald { 310*10277393SMatthias Ringwald 32000, 0x06, 2, 311*10277393SMatthias Ringwald { 312*10277393SMatthias Ringwald { "32_1", LC3_FRAME_DURATION_7500US, 60}, 313*10277393SMatthias Ringwald { "32_2", LC3_FRAME_DURATION_10000US, 80} 314*10277393SMatthias Ringwald } 315*10277393SMatthias Ringwald }, 316*10277393SMatthias Ringwald { 317*10277393SMatthias Ringwald 44100, 0x07, 2, 318*10277393SMatthias Ringwald { 319*10277393SMatthias Ringwald { "441_1", LC3_FRAME_DURATION_7500US, 97}, 320*10277393SMatthias Ringwald { "441_2", LC3_FRAME_DURATION_10000US, 130} 321*10277393SMatthias Ringwald } 322*10277393SMatthias Ringwald }, 323*10277393SMatthias Ringwald { 324*10277393SMatthias Ringwald 48000, 0x08, 6, 325*10277393SMatthias Ringwald { 326*10277393SMatthias Ringwald { "48_1", LC3_FRAME_DURATION_7500US, 75}, 327*10277393SMatthias Ringwald { "48_2", LC3_FRAME_DURATION_10000US, 100}, 328*10277393SMatthias Ringwald { "48_3", LC3_FRAME_DURATION_7500US, 90}, 329*10277393SMatthias Ringwald { "48_4", LC3_FRAME_DURATION_10000US, 120}, 330*10277393SMatthias Ringwald { "48_5", LC3_FRAME_DURATION_7500US, 117}, 331*10277393SMatthias Ringwald { "48_6", LC3_FRAME_DURATION_10000US, 155} 332*10277393SMatthias Ringwald } 333*10277393SMatthias Ringwald }, 334*10277393SMatthias Ringwald }; 335*10277393SMatthias Ringwald 336*10277393SMatthias Ringwald static void show_usage(void); 337*10277393SMatthias Ringwald 338*10277393SMatthias Ringwald static void print_config(void) { 339*10277393SMatthias Ringwald printf("Config '%s_%u': %u, %s ms, %u octets - %s\n", 340*10277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 341*10277393SMatthias Ringwald num_bis, 342*10277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].samplingrate_hz, 343*10277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == LC3_FRAME_DURATION_7500US ? "7.5" : "10", 344*10277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 345*10277393SMatthias Ringwald audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer"); 346*10277393SMatthias Ringwald } 347*10277393SMatthias Ringwald 348*10277393SMatthias Ringwald static void setup_lc3_encoder(void){ 349*10277393SMatthias Ringwald uint8_t channel; 350*10277393SMatthias Ringwald for (channel = 0 ; channel < num_bis ; channel++){ 351*10277393SMatthias Ringwald lc3_encoder_ehima_t * context = &encoder_contexts[channel]; 352*10277393SMatthias Ringwald lc3_encoder = lc3_encoder_ehima_init_instance(context); 353*10277393SMatthias Ringwald lc3_encoder->configure(context, sampling_frequency_hz, frame_duration); 354*10277393SMatthias Ringwald } 355*10277393SMatthias Ringwald number_samples_per_frame = lc3_encoder->get_number_samples_per_frame(&encoder_contexts[0]); 356*10277393SMatthias Ringwald btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 357*10277393SMatthias Ringwald printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 358*10277393SMatthias Ringwald sampling_frequency_hz, frame_duration == LC3_FRAME_DURATION_7500US ? "7.5" : "10", 359*10277393SMatthias Ringwald number_samples_per_frame, octets_per_frame); 360*10277393SMatthias Ringwald } 361*10277393SMatthias Ringwald 362*10277393SMatthias Ringwald static void setup_mod_player(void){ 363*10277393SMatthias Ringwald if (!hxcmod_initialized) { 364*10277393SMatthias Ringwald hxcmod_initialized = hxcmod_init(&mod_context); 365*10277393SMatthias Ringwald btstack_assert(hxcmod_initialized != 0); 366*10277393SMatthias Ringwald } 367*10277393SMatthias Ringwald hxcmod_unload(&mod_context); 368*10277393SMatthias Ringwald hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 369*10277393SMatthias Ringwald hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 370*10277393SMatthias Ringwald } 371*10277393SMatthias Ringwald 372*10277393SMatthias Ringwald static void generate_audio(void){ 373*10277393SMatthias Ringwald uint32_t start_ms = btstack_run_loop_get_time_ms(); 374*10277393SMatthias Ringwald uint16_t sample; 375*10277393SMatthias Ringwald switch (audio_source) { 376*10277393SMatthias Ringwald case AUDIO_SOURCE_SINE: 377*10277393SMatthias Ringwald // generate sine wave for all channels 378*10277393SMatthias Ringwald for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 379*10277393SMatthias Ringwald uint8_t channel; 380*10277393SMatthias Ringwald for (channel = 0; channel < num_bis; channel++) { 381*10277393SMatthias Ringwald int16_t value = sine_int16[sine_phases[channel]] / 4; 382*10277393SMatthias Ringwald pcm[channel * MAX_SAMPLES_PER_FRAME + sample] = value; 383*10277393SMatthias Ringwald sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 384*10277393SMatthias Ringwald if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 385*10277393SMatthias Ringwald sine_phases[channel] = 0; 386*10277393SMatthias Ringwald } 387*10277393SMatthias Ringwald } 388*10277393SMatthias Ringwald } 389*10277393SMatthias Ringwald break; 390*10277393SMatthias Ringwald case AUDIO_SOURCE_MODPLAYER: 391*10277393SMatthias Ringwald // mod player configured for stereo 392*10277393SMatthias Ringwald hxcmod_fillbuffer(&mod_context, (unsigned short *) &mod_pcm[0], number_samples_per_frame, &trkbuf); 393*10277393SMatthias Ringwald uint16_t i; 394*10277393SMatthias Ringwald if (num_bis == 1){ 395*10277393SMatthias Ringwald // stereo -> mono 396*10277393SMatthias Ringwald for (i=0;i<number_samples_per_frame;i++){ 397*10277393SMatthias Ringwald pcm[i] = (mod_pcm[2*i] / 2) + (mod_pcm[2*i+1] / 2); 398*10277393SMatthias Ringwald } 399*10277393SMatthias Ringwald } else { 400*10277393SMatthias Ringwald // sort interleaved samples 401*10277393SMatthias Ringwald for (i=0;i<number_samples_per_frame;i++){ 402*10277393SMatthias Ringwald pcm[i] = mod_pcm[2*i]; 403*10277393SMatthias Ringwald pcm[MAX_SAMPLES_PER_FRAME+i] = mod_pcm[2*i+1]; 404*10277393SMatthias Ringwald } 405*10277393SMatthias Ringwald } 406*10277393SMatthias Ringwald break; 407*10277393SMatthias Ringwald default: 408*10277393SMatthias Ringwald btstack_unreachable(); 409*10277393SMatthias Ringwald break; 410*10277393SMatthias Ringwald } 411*10277393SMatthias Ringwald time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 412*10277393SMatthias Ringwald iso_frame_counter++; 413*10277393SMatthias Ringwald } 414*10277393SMatthias Ringwald 415*10277393SMatthias Ringwald static void encode_and_send(uint8_t bis_index){ 416*10277393SMatthias Ringwald 417*10277393SMatthias Ringwald #ifdef COUNT_MODE 418*10277393SMatthias Ringwald if (bis_index == 0) { 419*10277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 420*10277393SMatthias Ringwald if (send_last_ms != 0) { 421*10277393SMatthias Ringwald uint16_t send_interval_ms = now - send_last_ms; 422*10277393SMatthias Ringwald if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 423*10277393SMatthias Ringwald printf("ERROR: send interval %u\n", send_interval_ms); 424*10277393SMatthias Ringwald } else { 425*10277393SMatthias Ringwald send_time_bins[send_interval_ms]++; 426*10277393SMatthias Ringwald } 427*10277393SMatthias Ringwald } 428*10277393SMatthias Ringwald send_last_ms = now; 429*10277393SMatthias Ringwald } 430*10277393SMatthias Ringwald #endif 431*10277393SMatthias Ringwald bool ok = hci_reserve_packet_buffer(); 432*10277393SMatthias Ringwald btstack_assert(ok); 433*10277393SMatthias Ringwald uint8_t * buffer = hci_get_outgoing_packet_buffer(); 434*10277393SMatthias Ringwald // complete SDU, no TimeStamp 435*10277393SMatthias Ringwald little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 436*10277393SMatthias Ringwald // len 437*10277393SMatthias Ringwald little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 438*10277393SMatthias Ringwald // TimeStamp if TS flag is set 439*10277393SMatthias Ringwald // packet seq nr 440*10277393SMatthias Ringwald little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 441*10277393SMatthias Ringwald // iso sdu len 442*10277393SMatthias Ringwald little_endian_store_16(buffer, 6, octets_per_frame); 443*10277393SMatthias Ringwald #ifdef COUNT_MODE 444*10277393SMatthias Ringwald // test data: bis_index, counter 445*10277393SMatthias Ringwald buffer[8] = bis_index; 446*10277393SMatthias Ringwald memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 447*10277393SMatthias Ringwald #else 448*10277393SMatthias Ringwald // encode as lc3 449*10277393SMatthias Ringwald lc3_encoder->encode(&encoder_contexts[bis_index], &pcm[bis_index * MAX_SAMPLES_PER_FRAME], &buffer[8], octets_per_frame); 450*10277393SMatthias Ringwald #endif 451*10277393SMatthias Ringwald // send 452*10277393SMatthias Ringwald hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 453*10277393SMatthias Ringwald 454*10277393SMatthias Ringwald if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 455*10277393SMatthias Ringwald printf("Encoding time: %u\n", time_generation_ms); 456*10277393SMatthias Ringwald } 457*10277393SMatthias Ringwald if ((packet_sequence_numbers[bis_index] & 0x7c) == 0){ 458*10277393SMatthias Ringwald printf("%04x %10u %u ", packet_sequence_numbers[bis_index], btstack_run_loop_get_time_ms(), bis_index); 459*10277393SMatthias Ringwald printf_hexdump(&buffer[8], octets_per_frame); 460*10277393SMatthias Ringwald } 461*10277393SMatthias Ringwald 462*10277393SMatthias Ringwald packet_sequence_numbers[bis_index]++; 463*10277393SMatthias Ringwald } 464*10277393SMatthias Ringwald 465*10277393SMatthias Ringwald static void try_send(void){ 466*10277393SMatthias Ringwald bool all_can_send = true; 467*10277393SMatthias Ringwald uint8_t i; 468*10277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 469*10277393SMatthias Ringwald all_can_send &= bis_can_send[i]; 470*10277393SMatthias Ringwald } 471*10277393SMatthias Ringwald #ifdef PTS_MODE 472*10277393SMatthias Ringwald static uint8_t next_sender; 473*10277393SMatthias Ringwald // PTS 8.2 sends a packet after the previous one was received -> it sends at half speed for stereo configuration 474*10277393SMatthias Ringwald if (all_can_send) { 475*10277393SMatthias Ringwald if (next_sender == 0) { 476*10277393SMatthias Ringwald generate_audio(); 477*10277393SMatthias Ringwald } 478*10277393SMatthias Ringwald bis_can_send[next_sender] = false; 479*10277393SMatthias Ringwald encode_and_send(next_sender); 480*10277393SMatthias Ringwald next_sender = (num_bis - 1) - next_sender; 481*10277393SMatthias Ringwald } 482*10277393SMatthias Ringwald #else 483*10277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 484*10277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 485*10277393SMatthias Ringwald if (hci_is_packet_buffer_reserved()) return; 486*10277393SMatthias Ringwald if (bis_has_data[i]){ 487*10277393SMatthias Ringwald bis_can_send[i] = false; 488*10277393SMatthias Ringwald bis_has_data[i] = false; 489*10277393SMatthias Ringwald encode_and_send(i); 490*10277393SMatthias Ringwald return; 491*10277393SMatthias Ringwald } 492*10277393SMatthias Ringwald } 493*10277393SMatthias Ringwald #else 494*10277393SMatthias Ringwald // check if next audio frame should be produced and send 495*10277393SMatthias Ringwald if (all_can_send){ 496*10277393SMatthias Ringwald generate_audio(); 497*10277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 498*10277393SMatthias Ringwald bis_has_data[i] = true; 499*10277393SMatthias Ringwald } 500*10277393SMatthias Ringwald } 501*10277393SMatthias Ringwald 502*10277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 503*10277393SMatthias Ringwald if (hci_is_packet_buffer_reserved()) return; 504*10277393SMatthias Ringwald if (bis_can_send[i] && bis_has_data[i]){ 505*10277393SMatthias Ringwald bis_can_send[i] = false; 506*10277393SMatthias Ringwald bis_has_data[i] = false; 507*10277393SMatthias Ringwald encode_and_send(i); 508*10277393SMatthias Ringwald return; 509*10277393SMatthias Ringwald } 510*10277393SMatthias Ringwald } 511*10277393SMatthias Ringwald #endif 512*10277393SMatthias Ringwald #endif 513*10277393SMatthias Ringwald } 514*10277393SMatthias Ringwald 515*10277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 516*10277393SMatthias Ringwald static void generate_audio_timer_handler(btstack_timer_source_t *ts){ 517*10277393SMatthias Ringwald 518*10277393SMatthias Ringwald generate_audio(); 519*10277393SMatthias Ringwald 520*10277393SMatthias Ringwald uint8_t i; 521*10277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 522*10277393SMatthias Ringwald bis_has_data[i] = true; 523*10277393SMatthias Ringwald } 524*10277393SMatthias Ringwald 525*10277393SMatthias Ringwald // next send time based on frame_duration_us 526*10277393SMatthias Ringwald next_send_time_additional_us += frame_duration_us % 1000; 527*10277393SMatthias Ringwald if (next_send_time_additional_us > 1000){ 528*10277393SMatthias Ringwald next_send_time_ms++; 529*10277393SMatthias Ringwald next_send_time_additional_us -= 1000; 530*10277393SMatthias Ringwald } 531*10277393SMatthias Ringwald next_send_time_ms += frame_duration_us / 1000; 532*10277393SMatthias Ringwald 533*10277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 534*10277393SMatthias Ringwald btstack_run_loop_set_timer(&send_timer, next_send_time_ms - now); 535*10277393SMatthias Ringwald btstack_run_loop_add_timer(&send_timer); 536*10277393SMatthias Ringwald 537*10277393SMatthias Ringwald try_send(); 538*10277393SMatthias Ringwald } 539*10277393SMatthias Ringwald #endif 540*10277393SMatthias Ringwald 541*10277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 542*10277393SMatthias Ringwald UNUSED(channel); 543*10277393SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 544*10277393SMatthias Ringwald 545*10277393SMatthias Ringwald switch (packet[0]) { 546*10277393SMatthias Ringwald case BTSTACK_EVENT_STATE: 547*10277393SMatthias Ringwald switch(btstack_event_state_get_state(packet)) { 548*10277393SMatthias Ringwald case HCI_STATE_WORKING: 549*10277393SMatthias Ringwald show_usage(); 550*10277393SMatthias Ringwald printf("Please select sample frequency and variation, then start broadcast\n"); 551*10277393SMatthias Ringwald break; 552*10277393SMatthias Ringwald case HCI_STATE_OFF: 553*10277393SMatthias Ringwald printf("Goodbye\n"); 554*10277393SMatthias Ringwald exit(0); 555*10277393SMatthias Ringwald break; 556*10277393SMatthias Ringwald default: 557*10277393SMatthias Ringwald break; 558*10277393SMatthias Ringwald } 559*10277393SMatthias Ringwald break; 560*10277393SMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 561*10277393SMatthias Ringwald switch (hci_event_command_complete_get_command_opcode(packet)){ 562*10277393SMatthias Ringwald case HCI_OPCODE_HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE: 563*10277393SMatthias Ringwald if (app_state != APP_W4_PERIODIC_ENABLED) break; 564*10277393SMatthias Ringwald app_state = APP_CREATE_BIG; 565*10277393SMatthias Ringwald break; 566*10277393SMatthias Ringwald case HCI_OPCODE_HCI_LE_SETUP_ISO_DATA_PATH: 567*10277393SMatthias Ringwald next_bis_index++; 568*10277393SMatthias Ringwald if (next_bis_index == num_bis){ 569*10277393SMatthias Ringwald printf("%u ISO path(s) set up\n", num_bis); 570*10277393SMatthias Ringwald // ready to send 571*10277393SMatthias Ringwald uint8_t i; 572*10277393SMatthias Ringwald for (i=0;i<num_bis;i++) { 573*10277393SMatthias Ringwald bis_can_send[i] = true; 574*10277393SMatthias Ringwald } 575*10277393SMatthias Ringwald app_state = APP_STREAMING; 576*10277393SMatthias Ringwald // 577*10277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 578*10277393SMatthias Ringwald btstack_run_loop_set_timer_handler(&send_timer, &generate_audio_timer_handler); 579*10277393SMatthias Ringwald uint32_t next_send_time_ms = btstack_run_loop_get_time_ms() + 10; 580*10277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 581*10277393SMatthias Ringwald btstack_run_loop_set_timer(&send_timer, next_send_time_ms - now); 582*10277393SMatthias Ringwald btstack_run_loop_add_timer(&send_timer); 583*10277393SMatthias Ringwald #endif 584*10277393SMatthias Ringwald } 585*10277393SMatthias Ringwald break; 586*10277393SMatthias Ringwald } 587*10277393SMatthias Ringwald break; 588*10277393SMatthias Ringwald case HCI_EVENT_LE_META: 589*10277393SMatthias Ringwald switch(hci_event_le_meta_get_subevent_code(packet)){ 590*10277393SMatthias Ringwald case HCI_SUBEVENT_LE_CREATE_BIG_COMPLETE: 591*10277393SMatthias Ringwald if (app_state == APP_W4_CREATE_BIG_COMPLETE){ 592*10277393SMatthias Ringwald uint8_t i; 593*10277393SMatthias Ringwald printf("BIS Connection Handles: "); 594*10277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 595*10277393SMatthias Ringwald bis_con_handles[i] = little_endian_read_16(packet, 21 + 2*i); 596*10277393SMatthias Ringwald printf("0x%04x ", bis_con_handles[i]); 597*10277393SMatthias Ringwald } 598*10277393SMatthias Ringwald printf("\n"); 599*10277393SMatthias Ringwald next_bis_index = 0; 600*10277393SMatthias Ringwald app_state = APP_SET_ISO_PATH; 601*10277393SMatthias Ringwald printf("Start streaming\n"); 602*10277393SMatthias Ringwald } 603*10277393SMatthias Ringwald break; 604*10277393SMatthias Ringwald default: 605*10277393SMatthias Ringwald break; 606*10277393SMatthias Ringwald } 607*10277393SMatthias Ringwald break; 608*10277393SMatthias Ringwald case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: 609*10277393SMatthias Ringwald if (size >= 3){ 610*10277393SMatthias Ringwald uint16_t num_handles = packet[2]; 611*10277393SMatthias Ringwald if (size != (3u + num_handles * 4u)) break; 612*10277393SMatthias Ringwald uint16_t offset = 3; 613*10277393SMatthias Ringwald uint16_t i; 614*10277393SMatthias Ringwald for (i=0; i<num_handles;i++) { 615*10277393SMatthias Ringwald hci_con_handle_t handle = little_endian_read_16(packet, offset) & 0x0fffu; 616*10277393SMatthias Ringwald offset += 2u; 617*10277393SMatthias Ringwald uint16_t num_packets = little_endian_read_16(packet, offset); 618*10277393SMatthias Ringwald offset += 2u; 619*10277393SMatthias Ringwald uint8_t j; 620*10277393SMatthias Ringwald for (j=0 ; j<num_bis ; j++){ 621*10277393SMatthias Ringwald if (handle == bis_con_handles[j]){ 622*10277393SMatthias Ringwald // allow to send 623*10277393SMatthias Ringwald bis_can_send[j] = true; 624*10277393SMatthias Ringwald } 625*10277393SMatthias Ringwald } 626*10277393SMatthias Ringwald } 627*10277393SMatthias Ringwald } 628*10277393SMatthias Ringwald break; 629*10277393SMatthias Ringwald default: 630*10277393SMatthias Ringwald break; 631*10277393SMatthias Ringwald } 632*10277393SMatthias Ringwald 633*10277393SMatthias Ringwald const uint8_t broadcast_code[16] = { 0 }; 634*10277393SMatthias Ringwald switch(app_state){ 635*10277393SMatthias Ringwald case APP_CREATE_BIG: 636*10277393SMatthias Ringwald if (hci_can_send_command_packet_now()) { 637*10277393SMatthias Ringwald app_state = APP_W4_CREATE_BIG_COMPLETE; 638*10277393SMatthias Ringwald if (sampling_frequency_hz == 44100){ 639*10277393SMatthias Ringwald framed_pdus = 1; 640*10277393SMatthias Ringwald // same config as for 48k -> frame is longer by 48/44.1 641*10277393SMatthias Ringwald frame_duration_us = frame_duration == LC3_FRAME_DURATION_7500US ? 8163 : 10884; 642*10277393SMatthias Ringwald } else { 643*10277393SMatthias Ringwald framed_pdus = 0; 644*10277393SMatthias Ringwald frame_duration_us = frame_duration == LC3_FRAME_DURATION_7500US ? 7500 : 10000; 645*10277393SMatthias Ringwald } 646*10277393SMatthias Ringwald hci_send_cmd(&hci_le_create_big, 0, adv_handle, num_bis, frame_duration_us, octets_per_frame, 0x1F, 2, 2, 0, framed_pdus, 0, broadcast_code); 647*10277393SMatthias Ringwald } 648*10277393SMatthias Ringwald break; 649*10277393SMatthias Ringwald case APP_SET_ISO_PATH: 650*10277393SMatthias Ringwald if (!hci_can_send_command_packet_now()) break; 651*10277393SMatthias Ringwald hci_send_cmd(&hci_le_setup_iso_data_path, bis_con_handles[next_bis_index], 0, 0, 0, 0, 0, 0, 0, NULL); 652*10277393SMatthias Ringwald break; 653*10277393SMatthias Ringwald default: 654*10277393SMatthias Ringwald break; 655*10277393SMatthias Ringwald } 656*10277393SMatthias Ringwald 657*10277393SMatthias Ringwald try_send(); 658*10277393SMatthias Ringwald } 659*10277393SMatthias Ringwald 660*10277393SMatthias Ringwald static void show_usage(void){ 661*10277393SMatthias Ringwald printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 662*10277393SMatthias Ringwald print_config(); 663*10277393SMatthias Ringwald printf("---\n"); 664*10277393SMatthias Ringwald printf("c - toggle channels\n"); 665*10277393SMatthias Ringwald printf("f - next sampling frequency\n"); 666*10277393SMatthias Ringwald printf("v - next codec variant\n"); 667*10277393SMatthias Ringwald printf("t - toggle sine / modplayer\n"); 668*10277393SMatthias Ringwald printf("s - start broadcast\n"); 669*10277393SMatthias Ringwald printf("x - shutdown\n"); 670*10277393SMatthias Ringwald printf("---\n"); 671*10277393SMatthias Ringwald } 672*10277393SMatthias Ringwald 673*10277393SMatthias Ringwald static void stdin_process(char c){ 674*10277393SMatthias Ringwald switch (c){ 675*10277393SMatthias Ringwald case 'c': 676*10277393SMatthias Ringwald if (app_state != APP_IDLE){ 677*10277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 678*10277393SMatthias Ringwald break; 679*10277393SMatthias Ringwald } 680*10277393SMatthias Ringwald num_bis = 3 - num_bis; 681*10277393SMatthias Ringwald print_config(); 682*10277393SMatthias Ringwald break; 683*10277393SMatthias Ringwald case 'f': 684*10277393SMatthias Ringwald if (app_state != APP_IDLE){ 685*10277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 686*10277393SMatthias Ringwald break; 687*10277393SMatthias Ringwald } 688*10277393SMatthias Ringwald menu_sampling_frequency++; 689*10277393SMatthias Ringwald if (menu_sampling_frequency >= 6){ 690*10277393SMatthias Ringwald menu_sampling_frequency = 0; 691*10277393SMatthias Ringwald } 692*10277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 693*10277393SMatthias Ringwald menu_variant = 0; 694*10277393SMatthias Ringwald } 695*10277393SMatthias Ringwald print_config(); 696*10277393SMatthias Ringwald break; 697*10277393SMatthias Ringwald case 'v': 698*10277393SMatthias Ringwald if (app_state != APP_IDLE){ 699*10277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 700*10277393SMatthias Ringwald break; 701*10277393SMatthias Ringwald } 702*10277393SMatthias Ringwald menu_variant++; 703*10277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 704*10277393SMatthias Ringwald menu_variant = 0; 705*10277393SMatthias Ringwald } 706*10277393SMatthias Ringwald print_config(); 707*10277393SMatthias Ringwald break; 708*10277393SMatthias Ringwald case 'x': 709*10277393SMatthias Ringwald #ifdef COUNT_MODE 710*10277393SMatthias Ringwald printf("Send statistic:\n"); 711*10277393SMatthias Ringwald { 712*10277393SMatthias Ringwald uint16_t i; 713*10277393SMatthias Ringwald for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){ 714*10277393SMatthias Ringwald printf("%2u: %5u\n", i, send_time_bins[i]); 715*10277393SMatthias Ringwald } 716*10277393SMatthias Ringwald } 717*10277393SMatthias Ringwald #endif 718*10277393SMatthias Ringwald printf("Shutdown...\n"); 719*10277393SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 720*10277393SMatthias Ringwald break; 721*10277393SMatthias Ringwald case 's': 722*10277393SMatthias Ringwald if (app_state != APP_IDLE){ 723*10277393SMatthias Ringwald printf("Cannot start broadcast - not in idle state\n"); 724*10277393SMatthias Ringwald break; 725*10277393SMatthias Ringwald } 726*10277393SMatthias Ringwald // use values from table 727*10277393SMatthias Ringwald sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 728*10277393SMatthias Ringwald octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 729*10277393SMatthias Ringwald frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 730*10277393SMatthias Ringwald 731*10277393SMatthias Ringwald // get num samples per frame 732*10277393SMatthias Ringwald setup_lc3_encoder(); 733*10277393SMatthias Ringwald 734*10277393SMatthias Ringwald // update BASEs 735*10277393SMatthias Ringwald periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 736*10277393SMatthias Ringwald periodic_adv_data_1[20] = (frame_duration == LC3_FRAME_DURATION_7500US) ? 0 : 1; 737*10277393SMatthias Ringwald little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame); 738*10277393SMatthias Ringwald 739*10277393SMatthias Ringwald periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 740*10277393SMatthias Ringwald periodic_adv_data_2[20] = (frame_duration == LC3_FRAME_DURATION_7500US) ? 0 : 1; 741*10277393SMatthias Ringwald little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame); 742*10277393SMatthias Ringwald 743*10277393SMatthias Ringwald // setup mod player 744*10277393SMatthias Ringwald setup_mod_player(); 745*10277393SMatthias Ringwald 746*10277393SMatthias Ringwald // setup sine generator 747*10277393SMatthias Ringwald if (sampling_frequency_hz == 44100){ 748*10277393SMatthias Ringwald sine_step = 2; 749*10277393SMatthias Ringwald } else { 750*10277393SMatthias Ringwald sine_step = 96000 / sampling_frequency_hz; 751*10277393SMatthias Ringwald } 752*10277393SMatthias Ringwald 753*10277393SMatthias Ringwald // setup 754*10277393SMatthias Ringwald app_state = APP_W4_PERIODIC_ENABLED; 755*10277393SMatthias Ringwald gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 756*10277393SMatthias Ringwald gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 757*10277393SMatthias Ringwald gap_periodic_advertising_set_params(adv_handle, &periodic_params); 758*10277393SMatthias Ringwald switch(num_bis){ 759*10277393SMatthias Ringwald case 1: 760*10277393SMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1); 761*10277393SMatthias Ringwald printf("BASE: "); 762*10277393SMatthias Ringwald printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1)); 763*10277393SMatthias Ringwald break; 764*10277393SMatthias Ringwald case 2: 765*10277393SMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2); 766*10277393SMatthias Ringwald printf("BASE: "); 767*10277393SMatthias Ringwald printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2)); 768*10277393SMatthias Ringwald break; 769*10277393SMatthias Ringwald default: 770*10277393SMatthias Ringwald btstack_unreachable(); 771*10277393SMatthias Ringwald break; 772*10277393SMatthias Ringwald } 773*10277393SMatthias Ringwald gap_periodic_advertising_start(adv_handle, 0); 774*10277393SMatthias Ringwald gap_extended_advertising_start(adv_handle, 0, 0); 775*10277393SMatthias Ringwald break; 776*10277393SMatthias Ringwald case 't': 777*10277393SMatthias Ringwald audio_source = 1 - audio_source; 778*10277393SMatthias Ringwald print_config(); 779*10277393SMatthias Ringwald break; 780*10277393SMatthias Ringwald case '\n': 781*10277393SMatthias Ringwald case '\r': 782*10277393SMatthias Ringwald break; 783*10277393SMatthias Ringwald default: 784*10277393SMatthias Ringwald show_usage(); 785*10277393SMatthias Ringwald break; 786*10277393SMatthias Ringwald } 787*10277393SMatthias Ringwald } 788*10277393SMatthias Ringwald 789*10277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 790*10277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 791*10277393SMatthias Ringwald (void) argv; 792*10277393SMatthias Ringwald (void) argc; 793*10277393SMatthias Ringwald 794*10277393SMatthias Ringwald // register for HCI events 795*10277393SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 796*10277393SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 797*10277393SMatthias Ringwald 798*10277393SMatthias Ringwald // turn on! 799*10277393SMatthias Ringwald hci_power_control(HCI_POWER_ON); 800*10277393SMatthias Ringwald 801*10277393SMatthias Ringwald btstack_stdin_setup(stdin_process); 802*10277393SMatthias Ringwald return 0; 803*10277393SMatthias Ringwald } 804