110277393SMatthias Ringwald /* 210277393SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 310277393SMatthias Ringwald * 410277393SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 510277393SMatthias Ringwald * modification, are permitted provided that the following conditions 610277393SMatthias Ringwald * are met: 710277393SMatthias Ringwald * 810277393SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 910277393SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 1010277393SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 1110277393SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 1210277393SMatthias Ringwald * documentation and/or other materials provided with the distribution. 1310277393SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 1410277393SMatthias Ringwald * contributors may be used to endorse or promote products derived 1510277393SMatthias Ringwald * from this software without specific prior written permission. 1610277393SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 1710277393SMatthias Ringwald * personal benefit and not for any commercial purpose or for 1810277393SMatthias Ringwald * monetary gain. 1910277393SMatthias Ringwald * 2010277393SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 2110277393SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2210277393SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2310277393SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 2410277393SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2510277393SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2610277393SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 2710277393SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2810277393SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2910277393SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 3010277393SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3110277393SMatthias Ringwald * SUCH DAMAGE. 3210277393SMatthias Ringwald * 3310277393SMatthias Ringwald * Please inquire about commercial licensing options at 3410277393SMatthias Ringwald * [email protected] 3510277393SMatthias Ringwald * 3610277393SMatthias Ringwald */ 3710277393SMatthias Ringwald 3810277393SMatthias Ringwald #define BTSTACK_FILE__ "le_audio_broadcast_source.c" 3910277393SMatthias Ringwald 4010277393SMatthias Ringwald /* 4110277393SMatthias Ringwald * LE Audio Broadcast Source 4210277393SMatthias Ringwald */ 4310277393SMatthias Ringwald 4410277393SMatthias Ringwald #include <stdint.h> 4510277393SMatthias Ringwald #include <stdio.h> 4610277393SMatthias Ringwald #include <string.h> 4710277393SMatthias Ringwald #include <btstack_debug.h> 4810277393SMatthias Ringwald 4910277393SMatthias Ringwald #include "bluetooth_data_types.h" 5010277393SMatthias Ringwald #include "btstack_stdin.h" 5110277393SMatthias Ringwald #include "btstack_event.h" 5210277393SMatthias Ringwald #include "btstack_run_loop.h" 5310277393SMatthias Ringwald #include "gap.h" 5410277393SMatthias Ringwald #include "hci.h" 5510277393SMatthias Ringwald #include "hci_cmd.h" 5610277393SMatthias Ringwald #include "hci_dump.h" 572fd68da2SMatthias Ringwald #include "btstack_lc3.h" 58e40ee29aSMatthias Ringwald #include "btstack_lc3_google.h" 5910277393SMatthias Ringwald 6010277393SMatthias Ringwald #include "hxcmod.h" 6110277393SMatthias Ringwald #include "mods/mod.h" 6210277393SMatthias Ringwald 6310277393SMatthias Ringwald // PTS mode 6410277393SMatthias Ringwald // #define PTS_MODE 6510277393SMatthias Ringwald 6610277393SMatthias Ringwald // Count mode - send packet count as test data for manual analysis 6710277393SMatthias Ringwald // #define COUNT_MODE 6810277393SMatthias Ringwald 6910277393SMatthias Ringwald // create audio based on timer instead of num completed packets 7010277393SMatthias Ringwald // #define GENERATE_AUDIO_WITH_TIMER 7110277393SMatthias Ringwald 7210277393SMatthias Ringwald // max config 7310277393SMatthias Ringwald #define MAX_NUM_BIS 2 7410277393SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 7510277393SMatthias Ringwald 7610277393SMatthias Ringwald static const uint8_t adv_sid = 0; 7710277393SMatthias Ringwald 7810277393SMatthias Ringwald static le_advertising_set_t le_advertising_set; 7910277393SMatthias Ringwald 8010277393SMatthias Ringwald static const le_extended_advertising_parameters_t extended_params = { 8110277393SMatthias Ringwald .advertising_event_properties = 0, 8210277393SMatthias Ringwald .primary_advertising_interval_min = 0x4b0, // 750 ms 8310277393SMatthias Ringwald .primary_advertising_interval_max = 0x4b0, // 750 ms 8410277393SMatthias Ringwald .primary_advertising_channel_map = 7, 8510277393SMatthias Ringwald .own_address_type = 0, 8610277393SMatthias Ringwald .peer_address_type = 0, 8710277393SMatthias Ringwald .peer_address = 0, 8810277393SMatthias Ringwald .advertising_filter_policy = 0, 8910277393SMatthias Ringwald .advertising_tx_power = 10, // 10 dBm 9010277393SMatthias Ringwald .primary_advertising_phy = 1, // LE 1M PHY 9110277393SMatthias Ringwald .secondary_advertising_max_skip = 0, 9210277393SMatthias Ringwald .secondary_advertising_phy = 1, // LE 1M PHY 9310277393SMatthias Ringwald .advertising_sid = adv_sid, 9410277393SMatthias Ringwald .scan_request_notification_enable = 0, 9510277393SMatthias Ringwald }; 9610277393SMatthias Ringwald 9710277393SMatthias Ringwald static const uint8_t extended_adv_data[] = { 9810277393SMatthias Ringwald // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID 9910277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18, 0x30, 0x5d, 0x9b, 10010277393SMatthias Ringwald // name 10110277393SMatthias Ringwald #ifdef PTS_MODE 10210277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x' 10310277393SMatthias Ringwald #elif defined(COUNT_MODE) 10410277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T' 10510277393SMatthias Ringwald #else 10610277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e' 10710277393SMatthias Ringwald #endif 10810277393SMatthias Ringwald }; 10910277393SMatthias Ringwald 11010277393SMatthias Ringwald static const le_periodic_advertising_parameters_t periodic_params = { 11110277393SMatthias Ringwald .periodic_advertising_interval_min = 0x258, // 375 ms 11210277393SMatthias Ringwald .periodic_advertising_interval_max = 0x258, // 375 ms 11310277393SMatthias Ringwald .periodic_advertising_properties = 0 11410277393SMatthias Ringwald }; 11510277393SMatthias Ringwald 11610277393SMatthias Ringwald static uint8_t periodic_adv_data_1[] = { 11710277393SMatthias Ringwald // 16 bit service data 11810277393SMatthias Ringwald 37, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 11910277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 12010277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 12110277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 12210277393SMatthias Ringwald 0x01, // Num_Subgroups 12310277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 12410277393SMatthias Ringwald // offset 8 12510277393SMatthias Ringwald 0x01, // The number of BISes in this subgroup 12610277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 12710277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 12810277393SMatthias Ringwald // Codec_Specific_Configuration[i] = 8_2 12910277393SMatthias Ringwald // offset 15 13010277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 13110277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 13210277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 13310277393SMatthias Ringwald 4, // Metadata_Length[i] 13410277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[i] 13510277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 13610277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 13710277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 13810277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 13910277393SMatthias Ringwald }; 14010277393SMatthias Ringwald 14110277393SMatthias Ringwald static uint8_t periodic_adv_data_2[] = { 14210277393SMatthias Ringwald // 16 bit service data 14310277393SMatthias Ringwald 37+8, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 14410277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 14510277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 14610277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 14710277393SMatthias Ringwald 0x01, // Num_Subgroups 14810277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 14910277393SMatthias Ringwald // offset 8 15010277393SMatthias Ringwald 0x02, // The number of BISes in this subgroup 15110277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 15210277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 15310277393SMatthias Ringwald // Codec_Specific_Configuration[0] = 8_2 15410277393SMatthias Ringwald // offset 15 15510277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 15610277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 15710277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 15810277393SMatthias Ringwald 4, // Metadata_Length[i] 15910277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[0] 16010277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 16110277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 16210277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 16310277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, // Codec_Specific_Configuration[i[k]] 16410277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 16510277393SMatthias Ringwald 0x02, // BIS_index[i[k]] 16610277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 16710277393SMatthias Ringwald 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 16810277393SMatthias Ringwald }; 16910277393SMatthias Ringwald 17010277393SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz 17110277393SMatthias Ringwald static const int16_t sine_int16[] = { 17210277393SMatthias Ringwald 0, 643, 1286, 1929, 2571, 3212, 3851, 4489, 5126, 5760, 17310277393SMatthias Ringwald 6393, 7022, 7649, 8273, 8894, 9512, 10126, 10735, 11341, 11943, 17410277393SMatthias Ringwald 12539, 13131, 13718, 14300, 14876, 15446, 16011, 16569, 17121, 17666, 17510277393SMatthias Ringwald 18204, 18736, 19260, 19777, 20286, 20787, 21280, 21766, 22242, 22710, 17610277393SMatthias Ringwald 23170, 23620, 24062, 24494, 24916, 25329, 25732, 26126, 26509, 26882, 17710277393SMatthias Ringwald 27245, 27597, 27938, 28269, 28589, 28898, 29196, 29482, 29757, 30021, 17810277393SMatthias Ringwald 30273, 30513, 30742, 30958, 31163, 31356, 31537, 31705, 31862, 32006, 17910277393SMatthias Ringwald 32137, 32257, 32364, 32458, 32540, 32609, 32666, 32710, 32742, 32761, 18010277393SMatthias Ringwald 32767, 32761, 32742, 32710, 32666, 32609, 32540, 32458, 32364, 32257, 18110277393SMatthias Ringwald 32137, 32006, 31862, 31705, 31537, 31356, 31163, 30958, 30742, 30513, 18210277393SMatthias Ringwald 30273, 30021, 29757, 29482, 29196, 28898, 28589, 28269, 27938, 27597, 18310277393SMatthias Ringwald 27245, 26882, 26509, 26126, 25732, 25329, 24916, 24494, 24062, 23620, 18410277393SMatthias Ringwald 23170, 22710, 22242, 21766, 21280, 20787, 20286, 19777, 19260, 18736, 18510277393SMatthias Ringwald 18204, 17666, 17121, 16569, 16011, 15446, 14876, 14300, 13718, 13131, 18610277393SMatthias Ringwald 12539, 11943, 11341, 10735, 10126, 9512, 8894, 8273, 7649, 7022, 18710277393SMatthias Ringwald 6393, 5760, 5126, 4489, 3851, 3212, 2571, 1929, 1286, 643, 18810277393SMatthias Ringwald 0, -643, -1286, -1929, -2571, -3212, -3851, -4489, -5126, -5760, 18910277393SMatthias Ringwald -6393, -7022, -7649, -8273, -8894, -9512, -10126, -10735, -11341, -11943, 19010277393SMatthias Ringwald -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666, 19110277393SMatthias Ringwald -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710, 19210277393SMatthias Ringwald -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882, 19310277393SMatthias Ringwald -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021, 19410277393SMatthias Ringwald -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006, 19510277393SMatthias Ringwald -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761, 19610277393SMatthias Ringwald -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257, 19710277393SMatthias Ringwald -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513, 19810277393SMatthias Ringwald -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597, 19910277393SMatthias Ringwald -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620, 20010277393SMatthias Ringwald -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736, 20110277393SMatthias Ringwald -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131, 20210277393SMatthias Ringwald -12539, -11943, -11341, -10735, -10126, -9512, -8894, -8273, -7649, -7022, 20310277393SMatthias Ringwald -6393, -5760, -5126, -4489, -3851, -3212, -2571, -1929, -1286, -643, 20410277393SMatthias Ringwald }; 20510277393SMatthias Ringwald 20610277393SMatthias Ringwald static bd_addr_t remote; 20710277393SMatthias Ringwald static const char * remote_addr_string = "00:1B:DC:08:E2:72"; 20810277393SMatthias Ringwald 20910277393SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 21010277393SMatthias Ringwald 21110277393SMatthias Ringwald static uint8_t adv_handle = 0; 21210277393SMatthias Ringwald static unsigned int next_bis_index; 21310277393SMatthias Ringwald static hci_con_handle_t bis_con_handles[MAX_NUM_BIS]; 21410277393SMatthias Ringwald static uint16_t packet_sequence_numbers[MAX_NUM_BIS]; 21510277393SMatthias Ringwald static uint8_t framed_pdus; 21610277393SMatthias Ringwald static bool bis_can_send[MAX_NUM_BIS]; 21710277393SMatthias Ringwald static bool bis_has_data[MAX_NUM_BIS]; 21810277393SMatthias Ringwald static uint8_t iso_frame_counter; 21910277393SMatthias Ringwald static uint16_t frame_duration_us; 22010277393SMatthias Ringwald 221cd0bedb1SMatthias Ringwald static le_audio_big_t big_storage; 222cd0bedb1SMatthias Ringwald static le_audio_big_params_t big_params; 223cd0bedb1SMatthias Ringwald 22410277393SMatthias Ringwald // time stamping 22510277393SMatthias Ringwald #ifdef COUNT_MODE 22610277393SMatthias Ringwald #define MAX_PACKET_INTERVAL_BINS_MS 50 22710277393SMatthias Ringwald static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS]; 22810277393SMatthias Ringwald static uint32_t send_last_ms; 22910277393SMatthias Ringwald #endif 23010277393SMatthias Ringwald 23110277393SMatthias Ringwald // time based sender 23210277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 23310277393SMatthias Ringwald static uint32_t next_send_time_ms; 23410277393SMatthias Ringwald static uint32_t next_send_time_additional_us; 23510277393SMatthias Ringwald static btstack_timer_source_t send_timer; 23610277393SMatthias Ringwald #endif 23710277393SMatthias Ringwald 23810277393SMatthias Ringwald // lc3 codec config 23910277393SMatthias Ringwald static uint32_t sampling_frequency_hz; 2402fd68da2SMatthias Ringwald static btstack_lc3_frame_duration_t frame_duration; 24110277393SMatthias Ringwald static uint16_t number_samples_per_frame; 24210277393SMatthias Ringwald static uint16_t octets_per_frame; 24310277393SMatthias Ringwald static uint8_t num_bis = 1; 24410277393SMatthias Ringwald 24510277393SMatthias Ringwald // lc3 encoder 2462fd68da2SMatthias Ringwald static const btstack_lc3_encoder_t * lc3_encoder; 247e40ee29aSMatthias Ringwald static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS]; 24810277393SMatthias Ringwald static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 24910277393SMatthias Ringwald static uint32_t time_generation_ms; 25010277393SMatthias Ringwald 25110277393SMatthias Ringwald // codec menu 25210277393SMatthias Ringwald static uint8_t menu_sampling_frequency; 25310277393SMatthias Ringwald static uint8_t menu_variant; 25410277393SMatthias Ringwald 25510277393SMatthias Ringwald // mod player 25610277393SMatthias Ringwald static int hxcmod_initialized; 25710277393SMatthias Ringwald static modcontext mod_context; 25810277393SMatthias Ringwald static tracker_buffer_state trkbuf; 25910277393SMatthias Ringwald 26010277393SMatthias Ringwald // sine generator 26110277393SMatthias Ringwald static uint8_t sine_step; 26210277393SMatthias Ringwald static uint16_t sine_phases[MAX_NUM_BIS]; 26310277393SMatthias Ringwald 26410277393SMatthias Ringwald // audio producer 26510277393SMatthias Ringwald static enum { 26610277393SMatthias Ringwald AUDIO_SOURCE_SINE, 26710277393SMatthias Ringwald AUDIO_SOURCE_MODPLAYER 26810277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER; 26910277393SMatthias Ringwald 27010277393SMatthias Ringwald static enum { 27110277393SMatthias Ringwald APP_IDLE, 27210277393SMatthias Ringwald APP_W4_PERIODIC_ENABLED, 27310277393SMatthias Ringwald APP_W4_CREATE_BIG_COMPLETE, 274*b9b9e477SMatthias Ringwald APP_STREAMING, 275*b9b9e477SMatthias Ringwald APP_W4_POWER_OFF, 27610277393SMatthias Ringwald } app_state = APP_IDLE; 27710277393SMatthias Ringwald 27810277393SMatthias Ringwald // enumerate default codec configs 27910277393SMatthias Ringwald static struct { 28010277393SMatthias Ringwald uint32_t samplingrate_hz; 28110277393SMatthias Ringwald uint8_t samplingrate_index; 28210277393SMatthias Ringwald uint8_t num_variants; 28310277393SMatthias Ringwald struct { 28410277393SMatthias Ringwald const char * name; 2852fd68da2SMatthias Ringwald btstack_lc3_frame_duration_t frame_duration; 28610277393SMatthias Ringwald uint16_t octets_per_frame; 28710277393SMatthias Ringwald } variants[6]; 28810277393SMatthias Ringwald } codec_configurations[] = { 28910277393SMatthias Ringwald { 29010277393SMatthias Ringwald 8000, 0x01, 2, 29110277393SMatthias Ringwald { 2922fd68da2SMatthias Ringwald { "8_1", BTSTACK_LC3_FRAME_DURATION_7500US, 26}, 2932fd68da2SMatthias Ringwald { "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30} 29410277393SMatthias Ringwald } 29510277393SMatthias Ringwald }, 29610277393SMatthias Ringwald { 29710277393SMatthias Ringwald 16000, 0x03, 2, 29810277393SMatthias Ringwald { 2992fd68da2SMatthias Ringwald { "16_1", BTSTACK_LC3_FRAME_DURATION_7500US, 30}, 3002fd68da2SMatthias Ringwald { "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40} 30110277393SMatthias Ringwald } 30210277393SMatthias Ringwald }, 30310277393SMatthias Ringwald { 30410277393SMatthias Ringwald 24000, 0x05, 2, 30510277393SMatthias Ringwald { 3062fd68da2SMatthias Ringwald { "24_1", BTSTACK_LC3_FRAME_DURATION_7500US, 45}, 3072fd68da2SMatthias Ringwald { "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60} 30810277393SMatthias Ringwald } 30910277393SMatthias Ringwald }, 31010277393SMatthias Ringwald { 31110277393SMatthias Ringwald 32000, 0x06, 2, 31210277393SMatthias Ringwald { 3132fd68da2SMatthias Ringwald { "32_1", BTSTACK_LC3_FRAME_DURATION_7500US, 60}, 3142fd68da2SMatthias Ringwald { "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80} 31510277393SMatthias Ringwald } 31610277393SMatthias Ringwald }, 31710277393SMatthias Ringwald { 31810277393SMatthias Ringwald 44100, 0x07, 2, 31910277393SMatthias Ringwald { 3202fd68da2SMatthias Ringwald { "441_1", BTSTACK_LC3_FRAME_DURATION_7500US, 97}, 3212fd68da2SMatthias Ringwald { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130} 32210277393SMatthias Ringwald } 32310277393SMatthias Ringwald }, 32410277393SMatthias Ringwald { 32510277393SMatthias Ringwald 48000, 0x08, 6, 32610277393SMatthias Ringwald { 3272fd68da2SMatthias Ringwald { "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75}, 3282fd68da2SMatthias Ringwald { "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100}, 3292fd68da2SMatthias Ringwald { "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90}, 3302fd68da2SMatthias Ringwald { "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120}, 3312fd68da2SMatthias Ringwald { "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117}, 3322fd68da2SMatthias Ringwald { "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155} 33310277393SMatthias Ringwald } 33410277393SMatthias Ringwald }, 33510277393SMatthias Ringwald }; 33610277393SMatthias Ringwald 33710277393SMatthias Ringwald static void show_usage(void); 33810277393SMatthias Ringwald 33910277393SMatthias Ringwald static void print_config(void) { 34010277393SMatthias Ringwald printf("Config '%s_%u': %u, %s ms, %u octets - %s\n", 34110277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 34210277393SMatthias Ringwald num_bis, 34310277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].samplingrate_hz, 3442fd68da2SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 34510277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 34610277393SMatthias Ringwald audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer"); 34710277393SMatthias Ringwald } 34810277393SMatthias Ringwald 34910277393SMatthias Ringwald static void setup_lc3_encoder(void){ 35010277393SMatthias Ringwald uint8_t channel; 35110277393SMatthias Ringwald for (channel = 0 ; channel < num_bis ; channel++){ 352e40ee29aSMatthias Ringwald btstack_lc3_encoder_google_t * context = &encoder_contexts[channel]; 353e40ee29aSMatthias Ringwald lc3_encoder = btstack_lc3_encoder_google_init_instance(context); 35410277393SMatthias Ringwald lc3_encoder->configure(context, sampling_frequency_hz, frame_duration); 35510277393SMatthias Ringwald } 35610277393SMatthias Ringwald number_samples_per_frame = lc3_encoder->get_number_samples_per_frame(&encoder_contexts[0]); 35710277393SMatthias Ringwald btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 35810277393SMatthias Ringwald printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 3592fd68da2SMatthias Ringwald sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 36010277393SMatthias Ringwald number_samples_per_frame, octets_per_frame); 36110277393SMatthias Ringwald } 36210277393SMatthias Ringwald 36310277393SMatthias Ringwald static void setup_mod_player(void){ 36410277393SMatthias Ringwald if (!hxcmod_initialized) { 36510277393SMatthias Ringwald hxcmod_initialized = hxcmod_init(&mod_context); 36610277393SMatthias Ringwald btstack_assert(hxcmod_initialized != 0); 36710277393SMatthias Ringwald } 36810277393SMatthias Ringwald hxcmod_unload(&mod_context); 36910277393SMatthias Ringwald hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 37010277393SMatthias Ringwald hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 37110277393SMatthias Ringwald } 37210277393SMatthias Ringwald 37310277393SMatthias Ringwald static void generate_audio(void){ 37410277393SMatthias Ringwald uint32_t start_ms = btstack_run_loop_get_time_ms(); 37510277393SMatthias Ringwald uint16_t sample; 37610277393SMatthias Ringwald switch (audio_source) { 37710277393SMatthias Ringwald case AUDIO_SOURCE_SINE: 37810277393SMatthias Ringwald // generate sine wave for all channels 37910277393SMatthias Ringwald for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 38010277393SMatthias Ringwald uint8_t channel; 38110277393SMatthias Ringwald for (channel = 0; channel < num_bis; channel++) { 38210277393SMatthias Ringwald int16_t value = sine_int16[sine_phases[channel]] / 4; 383c3e2434dSMatthias Ringwald pcm[sample * num_bis + channel] = value; 38410277393SMatthias Ringwald sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 38510277393SMatthias Ringwald if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 38610277393SMatthias Ringwald sine_phases[channel] = 0; 38710277393SMatthias Ringwald } 38810277393SMatthias Ringwald } 38910277393SMatthias Ringwald } 39010277393SMatthias Ringwald break; 39110277393SMatthias Ringwald case AUDIO_SOURCE_MODPLAYER: 39210277393SMatthias Ringwald // mod player configured for stereo 393c3e2434dSMatthias Ringwald hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf); 39410277393SMatthias Ringwald if (num_bis == 1) { 39510277393SMatthias Ringwald // stereo -> mono 396c3e2434dSMatthias Ringwald uint16_t i; 39710277393SMatthias Ringwald for (i=0;i<number_samples_per_frame;i++){ 398c3e2434dSMatthias Ringwald pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2); 39910277393SMatthias Ringwald } 40010277393SMatthias Ringwald } 40110277393SMatthias Ringwald break; 40210277393SMatthias Ringwald default: 40310277393SMatthias Ringwald btstack_unreachable(); 40410277393SMatthias Ringwald break; 40510277393SMatthias Ringwald } 40610277393SMatthias Ringwald time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 40710277393SMatthias Ringwald iso_frame_counter++; 40810277393SMatthias Ringwald } 40910277393SMatthias Ringwald 41010277393SMatthias Ringwald static void encode_and_send(uint8_t bis_index){ 41110277393SMatthias Ringwald 41210277393SMatthias Ringwald #ifdef COUNT_MODE 41310277393SMatthias Ringwald if (bis_index == 0) { 41410277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 41510277393SMatthias Ringwald if (send_last_ms != 0) { 41610277393SMatthias Ringwald uint16_t send_interval_ms = now - send_last_ms; 41710277393SMatthias Ringwald if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 41810277393SMatthias Ringwald printf("ERROR: send interval %u\n", send_interval_ms); 41910277393SMatthias Ringwald } else { 42010277393SMatthias Ringwald send_time_bins[send_interval_ms]++; 42110277393SMatthias Ringwald } 42210277393SMatthias Ringwald } 42310277393SMatthias Ringwald send_last_ms = now; 42410277393SMatthias Ringwald } 42510277393SMatthias Ringwald #endif 42610277393SMatthias Ringwald bool ok = hci_reserve_packet_buffer(); 42710277393SMatthias Ringwald btstack_assert(ok); 42810277393SMatthias Ringwald uint8_t * buffer = hci_get_outgoing_packet_buffer(); 42910277393SMatthias Ringwald // complete SDU, no TimeStamp 43010277393SMatthias Ringwald little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 43110277393SMatthias Ringwald // len 43210277393SMatthias Ringwald little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 43310277393SMatthias Ringwald // TimeStamp if TS flag is set 43410277393SMatthias Ringwald // packet seq nr 43510277393SMatthias Ringwald little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 43610277393SMatthias Ringwald // iso sdu len 43710277393SMatthias Ringwald little_endian_store_16(buffer, 6, octets_per_frame); 43810277393SMatthias Ringwald #ifdef COUNT_MODE 43910277393SMatthias Ringwald // test data: bis_index, counter 44010277393SMatthias Ringwald buffer[8] = bis_index; 44110277393SMatthias Ringwald memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 44210277393SMatthias Ringwald #else 44310277393SMatthias Ringwald // encode as lc3 444c3e2434dSMatthias Ringwald lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &buffer[8], octets_per_frame); 44510277393SMatthias Ringwald #endif 44610277393SMatthias Ringwald // send 44710277393SMatthias Ringwald hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 44810277393SMatthias Ringwald 44910277393SMatthias Ringwald if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 45010277393SMatthias Ringwald printf("Encoding time: %u\n", time_generation_ms); 45110277393SMatthias Ringwald } 45210277393SMatthias Ringwald if ((packet_sequence_numbers[bis_index] & 0x7c) == 0){ 45310277393SMatthias Ringwald printf("%04x %10u %u ", packet_sequence_numbers[bis_index], btstack_run_loop_get_time_ms(), bis_index); 45410277393SMatthias Ringwald printf_hexdump(&buffer[8], octets_per_frame); 45510277393SMatthias Ringwald } 45610277393SMatthias Ringwald 45710277393SMatthias Ringwald packet_sequence_numbers[bis_index]++; 45810277393SMatthias Ringwald } 45910277393SMatthias Ringwald 46010277393SMatthias Ringwald static void try_send(void){ 461*b9b9e477SMatthias Ringwald if (app_state != APP_STREAMING) return; 462*b9b9e477SMatthias Ringwald 46310277393SMatthias Ringwald bool all_can_send = true; 46410277393SMatthias Ringwald uint8_t i; 46510277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 46610277393SMatthias Ringwald all_can_send &= bis_can_send[i]; 46710277393SMatthias Ringwald } 46810277393SMatthias Ringwald #ifdef PTS_MODE 46910277393SMatthias Ringwald static uint8_t next_sender; 47010277393SMatthias Ringwald // PTS 8.2 sends a packet after the previous one was received -> it sends at half speed for stereo configuration 47110277393SMatthias Ringwald if (all_can_send) { 47210277393SMatthias Ringwald if (next_sender == 0) { 47310277393SMatthias Ringwald generate_audio(); 47410277393SMatthias Ringwald } 47510277393SMatthias Ringwald bis_can_send[next_sender] = false; 47610277393SMatthias Ringwald encode_and_send(next_sender); 47710277393SMatthias Ringwald next_sender = (num_bis - 1) - next_sender; 47810277393SMatthias Ringwald } 47910277393SMatthias Ringwald #else 48010277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 48110277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 48210277393SMatthias Ringwald if (hci_is_packet_buffer_reserved()) return; 48310277393SMatthias Ringwald if (bis_has_data[i]){ 48410277393SMatthias Ringwald bis_can_send[i] = false; 48510277393SMatthias Ringwald bis_has_data[i] = false; 48610277393SMatthias Ringwald encode_and_send(i); 48710277393SMatthias Ringwald return; 48810277393SMatthias Ringwald } 48910277393SMatthias Ringwald } 49010277393SMatthias Ringwald #else 49110277393SMatthias Ringwald // check if next audio frame should be produced and send 49210277393SMatthias Ringwald if (all_can_send){ 49310277393SMatthias Ringwald generate_audio(); 49410277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 49510277393SMatthias Ringwald bis_has_data[i] = true; 49610277393SMatthias Ringwald } 49710277393SMatthias Ringwald } 49810277393SMatthias Ringwald 49910277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 50010277393SMatthias Ringwald if (hci_is_packet_buffer_reserved()) return; 50110277393SMatthias Ringwald if (bis_can_send[i] && bis_has_data[i]){ 50210277393SMatthias Ringwald bis_can_send[i] = false; 50310277393SMatthias Ringwald bis_has_data[i] = false; 50410277393SMatthias Ringwald encode_and_send(i); 50510277393SMatthias Ringwald return; 50610277393SMatthias Ringwald } 50710277393SMatthias Ringwald } 50810277393SMatthias Ringwald #endif 50910277393SMatthias Ringwald #endif 51010277393SMatthias Ringwald } 51110277393SMatthias Ringwald 51210277393SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 51310277393SMatthias Ringwald static void generate_audio_timer_handler(btstack_timer_source_t *ts){ 51410277393SMatthias Ringwald 51510277393SMatthias Ringwald generate_audio(); 51610277393SMatthias Ringwald 51710277393SMatthias Ringwald uint8_t i; 51810277393SMatthias Ringwald for (i=0; i<num_bis;i++) { 51910277393SMatthias Ringwald bis_has_data[i] = true; 52010277393SMatthias Ringwald } 52110277393SMatthias Ringwald 52210277393SMatthias Ringwald // next send time based on frame_duration_us 52310277393SMatthias Ringwald next_send_time_additional_us += frame_duration_us % 1000; 52410277393SMatthias Ringwald if (next_send_time_additional_us > 1000){ 52510277393SMatthias Ringwald next_send_time_ms++; 52610277393SMatthias Ringwald next_send_time_additional_us -= 1000; 52710277393SMatthias Ringwald } 52810277393SMatthias Ringwald next_send_time_ms += frame_duration_us / 1000; 52910277393SMatthias Ringwald 53010277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 53110277393SMatthias Ringwald btstack_run_loop_set_timer(&send_timer, next_send_time_ms - now); 53210277393SMatthias Ringwald btstack_run_loop_add_timer(&send_timer); 53310277393SMatthias Ringwald 53410277393SMatthias Ringwald try_send(); 53510277393SMatthias Ringwald } 53610277393SMatthias Ringwald #endif 53710277393SMatthias Ringwald 538cd0bedb1SMatthias Ringwald static void create_big(void){ 539cd0bedb1SMatthias Ringwald // Create BIG 540cd0bedb1SMatthias Ringwald big_params.big_handle = 0; 541cd0bedb1SMatthias Ringwald big_params.advertising_handle = adv_handle; 542cd0bedb1SMatthias Ringwald big_params.num_bis = num_bis; 543cd0bedb1SMatthias Ringwald big_params.max_sdu = octets_per_frame; 544cd0bedb1SMatthias Ringwald big_params.max_transport_latency_ms = 31; 545cd0bedb1SMatthias Ringwald big_params.rtn = 2; 546cd0bedb1SMatthias Ringwald big_params.phy = 2; 547cd0bedb1SMatthias Ringwald big_params.packing = 0; 548cd0bedb1SMatthias Ringwald big_params.encryption = 0; 549cd0bedb1SMatthias Ringwald memset(big_params.broadcast_code, 0, 16); 550cd0bedb1SMatthias Ringwald if (sampling_frequency_hz == 44100){ 551cd0bedb1SMatthias Ringwald // same config as for 48k -> frame is longer by 48/44.1 552cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 553cd0bedb1SMatthias Ringwald big_params.framing = 1; 554cd0bedb1SMatthias Ringwald } else { 555cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 556cd0bedb1SMatthias Ringwald big_params.framing = 0; 557cd0bedb1SMatthias Ringwald } 558cd0bedb1SMatthias Ringwald app_state = APP_W4_CREATE_BIG_COMPLETE; 559cd0bedb1SMatthias Ringwald gap_big_create(&big_storage, &big_params); 560cd0bedb1SMatthias Ringwald } 561cd0bedb1SMatthias Ringwald 562cd0bedb1SMatthias Ringwald static void ready_to_send(void){ 563cd0bedb1SMatthias Ringwald // ready to send 564cd0bedb1SMatthias Ringwald uint8_t i; 565cd0bedb1SMatthias Ringwald for (i=0;i<num_bis;i++) { 566cd0bedb1SMatthias Ringwald bis_can_send[i] = true; 567cd0bedb1SMatthias Ringwald } 568cd0bedb1SMatthias Ringwald app_state = APP_STREAMING; 569cd0bedb1SMatthias Ringwald // 570cd0bedb1SMatthias Ringwald #ifdef GENERATE_AUDIO_WITH_TIMER 571cd0bedb1SMatthias Ringwald btstack_run_loop_set_timer_handler(&send_timer, &generate_audio_timer_handler); 572cd0bedb1SMatthias Ringwald uint32_t next_send_time_ms = btstack_run_loop_get_time_ms() + 10; 573cd0bedb1SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 574cd0bedb1SMatthias Ringwald btstack_run_loop_set_timer(&send_timer, next_send_time_ms - now); 575cd0bedb1SMatthias Ringwald btstack_run_loop_add_timer(&send_timer); 576cd0bedb1SMatthias Ringwald #endif 577cd0bedb1SMatthias Ringwald } 578cd0bedb1SMatthias Ringwald 57910277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 58010277393SMatthias Ringwald UNUSED(channel); 58110277393SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 58210277393SMatthias Ringwald 58310277393SMatthias Ringwald switch (packet[0]) { 58410277393SMatthias Ringwald case BTSTACK_EVENT_STATE: 58510277393SMatthias Ringwald switch(btstack_event_state_get_state(packet)) { 58610277393SMatthias Ringwald case HCI_STATE_WORKING: 58710277393SMatthias Ringwald show_usage(); 58810277393SMatthias Ringwald printf("Please select sample frequency and variation, then start broadcast\n"); 58910277393SMatthias Ringwald break; 59010277393SMatthias Ringwald case HCI_STATE_OFF: 59110277393SMatthias Ringwald printf("Goodbye\n"); 59210277393SMatthias Ringwald exit(0); 59310277393SMatthias Ringwald break; 59410277393SMatthias Ringwald default: 59510277393SMatthias Ringwald break; 59610277393SMatthias Ringwald } 59710277393SMatthias Ringwald break; 59810277393SMatthias Ringwald case HCI_EVENT_COMMAND_COMPLETE: 59910277393SMatthias Ringwald switch (hci_event_command_complete_get_command_opcode(packet)){ 60010277393SMatthias Ringwald case HCI_OPCODE_HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE: 60110277393SMatthias Ringwald if (app_state != APP_W4_PERIODIC_ENABLED) break; 602cd0bedb1SMatthias Ringwald create_big(); 60310277393SMatthias Ringwald break; 604cd0bedb1SMatthias Ringwald default: 605cd0bedb1SMatthias Ringwald break; 606cd0bedb1SMatthias Ringwald } 607cd0bedb1SMatthias Ringwald break; 608cd0bedb1SMatthias Ringwald case HCI_EVENT_META_GAP: 609cd0bedb1SMatthias Ringwald switch (hci_event_gap_meta_get_subevent_code(packet)){ 610cd0bedb1SMatthias Ringwald case GAP_SUBEVENT_BIG_CREATED: { 611cd0bedb1SMatthias Ringwald printf("BIG Created with BIS Connection handles: \n"); 61210277393SMatthias Ringwald uint8_t i; 61310277393SMatthias Ringwald for (i=0;i<num_bis;i++){ 614cd0bedb1SMatthias Ringwald bis_con_handles[i] = gap_subevent_big_created_get_bis_con_handles(packet, i); 61510277393SMatthias Ringwald printf("0x%04x ", bis_con_handles[i]); 61610277393SMatthias Ringwald } 617cd0bedb1SMatthias Ringwald ready_to_send(); 618cd0bedb1SMatthias Ringwald app_state = APP_STREAMING; 61910277393SMatthias Ringwald printf("Start streaming\n"); 62010277393SMatthias Ringwald break; 621cd0bedb1SMatthias Ringwald } 62210277393SMatthias Ringwald default: 62310277393SMatthias Ringwald break; 62410277393SMatthias Ringwald } 62510277393SMatthias Ringwald break; 62610277393SMatthias Ringwald case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: 62710277393SMatthias Ringwald if (size >= 3){ 62810277393SMatthias Ringwald uint16_t num_handles = packet[2]; 62910277393SMatthias Ringwald if (size != (3u + num_handles * 4u)) break; 63010277393SMatthias Ringwald uint16_t offset = 3; 63110277393SMatthias Ringwald uint16_t i; 63210277393SMatthias Ringwald for (i=0; i<num_handles;i++) { 63310277393SMatthias Ringwald hci_con_handle_t handle = little_endian_read_16(packet, offset) & 0x0fffu; 63410277393SMatthias Ringwald offset += 2u; 63510277393SMatthias Ringwald uint16_t num_packets = little_endian_read_16(packet, offset); 63610277393SMatthias Ringwald offset += 2u; 63710277393SMatthias Ringwald uint8_t j; 63810277393SMatthias Ringwald for (j=0 ; j<num_bis ; j++){ 63910277393SMatthias Ringwald if (handle == bis_con_handles[j]){ 64010277393SMatthias Ringwald // allow to send 64110277393SMatthias Ringwald bis_can_send[j] = true; 64210277393SMatthias Ringwald } 64310277393SMatthias Ringwald } 64410277393SMatthias Ringwald } 64510277393SMatthias Ringwald } 64610277393SMatthias Ringwald break; 64710277393SMatthias Ringwald default: 64810277393SMatthias Ringwald break; 64910277393SMatthias Ringwald } 65010277393SMatthias Ringwald 65110277393SMatthias Ringwald try_send(); 65210277393SMatthias Ringwald } 65310277393SMatthias Ringwald 65410277393SMatthias Ringwald static void show_usage(void){ 65510277393SMatthias Ringwald printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 65610277393SMatthias Ringwald print_config(); 65710277393SMatthias Ringwald printf("---\n"); 65810277393SMatthias Ringwald printf("c - toggle channels\n"); 65910277393SMatthias Ringwald printf("f - next sampling frequency\n"); 66010277393SMatthias Ringwald printf("v - next codec variant\n"); 66110277393SMatthias Ringwald printf("t - toggle sine / modplayer\n"); 66210277393SMatthias Ringwald printf("s - start broadcast\n"); 66310277393SMatthias Ringwald printf("x - shutdown\n"); 66410277393SMatthias Ringwald printf("---\n"); 66510277393SMatthias Ringwald } 66610277393SMatthias Ringwald 66710277393SMatthias Ringwald static void stdin_process(char c){ 66810277393SMatthias Ringwald switch (c){ 66910277393SMatthias Ringwald case 'c': 67010277393SMatthias Ringwald if (app_state != APP_IDLE){ 67110277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 67210277393SMatthias Ringwald break; 67310277393SMatthias Ringwald } 67410277393SMatthias Ringwald num_bis = 3 - num_bis; 67510277393SMatthias Ringwald print_config(); 67610277393SMatthias Ringwald break; 67710277393SMatthias Ringwald case 'f': 67810277393SMatthias Ringwald if (app_state != APP_IDLE){ 67910277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 68010277393SMatthias Ringwald break; 68110277393SMatthias Ringwald } 68210277393SMatthias Ringwald menu_sampling_frequency++; 68310277393SMatthias Ringwald if (menu_sampling_frequency >= 6){ 68410277393SMatthias Ringwald menu_sampling_frequency = 0; 68510277393SMatthias Ringwald } 68610277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 68710277393SMatthias Ringwald menu_variant = 0; 68810277393SMatthias Ringwald } 68910277393SMatthias Ringwald print_config(); 69010277393SMatthias Ringwald break; 69110277393SMatthias Ringwald case 'v': 69210277393SMatthias Ringwald if (app_state != APP_IDLE){ 69310277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 69410277393SMatthias Ringwald break; 69510277393SMatthias Ringwald } 69610277393SMatthias Ringwald menu_variant++; 69710277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 69810277393SMatthias Ringwald menu_variant = 0; 69910277393SMatthias Ringwald } 70010277393SMatthias Ringwald print_config(); 70110277393SMatthias Ringwald break; 70210277393SMatthias Ringwald case 'x': 70310277393SMatthias Ringwald #ifdef COUNT_MODE 70410277393SMatthias Ringwald printf("Send statistic:\n"); 70510277393SMatthias Ringwald { 70610277393SMatthias Ringwald uint16_t i; 70710277393SMatthias Ringwald for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){ 70810277393SMatthias Ringwald printf("%2u: %5u\n", i, send_time_bins[i]); 70910277393SMatthias Ringwald } 71010277393SMatthias Ringwald } 71110277393SMatthias Ringwald #endif 71210277393SMatthias Ringwald printf("Shutdown...\n"); 713*b9b9e477SMatthias Ringwald app_state = APP_W4_POWER_OFF; 71410277393SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 71510277393SMatthias Ringwald break; 71610277393SMatthias Ringwald case 's': 71710277393SMatthias Ringwald if (app_state != APP_IDLE){ 71810277393SMatthias Ringwald printf("Cannot start broadcast - not in idle state\n"); 71910277393SMatthias Ringwald break; 72010277393SMatthias Ringwald } 72110277393SMatthias Ringwald // use values from table 72210277393SMatthias Ringwald sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 72310277393SMatthias Ringwald octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 72410277393SMatthias Ringwald frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 72510277393SMatthias Ringwald 72610277393SMatthias Ringwald // get num samples per frame 72710277393SMatthias Ringwald setup_lc3_encoder(); 72810277393SMatthias Ringwald 72910277393SMatthias Ringwald // update BASEs 73010277393SMatthias Ringwald periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 7312fd68da2SMatthias Ringwald periodic_adv_data_1[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 73210277393SMatthias Ringwald little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame); 73310277393SMatthias Ringwald 73410277393SMatthias Ringwald periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 7352fd68da2SMatthias Ringwald periodic_adv_data_2[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 73610277393SMatthias Ringwald little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame); 73710277393SMatthias Ringwald 73810277393SMatthias Ringwald // setup mod player 73910277393SMatthias Ringwald setup_mod_player(); 74010277393SMatthias Ringwald 74110277393SMatthias Ringwald // setup sine generator 74210277393SMatthias Ringwald if (sampling_frequency_hz == 44100){ 74310277393SMatthias Ringwald sine_step = 2; 74410277393SMatthias Ringwald } else { 74510277393SMatthias Ringwald sine_step = 96000 / sampling_frequency_hz; 74610277393SMatthias Ringwald } 74710277393SMatthias Ringwald 74810277393SMatthias Ringwald // setup 74910277393SMatthias Ringwald app_state = APP_W4_PERIODIC_ENABLED; 75010277393SMatthias Ringwald gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 75110277393SMatthias Ringwald gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 75210277393SMatthias Ringwald gap_periodic_advertising_set_params(adv_handle, &periodic_params); 75310277393SMatthias Ringwald switch(num_bis){ 75410277393SMatthias Ringwald case 1: 75510277393SMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1); 75610277393SMatthias Ringwald printf("BASE: "); 75710277393SMatthias Ringwald printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1)); 75810277393SMatthias Ringwald break; 75910277393SMatthias Ringwald case 2: 76010277393SMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2); 76110277393SMatthias Ringwald printf("BASE: "); 76210277393SMatthias Ringwald printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2)); 76310277393SMatthias Ringwald break; 76410277393SMatthias Ringwald default: 76510277393SMatthias Ringwald btstack_unreachable(); 76610277393SMatthias Ringwald break; 76710277393SMatthias Ringwald } 76810277393SMatthias Ringwald gap_periodic_advertising_start(adv_handle, 0); 76910277393SMatthias Ringwald gap_extended_advertising_start(adv_handle, 0, 0); 77010277393SMatthias Ringwald break; 77110277393SMatthias Ringwald case 't': 77210277393SMatthias Ringwald audio_source = 1 - audio_source; 77310277393SMatthias Ringwald print_config(); 77410277393SMatthias Ringwald break; 77510277393SMatthias Ringwald case '\n': 77610277393SMatthias Ringwald case '\r': 77710277393SMatthias Ringwald break; 77810277393SMatthias Ringwald default: 77910277393SMatthias Ringwald show_usage(); 78010277393SMatthias Ringwald break; 78110277393SMatthias Ringwald } 78210277393SMatthias Ringwald } 78310277393SMatthias Ringwald 78410277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 78510277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 78610277393SMatthias Ringwald (void) argv; 78710277393SMatthias Ringwald (void) argc; 78810277393SMatthias Ringwald 78910277393SMatthias Ringwald // register for HCI events 79010277393SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 79110277393SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 79210277393SMatthias Ringwald 79310277393SMatthias Ringwald // turn on! 79410277393SMatthias Ringwald hci_power_control(HCI_POWER_ON); 79510277393SMatthias Ringwald 79610277393SMatthias Ringwald btstack_stdin_setup(stdin_process); 79710277393SMatthias Ringwald return 0; 79810277393SMatthias Ringwald } 799