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 // max config 7010277393SMatthias Ringwald #define MAX_NUM_BIS 2 7110277393SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 723f485d09SMatthias Ringwald #define MAX_LC3_FRAME_BYTES 155 7310277393SMatthias Ringwald 7410277393SMatthias Ringwald static const uint8_t adv_sid = 0; 7510277393SMatthias Ringwald 7610277393SMatthias Ringwald static le_advertising_set_t le_advertising_set; 7710277393SMatthias Ringwald 7810277393SMatthias Ringwald static const le_extended_advertising_parameters_t extended_params = { 7910277393SMatthias Ringwald .advertising_event_properties = 0, 8010277393SMatthias Ringwald .primary_advertising_interval_min = 0x4b0, // 750 ms 8110277393SMatthias Ringwald .primary_advertising_interval_max = 0x4b0, // 750 ms 8210277393SMatthias Ringwald .primary_advertising_channel_map = 7, 8310277393SMatthias Ringwald .own_address_type = 0, 8410277393SMatthias Ringwald .peer_address_type = 0, 85c52eeb3dSMatthias Ringwald .peer_address = { 0 }, 8610277393SMatthias Ringwald .advertising_filter_policy = 0, 8710277393SMatthias Ringwald .advertising_tx_power = 10, // 10 dBm 8810277393SMatthias Ringwald .primary_advertising_phy = 1, // LE 1M PHY 8910277393SMatthias Ringwald .secondary_advertising_max_skip = 0, 9010277393SMatthias Ringwald .secondary_advertising_phy = 1, // LE 1M PHY 9110277393SMatthias Ringwald .advertising_sid = adv_sid, 9210277393SMatthias Ringwald .scan_request_notification_enable = 0, 9310277393SMatthias Ringwald }; 9410277393SMatthias Ringwald 9510277393SMatthias Ringwald static const uint8_t extended_adv_data[] = { 9610277393SMatthias Ringwald // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID 9710277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18, 0x30, 0x5d, 0x9b, 9810277393SMatthias Ringwald // name 9910277393SMatthias Ringwald #ifdef PTS_MODE 10010277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x' 10110277393SMatthias Ringwald #elif defined(COUNT_MODE) 10210277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T' 10310277393SMatthias Ringwald #else 10410277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e' 10510277393SMatthias Ringwald #endif 10610277393SMatthias Ringwald }; 10710277393SMatthias Ringwald 10810277393SMatthias Ringwald static const le_periodic_advertising_parameters_t periodic_params = { 10910277393SMatthias Ringwald .periodic_advertising_interval_min = 0x258, // 375 ms 11010277393SMatthias Ringwald .periodic_advertising_interval_max = 0x258, // 375 ms 11110277393SMatthias Ringwald .periodic_advertising_properties = 0 11210277393SMatthias Ringwald }; 11310277393SMatthias Ringwald 11410277393SMatthias Ringwald static uint8_t periodic_adv_data_1[] = { 11510277393SMatthias Ringwald // 16 bit service data 11610277393SMatthias Ringwald 37, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 11710277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 11810277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 11910277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 12010277393SMatthias Ringwald 0x01, // Num_Subgroups 12110277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 12210277393SMatthias Ringwald // offset 8 12310277393SMatthias Ringwald 0x01, // The number of BISes in this subgroup 12410277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 12510277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 12610277393SMatthias Ringwald // Codec_Specific_Configuration[i] = 8_2 12710277393SMatthias Ringwald // offset 15 12810277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 12910277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 13010277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 13110277393SMatthias Ringwald 4, // Metadata_Length[i] 13210277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[i] 13310277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 13410277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 13510277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 13610277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 13710277393SMatthias Ringwald }; 13810277393SMatthias Ringwald 13910277393SMatthias Ringwald static uint8_t periodic_adv_data_2[] = { 14010277393SMatthias Ringwald // 16 bit service data 14110277393SMatthias Ringwald 37+8, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 14210277393SMatthias Ringwald // Level 1 - BIG Parameters (common to all BISes) 14310277393SMatthias Ringwald 0x51, 0x18, // Basic Audio Announcement Service UUID 14410277393SMatthias Ringwald 0x28, 0x00, 0x00, // Presentation Delay 3 14510277393SMatthias Ringwald 0x01, // Num_Subgroups 14610277393SMatthias Ringwald // Level 2 - BIS Subgroup Parameters (common parameters for subgroups of BISes) 14710277393SMatthias Ringwald // offset 8 14810277393SMatthias Ringwald 0x02, // The number of BISes in this subgroup 14910277393SMatthias Ringwald 0x06, 0x00, 0x00, 0x00, 0x00, // 0x06 = LC3, vendor id + codec id = 0 15010277393SMatthias Ringwald 10, // Codec_Specific_Configuration_Length[i] 15110277393SMatthias Ringwald // Codec_Specific_Configuration[0] = 8_2 15210277393SMatthias Ringwald // offset 15 15310277393SMatthias Ringwald 0x02, 0x01, 0x01, // Sampling frequency 0x01 = 0x01 / 8 kHz 15410277393SMatthias Ringwald 0x02, 0x02, 0x01, // Frame Duration 0x02 = 0x01 / 10 ms 15510277393SMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, // Octets per Frame 0x04 = 0x1e / 30 15610277393SMatthias Ringwald 4, // Metadata_Length[i] 15710277393SMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[0] 15810277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 15910277393SMatthias Ringwald 0x01, // BIS_index[i[k]] 16010277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 16110277393SMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00, // Codec_Specific_Configuration[i[k]] 16210277393SMatthias Ringwald // Level 3 - Specific BIS Parameters (if required, for individual BISes) 16310277393SMatthias Ringwald 0x02, // BIS_index[i[k]] 16410277393SMatthias Ringwald 6, // Codec_Specific_Configuration_Length[i[k]] 16510277393SMatthias Ringwald 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 // Codec_Specific_Configuration[i[k]] 16610277393SMatthias Ringwald }; 16710277393SMatthias Ringwald 16810277393SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz 16910277393SMatthias Ringwald static const int16_t sine_int16[] = { 17010277393SMatthias Ringwald 0, 643, 1286, 1929, 2571, 3212, 3851, 4489, 5126, 5760, 17110277393SMatthias Ringwald 6393, 7022, 7649, 8273, 8894, 9512, 10126, 10735, 11341, 11943, 17210277393SMatthias Ringwald 12539, 13131, 13718, 14300, 14876, 15446, 16011, 16569, 17121, 17666, 17310277393SMatthias Ringwald 18204, 18736, 19260, 19777, 20286, 20787, 21280, 21766, 22242, 22710, 17410277393SMatthias Ringwald 23170, 23620, 24062, 24494, 24916, 25329, 25732, 26126, 26509, 26882, 17510277393SMatthias Ringwald 27245, 27597, 27938, 28269, 28589, 28898, 29196, 29482, 29757, 30021, 17610277393SMatthias Ringwald 30273, 30513, 30742, 30958, 31163, 31356, 31537, 31705, 31862, 32006, 17710277393SMatthias Ringwald 32137, 32257, 32364, 32458, 32540, 32609, 32666, 32710, 32742, 32761, 17810277393SMatthias Ringwald 32767, 32761, 32742, 32710, 32666, 32609, 32540, 32458, 32364, 32257, 17910277393SMatthias Ringwald 32137, 32006, 31862, 31705, 31537, 31356, 31163, 30958, 30742, 30513, 18010277393SMatthias Ringwald 30273, 30021, 29757, 29482, 29196, 28898, 28589, 28269, 27938, 27597, 18110277393SMatthias Ringwald 27245, 26882, 26509, 26126, 25732, 25329, 24916, 24494, 24062, 23620, 18210277393SMatthias Ringwald 23170, 22710, 22242, 21766, 21280, 20787, 20286, 19777, 19260, 18736, 18310277393SMatthias Ringwald 18204, 17666, 17121, 16569, 16011, 15446, 14876, 14300, 13718, 13131, 18410277393SMatthias Ringwald 12539, 11943, 11341, 10735, 10126, 9512, 8894, 8273, 7649, 7022, 18510277393SMatthias Ringwald 6393, 5760, 5126, 4489, 3851, 3212, 2571, 1929, 1286, 643, 18610277393SMatthias Ringwald 0, -643, -1286, -1929, -2571, -3212, -3851, -4489, -5126, -5760, 18710277393SMatthias Ringwald -6393, -7022, -7649, -8273, -8894, -9512, -10126, -10735, -11341, -11943, 18810277393SMatthias Ringwald -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666, 18910277393SMatthias Ringwald -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710, 19010277393SMatthias Ringwald -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882, 19110277393SMatthias Ringwald -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021, 19210277393SMatthias Ringwald -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006, 19310277393SMatthias Ringwald -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761, 19410277393SMatthias Ringwald -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257, 19510277393SMatthias Ringwald -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513, 19610277393SMatthias Ringwald -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597, 19710277393SMatthias Ringwald -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620, 19810277393SMatthias Ringwald -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736, 19910277393SMatthias Ringwald -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131, 20010277393SMatthias Ringwald -12539, -11943, -11341, -10735, -10126, -9512, -8894, -8273, -7649, -7022, 20110277393SMatthias Ringwald -6393, -5760, -5126, -4489, -3851, -3212, -2571, -1929, -1286, -643, 20210277393SMatthias Ringwald }; 20310277393SMatthias Ringwald 20410277393SMatthias Ringwald static bd_addr_t remote; 20510277393SMatthias Ringwald static const char * remote_addr_string = "00:1B:DC:08:E2:72"; 20610277393SMatthias Ringwald 20710277393SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 20810277393SMatthias Ringwald 20910277393SMatthias Ringwald static uint8_t adv_handle = 0; 21010277393SMatthias Ringwald static unsigned int next_bis_index; 21110277393SMatthias Ringwald static hci_con_handle_t bis_con_handles[MAX_NUM_BIS]; 21210277393SMatthias Ringwald static uint16_t packet_sequence_numbers[MAX_NUM_BIS]; 21310277393SMatthias Ringwald static uint8_t framed_pdus; 21410277393SMatthias Ringwald static bool bis_can_send[MAX_NUM_BIS]; 21510277393SMatthias Ringwald static bool bis_has_data[MAX_NUM_BIS]; 21610277393SMatthias Ringwald static uint8_t iso_frame_counter; 21710277393SMatthias Ringwald static uint16_t frame_duration_us; 21810277393SMatthias Ringwald 219cd0bedb1SMatthias Ringwald static le_audio_big_t big_storage; 220cd0bedb1SMatthias Ringwald static le_audio_big_params_t big_params; 221cd0bedb1SMatthias Ringwald 22210277393SMatthias Ringwald // time stamping 22310277393SMatthias Ringwald #ifdef COUNT_MODE 22410277393SMatthias Ringwald #define MAX_PACKET_INTERVAL_BINS_MS 50 22510277393SMatthias Ringwald static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS]; 22610277393SMatthias Ringwald static uint32_t send_last_ms; 22710277393SMatthias Ringwald #endif 22810277393SMatthias Ringwald 22910277393SMatthias Ringwald // lc3 codec config 230c52eeb3dSMatthias Ringwald static uint16_t sampling_frequency_hz; 2312fd68da2SMatthias Ringwald static btstack_lc3_frame_duration_t frame_duration; 23210277393SMatthias Ringwald static uint16_t number_samples_per_frame; 23310277393SMatthias Ringwald static uint16_t octets_per_frame; 23410277393SMatthias Ringwald static uint8_t num_bis = 1; 23510277393SMatthias Ringwald 23610277393SMatthias Ringwald // lc3 encoder 2372fd68da2SMatthias Ringwald static const btstack_lc3_encoder_t * lc3_encoder; 238e40ee29aSMatthias Ringwald static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS]; 23910277393SMatthias Ringwald static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 2403f485d09SMatthias Ringwald static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES]; 24110277393SMatthias Ringwald static uint32_t time_generation_ms; 24210277393SMatthias Ringwald 24310277393SMatthias Ringwald // codec menu 24410277393SMatthias Ringwald static uint8_t menu_sampling_frequency; 24510277393SMatthias Ringwald static uint8_t menu_variant; 24610277393SMatthias Ringwald 24710277393SMatthias Ringwald // mod player 24810277393SMatthias Ringwald static int hxcmod_initialized; 24910277393SMatthias Ringwald static modcontext mod_context; 25010277393SMatthias Ringwald static tracker_buffer_state trkbuf; 25110277393SMatthias Ringwald 25210277393SMatthias Ringwald // sine generator 25310277393SMatthias Ringwald static uint8_t sine_step; 25410277393SMatthias Ringwald static uint16_t sine_phases[MAX_NUM_BIS]; 25510277393SMatthias Ringwald 256*ac95ea81SMatthias Ringwald // encryption 257*ac95ea81SMatthias Ringwald static uint8_t encryption = 0; 258*ac95ea81SMatthias Ringwald static uint8_t broadcast_code [] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; 259*ac95ea81SMatthias Ringwald 26010277393SMatthias Ringwald // audio producer 26110277393SMatthias Ringwald static enum { 26210277393SMatthias Ringwald AUDIO_SOURCE_SINE, 26310277393SMatthias Ringwald AUDIO_SOURCE_MODPLAYER 26410277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER; 26510277393SMatthias Ringwald 26610277393SMatthias Ringwald static enum { 26710277393SMatthias Ringwald APP_IDLE, 26810277393SMatthias Ringwald APP_W4_CREATE_BIG_COMPLETE, 269b9b9e477SMatthias Ringwald APP_STREAMING, 270b9b9e477SMatthias Ringwald APP_W4_POWER_OFF, 27110277393SMatthias Ringwald } app_state = APP_IDLE; 27210277393SMatthias Ringwald 27310277393SMatthias Ringwald // enumerate default codec configs 27410277393SMatthias Ringwald static struct { 275c52eeb3dSMatthias Ringwald uint16_t samplingrate_hz; 27610277393SMatthias Ringwald uint8_t samplingrate_index; 27710277393SMatthias Ringwald uint8_t num_variants; 27810277393SMatthias Ringwald struct { 27910277393SMatthias Ringwald const char * name; 2802fd68da2SMatthias Ringwald btstack_lc3_frame_duration_t frame_duration; 28110277393SMatthias Ringwald uint16_t octets_per_frame; 28210277393SMatthias Ringwald } variants[6]; 28310277393SMatthias Ringwald } codec_configurations[] = { 28410277393SMatthias Ringwald { 28510277393SMatthias Ringwald 8000, 0x01, 2, 28610277393SMatthias Ringwald { 2872fd68da2SMatthias Ringwald { "8_1", BTSTACK_LC3_FRAME_DURATION_7500US, 26}, 2882fd68da2SMatthias Ringwald { "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30} 28910277393SMatthias Ringwald } 29010277393SMatthias Ringwald }, 29110277393SMatthias Ringwald { 29210277393SMatthias Ringwald 16000, 0x03, 2, 29310277393SMatthias Ringwald { 2942fd68da2SMatthias Ringwald { "16_1", BTSTACK_LC3_FRAME_DURATION_7500US, 30}, 2952fd68da2SMatthias Ringwald { "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40} 29610277393SMatthias Ringwald } 29710277393SMatthias Ringwald }, 29810277393SMatthias Ringwald { 29910277393SMatthias Ringwald 24000, 0x05, 2, 30010277393SMatthias Ringwald { 3012fd68da2SMatthias Ringwald { "24_1", BTSTACK_LC3_FRAME_DURATION_7500US, 45}, 3022fd68da2SMatthias Ringwald { "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60} 30310277393SMatthias Ringwald } 30410277393SMatthias Ringwald }, 30510277393SMatthias Ringwald { 30610277393SMatthias Ringwald 32000, 0x06, 2, 30710277393SMatthias Ringwald { 3082fd68da2SMatthias Ringwald { "32_1", BTSTACK_LC3_FRAME_DURATION_7500US, 60}, 3092fd68da2SMatthias Ringwald { "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80} 31010277393SMatthias Ringwald } 31110277393SMatthias Ringwald }, 31210277393SMatthias Ringwald { 31310277393SMatthias Ringwald 44100, 0x07, 2, 31410277393SMatthias Ringwald { 3152fd68da2SMatthias Ringwald { "441_1", BTSTACK_LC3_FRAME_DURATION_7500US, 97}, 3162fd68da2SMatthias Ringwald { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130} 31710277393SMatthias Ringwald } 31810277393SMatthias Ringwald }, 31910277393SMatthias Ringwald { 32010277393SMatthias Ringwald 48000, 0x08, 6, 32110277393SMatthias Ringwald { 3222fd68da2SMatthias Ringwald { "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75}, 3232fd68da2SMatthias Ringwald { "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100}, 3242fd68da2SMatthias Ringwald { "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90}, 3252fd68da2SMatthias Ringwald { "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120}, 3262fd68da2SMatthias Ringwald { "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117}, 3272fd68da2SMatthias Ringwald { "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155} 32810277393SMatthias Ringwald } 32910277393SMatthias Ringwald }, 33010277393SMatthias Ringwald }; 33110277393SMatthias Ringwald 33210277393SMatthias Ringwald static void show_usage(void); 33310277393SMatthias Ringwald 33410277393SMatthias Ringwald static void print_config(void) { 335*ac95ea81SMatthias Ringwald printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n", 33610277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 33710277393SMatthias Ringwald num_bis, 33810277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].samplingrate_hz, 3392fd68da2SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 34010277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 341*ac95ea81SMatthias Ringwald audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : ""); 34210277393SMatthias Ringwald } 34310277393SMatthias Ringwald 34410277393SMatthias Ringwald static void setup_lc3_encoder(void){ 34510277393SMatthias Ringwald uint8_t channel; 34610277393SMatthias Ringwald for (channel = 0 ; channel < num_bis ; channel++){ 347e40ee29aSMatthias Ringwald btstack_lc3_encoder_google_t * context = &encoder_contexts[channel]; 348e40ee29aSMatthias Ringwald lc3_encoder = btstack_lc3_encoder_google_init_instance(context); 34910277393SMatthias Ringwald lc3_encoder->configure(context, sampling_frequency_hz, frame_duration); 35010277393SMatthias Ringwald } 35110277393SMatthias Ringwald number_samples_per_frame = lc3_encoder->get_number_samples_per_frame(&encoder_contexts[0]); 35210277393SMatthias Ringwald btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 35310277393SMatthias Ringwald printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 3542fd68da2SMatthias Ringwald sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 35510277393SMatthias Ringwald number_samples_per_frame, octets_per_frame); 35610277393SMatthias Ringwald } 35710277393SMatthias Ringwald 35810277393SMatthias Ringwald static void setup_mod_player(void){ 35910277393SMatthias Ringwald if (!hxcmod_initialized) { 36010277393SMatthias Ringwald hxcmod_initialized = hxcmod_init(&mod_context); 36110277393SMatthias Ringwald btstack_assert(hxcmod_initialized != 0); 36210277393SMatthias Ringwald } 36310277393SMatthias Ringwald hxcmod_unload(&mod_context); 36410277393SMatthias Ringwald hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 36510277393SMatthias Ringwald hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 36610277393SMatthias Ringwald } 36710277393SMatthias Ringwald 36810277393SMatthias Ringwald static void generate_audio(void){ 36910277393SMatthias Ringwald uint32_t start_ms = btstack_run_loop_get_time_ms(); 37010277393SMatthias Ringwald uint16_t sample; 37110277393SMatthias Ringwald switch (audio_source) { 37210277393SMatthias Ringwald case AUDIO_SOURCE_SINE: 37310277393SMatthias Ringwald // generate sine wave for all channels 37410277393SMatthias Ringwald for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 37510277393SMatthias Ringwald uint8_t channel; 37610277393SMatthias Ringwald for (channel = 0; channel < num_bis; channel++) { 37710277393SMatthias Ringwald int16_t value = sine_int16[sine_phases[channel]] / 4; 378c3e2434dSMatthias Ringwald pcm[sample * num_bis + channel] = value; 37910277393SMatthias Ringwald sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 38010277393SMatthias Ringwald if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 38110277393SMatthias Ringwald sine_phases[channel] = 0; 38210277393SMatthias Ringwald } 38310277393SMatthias Ringwald } 38410277393SMatthias Ringwald } 38510277393SMatthias Ringwald break; 38610277393SMatthias Ringwald case AUDIO_SOURCE_MODPLAYER: 38710277393SMatthias Ringwald // mod player configured for stereo 388c3e2434dSMatthias Ringwald hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf); 38910277393SMatthias Ringwald if (num_bis == 1) { 39010277393SMatthias Ringwald // stereo -> mono 391c3e2434dSMatthias Ringwald uint16_t i; 39210277393SMatthias Ringwald for (i=0;i<number_samples_per_frame;i++){ 393c3e2434dSMatthias Ringwald pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2); 39410277393SMatthias Ringwald } 39510277393SMatthias Ringwald } 39610277393SMatthias Ringwald break; 39710277393SMatthias Ringwald default: 39810277393SMatthias Ringwald btstack_unreachable(); 39910277393SMatthias Ringwald break; 40010277393SMatthias Ringwald } 40110277393SMatthias Ringwald time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 40210277393SMatthias Ringwald iso_frame_counter++; 40310277393SMatthias Ringwald } 40410277393SMatthias Ringwald 4053f485d09SMatthias Ringwald static void encode(uint8_t bis_index){ 4063f485d09SMatthias Ringwald // encode as lc3 4073f485d09SMatthias Ringwald lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 4083f485d09SMatthias Ringwald } 4093f485d09SMatthias Ringwald 4103f485d09SMatthias Ringwald 4113f485d09SMatthias Ringwald static void send_iso_packet(uint8_t bis_index) { 41210277393SMatthias Ringwald 41310277393SMatthias Ringwald #ifdef COUNT_MODE 41410277393SMatthias Ringwald if (bis_index == 0) { 41510277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 41610277393SMatthias Ringwald if (send_last_ms != 0) { 41710277393SMatthias Ringwald uint16_t send_interval_ms = now - send_last_ms; 41810277393SMatthias Ringwald if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 41910277393SMatthias Ringwald printf("ERROR: send interval %u\n", send_interval_ms); 42010277393SMatthias Ringwald } else { 42110277393SMatthias Ringwald send_time_bins[send_interval_ms]++; 42210277393SMatthias Ringwald } 42310277393SMatthias Ringwald } 42410277393SMatthias Ringwald send_last_ms = now; 42510277393SMatthias Ringwald } 42610277393SMatthias Ringwald #endif 42710277393SMatthias Ringwald bool ok = hci_reserve_packet_buffer(); 42810277393SMatthias Ringwald btstack_assert(ok); 42910277393SMatthias Ringwald uint8_t * buffer = hci_get_outgoing_packet_buffer(); 43010277393SMatthias Ringwald // complete SDU, no TimeStamp 43110277393SMatthias Ringwald little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 43210277393SMatthias Ringwald // len 43310277393SMatthias Ringwald little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 43410277393SMatthias Ringwald // TimeStamp if TS flag is set 43510277393SMatthias Ringwald // packet seq nr 43610277393SMatthias Ringwald little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 43710277393SMatthias Ringwald // iso sdu len 43810277393SMatthias Ringwald little_endian_store_16(buffer, 6, octets_per_frame); 43910277393SMatthias Ringwald #ifdef COUNT_MODE 44010277393SMatthias Ringwald // test data: bis_index, counter 44110277393SMatthias Ringwald buffer[8] = bis_index; 44210277393SMatthias Ringwald memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 44310277393SMatthias Ringwald #else 4443f485d09SMatthias Ringwald // copy encoded payload 4453f485d09SMatthias Ringwald memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 44610277393SMatthias Ringwald #endif 44710277393SMatthias Ringwald // send 44810277393SMatthias Ringwald hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 44910277393SMatthias Ringwald 4503f485d09SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 45110277393SMatthias Ringwald if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 45210277393SMatthias Ringwald printf("Encoding time: %u\n", time_generation_ms); 45310277393SMatthias Ringwald } 4543f485d09SMatthias Ringwald #endif 45510277393SMatthias Ringwald 45610277393SMatthias Ringwald packet_sequence_numbers[bis_index]++; 45710277393SMatthias Ringwald } 45810277393SMatthias Ringwald 4590be46310SMatthias Ringwald static void generate_audio_and_encode(void){ 46010277393SMatthias Ringwald uint8_t i; 46110277393SMatthias Ringwald generate_audio(); 46210277393SMatthias Ringwald for (i = 0; i < num_bis; i++) { 4630be46310SMatthias Ringwald encode(i); 46410277393SMatthias Ringwald bis_has_data[i] = true; 46510277393SMatthias Ringwald } 46610277393SMatthias Ringwald } 46710277393SMatthias Ringwald 46844959aebSMatthias Ringwald static void setup_advertising() { 46944959aebSMatthias Ringwald gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 47044959aebSMatthias Ringwald gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 47144959aebSMatthias Ringwald gap_periodic_advertising_set_params(adv_handle, &periodic_params); 47244959aebSMatthias Ringwald switch(num_bis){ 47344959aebSMatthias Ringwald case 1: 47444959aebSMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1); 47544959aebSMatthias Ringwald printf("BASE: "); 47644959aebSMatthias Ringwald printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1)); 47744959aebSMatthias Ringwald break; 47844959aebSMatthias Ringwald case 2: 47944959aebSMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2); 48044959aebSMatthias Ringwald printf("BASE: "); 48144959aebSMatthias Ringwald printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2)); 48244959aebSMatthias Ringwald break; 48344959aebSMatthias Ringwald default: 48444959aebSMatthias Ringwald btstack_unreachable(); 48544959aebSMatthias Ringwald break; 48644959aebSMatthias Ringwald } 48744959aebSMatthias Ringwald gap_periodic_advertising_start(adv_handle, 0); 48844959aebSMatthias Ringwald gap_extended_advertising_start(adv_handle, 0, 0); 48944959aebSMatthias Ringwald } 49044959aebSMatthias Ringwald 49144959aebSMatthias Ringwald static void setup_big(void){ 492cd0bedb1SMatthias Ringwald // Create BIG 493cd0bedb1SMatthias Ringwald big_params.big_handle = 0; 494cd0bedb1SMatthias Ringwald big_params.advertising_handle = adv_handle; 495cd0bedb1SMatthias Ringwald big_params.num_bis = num_bis; 496cd0bedb1SMatthias Ringwald big_params.max_sdu = octets_per_frame; 497cd0bedb1SMatthias Ringwald big_params.max_transport_latency_ms = 31; 498cd0bedb1SMatthias Ringwald big_params.rtn = 2; 499cd0bedb1SMatthias Ringwald big_params.phy = 2; 500cd0bedb1SMatthias Ringwald big_params.packing = 0; 501*ac95ea81SMatthias Ringwald big_params.encryption = encryption; 502*ac95ea81SMatthias Ringwald if (encryption) { 503*ac95ea81SMatthias Ringwald memcpy(big_params.broadcast_code, &broadcast_code[0], 16); 504*ac95ea81SMatthias Ringwald } else { 505cd0bedb1SMatthias Ringwald memset(big_params.broadcast_code, 0, 16); 506*ac95ea81SMatthias Ringwald } 507cd0bedb1SMatthias Ringwald if (sampling_frequency_hz == 44100){ 508cd0bedb1SMatthias Ringwald // same config as for 48k -> frame is longer by 48/44.1 509cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 510cd0bedb1SMatthias Ringwald big_params.framing = 1; 511cd0bedb1SMatthias Ringwald } else { 512cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 513cd0bedb1SMatthias Ringwald big_params.framing = 0; 514cd0bedb1SMatthias Ringwald } 515cd0bedb1SMatthias Ringwald app_state = APP_W4_CREATE_BIG_COMPLETE; 516cd0bedb1SMatthias Ringwald gap_big_create(&big_storage, &big_params); 517cd0bedb1SMatthias Ringwald } 518cd0bedb1SMatthias Ringwald 51956c77a86SMatthias Ringwald 52056c77a86SMatthias Ringwald static void start_broadcast() {// use values from table 52156c77a86SMatthias Ringwald sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 52256c77a86SMatthias Ringwald octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 52356c77a86SMatthias Ringwald frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 52456c77a86SMatthias Ringwald 52556c77a86SMatthias Ringwald // get num samples per frame 52656c77a86SMatthias Ringwald setup_lc3_encoder(); 52756c77a86SMatthias Ringwald 52856c77a86SMatthias Ringwald // update BASEs 52956c77a86SMatthias Ringwald periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 53056c77a86SMatthias Ringwald periodic_adv_data_1[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 53156c77a86SMatthias Ringwald little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame); 53256c77a86SMatthias Ringwald 53356c77a86SMatthias Ringwald periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index; 53456c77a86SMatthias Ringwald periodic_adv_data_2[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1; 53556c77a86SMatthias Ringwald little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame); 53656c77a86SMatthias Ringwald 53756c77a86SMatthias Ringwald // setup mod player 53856c77a86SMatthias Ringwald setup_mod_player(); 53956c77a86SMatthias Ringwald 54056c77a86SMatthias Ringwald // setup sine generator 54156c77a86SMatthias Ringwald if (sampling_frequency_hz == 44100){ 54256c77a86SMatthias Ringwald sine_step = 2; 54356c77a86SMatthias Ringwald } else { 54456c77a86SMatthias Ringwald sine_step = 96000 / sampling_frequency_hz; 54556c77a86SMatthias Ringwald } 54656c77a86SMatthias Ringwald 54756c77a86SMatthias Ringwald // setup extended and periodic advertising 54856c77a86SMatthias Ringwald setup_advertising(); 54956c77a86SMatthias Ringwald 55056c77a86SMatthias Ringwald // setup big 55156c77a86SMatthias Ringwald setup_big(); 55256c77a86SMatthias Ringwald } 55356c77a86SMatthias Ringwald 55410277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 55510277393SMatthias Ringwald UNUSED(channel); 55610277393SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 5570be46310SMatthias Ringwald uint8_t bis_index; 55810277393SMatthias Ringwald 55910277393SMatthias Ringwald switch (packet[0]) { 56010277393SMatthias Ringwald case BTSTACK_EVENT_STATE: 56110277393SMatthias Ringwald switch(btstack_event_state_get_state(packet)) { 56210277393SMatthias Ringwald case HCI_STATE_WORKING: 56356c77a86SMatthias Ringwald #ifdef ENABLE_DEMO_MODE 56456c77a86SMatthias Ringwald // start broadcast automatically, mod player, 48_5_1 56556c77a86SMatthias Ringwald num_bis = 1; 56656c77a86SMatthias Ringwald menu_sampling_frequency = 5; 56756c77a86SMatthias Ringwald menu_variant = 4; 56856c77a86SMatthias Ringwald start_broadcast(); 56956c77a86SMatthias Ringwald #else 57010277393SMatthias Ringwald show_usage(); 57110277393SMatthias Ringwald printf("Please select sample frequency and variation, then start broadcast\n"); 57256c77a86SMatthias Ringwald #endif 57310277393SMatthias Ringwald break; 57410277393SMatthias Ringwald case HCI_STATE_OFF: 57510277393SMatthias Ringwald printf("Goodbye\n"); 57610277393SMatthias Ringwald exit(0); 57710277393SMatthias Ringwald break; 57810277393SMatthias Ringwald default: 57910277393SMatthias Ringwald break; 58010277393SMatthias Ringwald } 58110277393SMatthias Ringwald break; 582cd0bedb1SMatthias Ringwald case HCI_EVENT_META_GAP: 583cd0bedb1SMatthias Ringwald switch (hci_event_gap_meta_get_subevent_code(packet)){ 5840be46310SMatthias Ringwald case GAP_SUBEVENT_BIG_CREATED: 585cd0bedb1SMatthias Ringwald printf("BIG Created with BIS Connection handles: \n"); 5860be46310SMatthias Ringwald for (bis_index=0;bis_index<num_bis;bis_index++){ 5870be46310SMatthias Ringwald bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index); 5880be46310SMatthias Ringwald printf("0x%04x ", bis_con_handles[bis_index]); 58910277393SMatthias Ringwald } 59044959aebSMatthias Ringwald 591cd0bedb1SMatthias Ringwald app_state = APP_STREAMING; 59210277393SMatthias Ringwald printf("Start streaming\n"); 5930be46310SMatthias Ringwald generate_audio_and_encode(); 5940be46310SMatthias Ringwald hci_request_bis_can_send_now_events(big_params.big_handle); 59510277393SMatthias Ringwald break; 59610277393SMatthias Ringwald default: 59710277393SMatthias Ringwald break; 59810277393SMatthias Ringwald } 59910277393SMatthias Ringwald break; 6000be46310SMatthias Ringwald case HCI_EVENT_BIS_CAN_SEND_NOW: 6010d718107SMatthias Ringwald bis_index = hci_event_bis_can_send_now_get_bis_index(packet); 6020d718107SMatthias Ringwald send_iso_packet(bis_index); 6030be46310SMatthias Ringwald bis_index++; 6040be46310SMatthias Ringwald if (bis_index == num_bis){ 6050be46310SMatthias Ringwald generate_audio_and_encode(); 6060be46310SMatthias Ringwald hci_request_bis_can_send_now_events(big_params.big_handle); 60710277393SMatthias Ringwald } 60810277393SMatthias Ringwald break; 60910277393SMatthias Ringwald default: 61010277393SMatthias Ringwald break; 61110277393SMatthias Ringwald } 61210277393SMatthias Ringwald } 61310277393SMatthias Ringwald 61410277393SMatthias Ringwald static void show_usage(void){ 61510277393SMatthias Ringwald printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 61610277393SMatthias Ringwald print_config(); 61710277393SMatthias Ringwald printf("---\n"); 61810277393SMatthias Ringwald printf("c - toggle channels\n"); 619*ac95ea81SMatthias Ringwald printf("e - toggle encryption\n"); 62010277393SMatthias Ringwald printf("f - next sampling frequency\n"); 62110277393SMatthias Ringwald printf("v - next codec variant\n"); 62210277393SMatthias Ringwald printf("t - toggle sine / modplayer\n"); 62310277393SMatthias Ringwald printf("s - start broadcast\n"); 62410277393SMatthias Ringwald printf("x - shutdown\n"); 62510277393SMatthias Ringwald printf("---\n"); 62610277393SMatthias Ringwald } 62710277393SMatthias Ringwald static void stdin_process(char c){ 62810277393SMatthias Ringwald switch (c){ 62910277393SMatthias Ringwald case 'c': 63010277393SMatthias Ringwald if (app_state != APP_IDLE){ 63110277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 63210277393SMatthias Ringwald break; 63310277393SMatthias Ringwald } 63410277393SMatthias Ringwald num_bis = 3 - num_bis; 63510277393SMatthias Ringwald print_config(); 63610277393SMatthias Ringwald break; 637*ac95ea81SMatthias Ringwald case 'e': 638*ac95ea81SMatthias Ringwald if (app_state != APP_IDLE){ 639*ac95ea81SMatthias Ringwald printf("Encryption can only be changed in idle state\n"); 640*ac95ea81SMatthias Ringwald break; 641*ac95ea81SMatthias Ringwald } 642*ac95ea81SMatthias Ringwald encryption = 1 - encryption; 643*ac95ea81SMatthias Ringwald print_config(); 644*ac95ea81SMatthias Ringwald break; 64510277393SMatthias Ringwald case 'f': 64610277393SMatthias Ringwald if (app_state != APP_IDLE){ 64710277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 64810277393SMatthias Ringwald break; 64910277393SMatthias Ringwald } 65010277393SMatthias Ringwald menu_sampling_frequency++; 65110277393SMatthias Ringwald if (menu_sampling_frequency >= 6){ 65210277393SMatthias Ringwald menu_sampling_frequency = 0; 65310277393SMatthias Ringwald } 65410277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 65510277393SMatthias Ringwald menu_variant = 0; 65610277393SMatthias Ringwald } 65710277393SMatthias Ringwald print_config(); 65810277393SMatthias Ringwald break; 65910277393SMatthias Ringwald case 'v': 66010277393SMatthias Ringwald if (app_state != APP_IDLE){ 66110277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 66210277393SMatthias Ringwald break; 66310277393SMatthias Ringwald } 66410277393SMatthias Ringwald menu_variant++; 66510277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 66610277393SMatthias Ringwald menu_variant = 0; 66710277393SMatthias Ringwald } 66810277393SMatthias Ringwald print_config(); 66910277393SMatthias Ringwald break; 67010277393SMatthias Ringwald case 'x': 67110277393SMatthias Ringwald #ifdef COUNT_MODE 67210277393SMatthias Ringwald printf("Send statistic:\n"); 67310277393SMatthias Ringwald { 67410277393SMatthias Ringwald uint16_t i; 67510277393SMatthias Ringwald for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){ 67610277393SMatthias Ringwald printf("%2u: %5u\n", i, send_time_bins[i]); 67710277393SMatthias Ringwald } 67810277393SMatthias Ringwald } 67910277393SMatthias Ringwald #endif 68010277393SMatthias Ringwald printf("Shutdown...\n"); 681b9b9e477SMatthias Ringwald app_state = APP_W4_POWER_OFF; 68210277393SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 68310277393SMatthias Ringwald break; 68410277393SMatthias Ringwald case 's': 68510277393SMatthias Ringwald if (app_state != APP_IDLE){ 68610277393SMatthias Ringwald printf("Cannot start broadcast - not in idle state\n"); 68710277393SMatthias Ringwald break; 68810277393SMatthias Ringwald } 68956c77a86SMatthias Ringwald start_broadcast(); 69010277393SMatthias Ringwald break; 69110277393SMatthias Ringwald case 't': 69210277393SMatthias Ringwald audio_source = 1 - audio_source; 69310277393SMatthias Ringwald print_config(); 69410277393SMatthias Ringwald break; 69510277393SMatthias Ringwald case '\n': 69610277393SMatthias Ringwald case '\r': 69710277393SMatthias Ringwald break; 69810277393SMatthias Ringwald default: 69910277393SMatthias Ringwald show_usage(); 70010277393SMatthias Ringwald break; 70110277393SMatthias Ringwald } 70210277393SMatthias Ringwald } 70310277393SMatthias Ringwald 70410277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 70510277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 70610277393SMatthias Ringwald (void) argv; 70710277393SMatthias Ringwald (void) argc; 70810277393SMatthias Ringwald 70910277393SMatthias Ringwald // register for HCI events 71010277393SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 71110277393SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 71210277393SMatthias Ringwald 71310277393SMatthias Ringwald // turn on! 71410277393SMatthias Ringwald hci_power_control(HCI_POWER_ON); 71510277393SMatthias Ringwald 71610277393SMatthias Ringwald btstack_stdin_setup(stdin_process); 71710277393SMatthias Ringwald return 0; 71810277393SMatthias Ringwald } 719