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" 594a06e23fSMatthias Ringwald #include "le-audio/le_audio_base_builder.h" 6010277393SMatthias Ringwald 6110277393SMatthias Ringwald #include "hxcmod.h" 6210277393SMatthias Ringwald #include "mods/mod.h" 6310277393SMatthias Ringwald 6410277393SMatthias Ringwald // PTS mode 6510277393SMatthias Ringwald // #define PTS_MODE 6610277393SMatthias Ringwald 6710277393SMatthias Ringwald // Count mode - send packet count as test data for manual analysis 6810277393SMatthias Ringwald // #define COUNT_MODE 6910277393SMatthias Ringwald 7010277393SMatthias Ringwald // max config 7110277393SMatthias Ringwald #define MAX_NUM_BIS 2 7210277393SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 733f485d09SMatthias Ringwald #define MAX_LC3_FRAME_BYTES 155 7410277393SMatthias Ringwald 7510277393SMatthias Ringwald static const uint8_t adv_sid = 0; 7610277393SMatthias Ringwald 7710277393SMatthias Ringwald static le_advertising_set_t le_advertising_set; 7810277393SMatthias Ringwald 7910277393SMatthias Ringwald static const le_extended_advertising_parameters_t extended_params = { 8010277393SMatthias Ringwald .advertising_event_properties = 0, 8110277393SMatthias Ringwald .primary_advertising_interval_min = 0x4b0, // 750 ms 8210277393SMatthias Ringwald .primary_advertising_interval_max = 0x4b0, // 750 ms 8310277393SMatthias Ringwald .primary_advertising_channel_map = 7, 8410277393SMatthias Ringwald .own_address_type = 0, 8510277393SMatthias Ringwald .peer_address_type = 0, 86c52eeb3dSMatthias Ringwald .peer_address = { 0 }, 8710277393SMatthias Ringwald .advertising_filter_policy = 0, 8810277393SMatthias Ringwald .advertising_tx_power = 10, // 10 dBm 8910277393SMatthias Ringwald .primary_advertising_phy = 1, // LE 1M PHY 9010277393SMatthias Ringwald .secondary_advertising_max_skip = 0, 9110277393SMatthias Ringwald .secondary_advertising_phy = 1, // LE 1M PHY 9210277393SMatthias Ringwald .advertising_sid = adv_sid, 9310277393SMatthias Ringwald .scan_request_notification_enable = 0, 9410277393SMatthias Ringwald }; 9510277393SMatthias Ringwald 9670718632SMatthias Ringwald // Random Broadcast ID, valid for lifetime of BIG 9770718632SMatthias Ringwald #define BROADCAST_ID (0x112233u) 9870718632SMatthias Ringwald 9910277393SMatthias Ringwald static const uint8_t extended_adv_data[] = { 10010277393SMatthias Ringwald // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID 10170718632SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18, 10270718632SMatthias Ringwald BROADCAST_ID >> 16, 10370718632SMatthias Ringwald (BROADCAST_ID >> 8) & 0xff, 10470718632SMatthias Ringwald BROADCAST_ID & 0xff, 10510277393SMatthias Ringwald // name 10610277393SMatthias Ringwald #ifdef PTS_MODE 10710277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x' 10810277393SMatthias Ringwald #elif defined(COUNT_MODE) 10910277393SMatthias Ringwald 6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T' 11010277393SMatthias Ringwald #else 11110277393SMatthias Ringwald 7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e' 11210277393SMatthias Ringwald #endif 11310277393SMatthias Ringwald }; 11410277393SMatthias Ringwald 11510277393SMatthias Ringwald static const le_periodic_advertising_parameters_t periodic_params = { 11610277393SMatthias Ringwald .periodic_advertising_interval_min = 0x258, // 375 ms 11710277393SMatthias Ringwald .periodic_advertising_interval_max = 0x258, // 375 ms 11810277393SMatthias Ringwald .periodic_advertising_properties = 0 11910277393SMatthias Ringwald }; 12010277393SMatthias Ringwald 12110277393SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz 12210277393SMatthias Ringwald static const int16_t sine_int16[] = { 12310277393SMatthias Ringwald 0, 643, 1286, 1929, 2571, 3212, 3851, 4489, 5126, 5760, 12410277393SMatthias Ringwald 6393, 7022, 7649, 8273, 8894, 9512, 10126, 10735, 11341, 11943, 12510277393SMatthias Ringwald 12539, 13131, 13718, 14300, 14876, 15446, 16011, 16569, 17121, 17666, 12610277393SMatthias Ringwald 18204, 18736, 19260, 19777, 20286, 20787, 21280, 21766, 22242, 22710, 12710277393SMatthias Ringwald 23170, 23620, 24062, 24494, 24916, 25329, 25732, 26126, 26509, 26882, 12810277393SMatthias Ringwald 27245, 27597, 27938, 28269, 28589, 28898, 29196, 29482, 29757, 30021, 12910277393SMatthias Ringwald 30273, 30513, 30742, 30958, 31163, 31356, 31537, 31705, 31862, 32006, 13010277393SMatthias Ringwald 32137, 32257, 32364, 32458, 32540, 32609, 32666, 32710, 32742, 32761, 13110277393SMatthias Ringwald 32767, 32761, 32742, 32710, 32666, 32609, 32540, 32458, 32364, 32257, 13210277393SMatthias Ringwald 32137, 32006, 31862, 31705, 31537, 31356, 31163, 30958, 30742, 30513, 13310277393SMatthias Ringwald 30273, 30021, 29757, 29482, 29196, 28898, 28589, 28269, 27938, 27597, 13410277393SMatthias Ringwald 27245, 26882, 26509, 26126, 25732, 25329, 24916, 24494, 24062, 23620, 13510277393SMatthias Ringwald 23170, 22710, 22242, 21766, 21280, 20787, 20286, 19777, 19260, 18736, 13610277393SMatthias Ringwald 18204, 17666, 17121, 16569, 16011, 15446, 14876, 14300, 13718, 13131, 13710277393SMatthias Ringwald 12539, 11943, 11341, 10735, 10126, 9512, 8894, 8273, 7649, 7022, 13810277393SMatthias Ringwald 6393, 5760, 5126, 4489, 3851, 3212, 2571, 1929, 1286, 643, 13910277393SMatthias Ringwald 0, -643, -1286, -1929, -2571, -3212, -3851, -4489, -5126, -5760, 14010277393SMatthias Ringwald -6393, -7022, -7649, -8273, -8894, -9512, -10126, -10735, -11341, -11943, 14110277393SMatthias Ringwald -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666, 14210277393SMatthias Ringwald -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710, 14310277393SMatthias Ringwald -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882, 14410277393SMatthias Ringwald -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021, 14510277393SMatthias Ringwald -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006, 14610277393SMatthias Ringwald -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761, 14710277393SMatthias Ringwald -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257, 14810277393SMatthias Ringwald -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513, 14910277393SMatthias Ringwald -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597, 15010277393SMatthias Ringwald -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620, 15110277393SMatthias Ringwald -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736, 15210277393SMatthias Ringwald -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131, 15310277393SMatthias Ringwald -12539, -11943, -11341, -10735, -10126, -9512, -8894, -8273, -7649, -7022, 15410277393SMatthias Ringwald -6393, -5760, -5126, -4489, -3851, -3212, -2571, -1929, -1286, -643, 15510277393SMatthias Ringwald }; 15610277393SMatthias Ringwald 15710277393SMatthias Ringwald static bd_addr_t remote; 15810277393SMatthias Ringwald static const char * remote_addr_string = "00:1B:DC:08:E2:72"; 15910277393SMatthias Ringwald 16010277393SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 1614a06e23fSMatthias Ringwald static uint8_t period_adv_data[255]; 1624a06e23fSMatthias Ringwald static uint16_t period_adv_data_len; 16310277393SMatthias Ringwald 16410277393SMatthias Ringwald static uint8_t adv_handle = 0; 16510277393SMatthias Ringwald static unsigned int next_bis_index; 16610277393SMatthias Ringwald static hci_con_handle_t bis_con_handles[MAX_NUM_BIS]; 16710277393SMatthias Ringwald static uint16_t packet_sequence_numbers[MAX_NUM_BIS]; 16810277393SMatthias Ringwald static uint8_t framed_pdus; 16910277393SMatthias Ringwald static bool bis_can_send[MAX_NUM_BIS]; 17010277393SMatthias Ringwald static bool bis_has_data[MAX_NUM_BIS]; 17110277393SMatthias Ringwald static uint8_t iso_frame_counter; 17210277393SMatthias Ringwald static uint16_t frame_duration_us; 17310277393SMatthias Ringwald 174cd0bedb1SMatthias Ringwald static le_audio_big_t big_storage; 175cd0bedb1SMatthias Ringwald static le_audio_big_params_t big_params; 176cd0bedb1SMatthias Ringwald 17710277393SMatthias Ringwald // time stamping 17810277393SMatthias Ringwald #ifdef COUNT_MODE 17910277393SMatthias Ringwald #define MAX_PACKET_INTERVAL_BINS_MS 50 18010277393SMatthias Ringwald static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS]; 18110277393SMatthias Ringwald static uint32_t send_last_ms; 18210277393SMatthias Ringwald #endif 18310277393SMatthias Ringwald 18410277393SMatthias Ringwald // lc3 codec config 185c52eeb3dSMatthias Ringwald static uint16_t sampling_frequency_hz; 1862fd68da2SMatthias Ringwald static btstack_lc3_frame_duration_t frame_duration; 18710277393SMatthias Ringwald static uint16_t number_samples_per_frame; 18810277393SMatthias Ringwald static uint16_t octets_per_frame; 18910277393SMatthias Ringwald static uint8_t num_bis = 1; 19010277393SMatthias Ringwald 19110277393SMatthias Ringwald // lc3 encoder 1922fd68da2SMatthias Ringwald static const btstack_lc3_encoder_t * lc3_encoder; 193e40ee29aSMatthias Ringwald static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS]; 19410277393SMatthias Ringwald static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME]; 1953f485d09SMatthias Ringwald static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES]; 19610277393SMatthias Ringwald static uint32_t time_generation_ms; 19710277393SMatthias Ringwald 19810277393SMatthias Ringwald // codec menu 19910277393SMatthias Ringwald static uint8_t menu_sampling_frequency; 20010277393SMatthias Ringwald static uint8_t menu_variant; 20110277393SMatthias Ringwald 20210277393SMatthias Ringwald // mod player 20310277393SMatthias Ringwald static int hxcmod_initialized; 20410277393SMatthias Ringwald static modcontext mod_context; 20510277393SMatthias Ringwald static tracker_buffer_state trkbuf; 20610277393SMatthias Ringwald 20710277393SMatthias Ringwald // sine generator 20810277393SMatthias Ringwald static uint8_t sine_step; 20910277393SMatthias Ringwald static uint16_t sine_phases[MAX_NUM_BIS]; 21010277393SMatthias Ringwald 211ac95ea81SMatthias Ringwald // encryption 212ac95ea81SMatthias Ringwald static uint8_t encryption = 0; 213166aee19SMatthias Ringwald static uint8_t broadcast_code [] = {0x01, 0x02, 0x68, 0x05, 0x53, 0xF1, 0x41, 0x5A, 0xA2, 0x65, 0xBB, 0xAF, 0xC6, 0xEA, 0x03, 0xB8, }; 214ac95ea81SMatthias Ringwald 21510277393SMatthias Ringwald // audio producer 21610277393SMatthias Ringwald static enum { 21710277393SMatthias Ringwald AUDIO_SOURCE_SINE, 21810277393SMatthias Ringwald AUDIO_SOURCE_MODPLAYER 21910277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER; 22010277393SMatthias Ringwald 22110277393SMatthias Ringwald static enum { 22210277393SMatthias Ringwald APP_IDLE, 22310277393SMatthias Ringwald APP_W4_CREATE_BIG_COMPLETE, 224b9b9e477SMatthias Ringwald APP_STREAMING, 225b9b9e477SMatthias Ringwald APP_W4_POWER_OFF, 22610277393SMatthias Ringwald } app_state = APP_IDLE; 22710277393SMatthias Ringwald 22810277393SMatthias Ringwald // enumerate default codec configs 22910277393SMatthias Ringwald static struct { 230c52eeb3dSMatthias Ringwald uint16_t samplingrate_hz; 23110277393SMatthias Ringwald uint8_t samplingrate_index; 23210277393SMatthias Ringwald uint8_t num_variants; 23310277393SMatthias Ringwald struct { 23410277393SMatthias Ringwald const char * name; 2352fd68da2SMatthias Ringwald btstack_lc3_frame_duration_t frame_duration; 23610277393SMatthias Ringwald uint16_t octets_per_frame; 23710277393SMatthias Ringwald } variants[6]; 23810277393SMatthias Ringwald } codec_configurations[] = { 23910277393SMatthias Ringwald { 24010277393SMatthias Ringwald 8000, 0x01, 2, 24110277393SMatthias Ringwald { 2422fd68da2SMatthias Ringwald { "8_1", BTSTACK_LC3_FRAME_DURATION_7500US, 26}, 2432fd68da2SMatthias Ringwald { "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30} 24410277393SMatthias Ringwald } 24510277393SMatthias Ringwald }, 24610277393SMatthias Ringwald { 24710277393SMatthias Ringwald 16000, 0x03, 2, 24810277393SMatthias Ringwald { 2492fd68da2SMatthias Ringwald { "16_1", BTSTACK_LC3_FRAME_DURATION_7500US, 30}, 2502fd68da2SMatthias Ringwald { "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40} 25110277393SMatthias Ringwald } 25210277393SMatthias Ringwald }, 25310277393SMatthias Ringwald { 25410277393SMatthias Ringwald 24000, 0x05, 2, 25510277393SMatthias Ringwald { 2562fd68da2SMatthias Ringwald { "24_1", BTSTACK_LC3_FRAME_DURATION_7500US, 45}, 2572fd68da2SMatthias Ringwald { "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60} 25810277393SMatthias Ringwald } 25910277393SMatthias Ringwald }, 26010277393SMatthias Ringwald { 26110277393SMatthias Ringwald 32000, 0x06, 2, 26210277393SMatthias Ringwald { 2632fd68da2SMatthias Ringwald { "32_1", BTSTACK_LC3_FRAME_DURATION_7500US, 60}, 2642fd68da2SMatthias Ringwald { "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80} 26510277393SMatthias Ringwald } 26610277393SMatthias Ringwald }, 26710277393SMatthias Ringwald { 26810277393SMatthias Ringwald 44100, 0x07, 2, 26910277393SMatthias Ringwald { 2702fd68da2SMatthias Ringwald { "441_1", BTSTACK_LC3_FRAME_DURATION_7500US, 97}, 2712fd68da2SMatthias Ringwald { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130} 27210277393SMatthias Ringwald } 27310277393SMatthias Ringwald }, 27410277393SMatthias Ringwald { 27510277393SMatthias Ringwald 48000, 0x08, 6, 27610277393SMatthias Ringwald { 2772fd68da2SMatthias Ringwald { "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75}, 2782fd68da2SMatthias Ringwald { "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100}, 2792fd68da2SMatthias Ringwald { "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90}, 2802fd68da2SMatthias Ringwald { "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120}, 2812fd68da2SMatthias Ringwald { "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117}, 2822fd68da2SMatthias Ringwald { "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155} 28310277393SMatthias Ringwald } 28410277393SMatthias Ringwald }, 28510277393SMatthias Ringwald }; 28610277393SMatthias Ringwald 28710277393SMatthias Ringwald static void show_usage(void); 28810277393SMatthias Ringwald 28910277393SMatthias Ringwald static void print_config(void) { 290ac95ea81SMatthias Ringwald printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n", 29110277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].name, 29210277393SMatthias Ringwald num_bis, 29310277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].samplingrate_hz, 2942fd68da2SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 29510277393SMatthias Ringwald codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame, 296ac95ea81SMatthias Ringwald audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : ""); 29710277393SMatthias Ringwald } 29810277393SMatthias Ringwald 29910277393SMatthias Ringwald static void setup_lc3_encoder(void){ 30010277393SMatthias Ringwald uint8_t channel; 30110277393SMatthias Ringwald for (channel = 0 ; channel < num_bis ; channel++){ 302e40ee29aSMatthias Ringwald btstack_lc3_encoder_google_t * context = &encoder_contexts[channel]; 303e40ee29aSMatthias Ringwald lc3_encoder = btstack_lc3_encoder_google_init_instance(context); 304da364eecSMatthias Ringwald lc3_encoder->configure(context, sampling_frequency_hz, frame_duration, octets_per_frame); 30510277393SMatthias Ringwald } 306dc0d751cSMatthias Ringwald number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration); 30710277393SMatthias Ringwald btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME); 30810277393SMatthias Ringwald printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n", 3092fd68da2SMatthias Ringwald sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10", 31010277393SMatthias Ringwald number_samples_per_frame, octets_per_frame); 31110277393SMatthias Ringwald } 31210277393SMatthias Ringwald 31310277393SMatthias Ringwald static void setup_mod_player(void){ 31410277393SMatthias Ringwald if (!hxcmod_initialized) { 31510277393SMatthias Ringwald hxcmod_initialized = hxcmod_init(&mod_context); 31610277393SMatthias Ringwald btstack_assert(hxcmod_initialized != 0); 31710277393SMatthias Ringwald } 31810277393SMatthias Ringwald hxcmod_unload(&mod_context); 31910277393SMatthias Ringwald hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1); 32010277393SMatthias Ringwald hxcmod_load(&mod_context, (void *) &mod_data, mod_len); 32110277393SMatthias Ringwald } 32210277393SMatthias Ringwald 32310277393SMatthias Ringwald static void generate_audio(void){ 32410277393SMatthias Ringwald uint32_t start_ms = btstack_run_loop_get_time_ms(); 32510277393SMatthias Ringwald uint16_t sample; 32610277393SMatthias Ringwald switch (audio_source) { 32710277393SMatthias Ringwald case AUDIO_SOURCE_SINE: 32810277393SMatthias Ringwald // generate sine wave for all channels 32910277393SMatthias Ringwald for (sample = 0 ; sample < number_samples_per_frame ; sample++){ 33010277393SMatthias Ringwald uint8_t channel; 33110277393SMatthias Ringwald for (channel = 0; channel < num_bis; channel++) { 33210277393SMatthias Ringwald int16_t value = sine_int16[sine_phases[channel]] / 4; 333c3e2434dSMatthias Ringwald pcm[sample * num_bis + channel] = value; 33410277393SMatthias Ringwald sine_phases[channel] += sine_step * (1+channel); // second channel, double frequency 33510277393SMatthias Ringwald if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) { 33610277393SMatthias Ringwald sine_phases[channel] = 0; 33710277393SMatthias Ringwald } 33810277393SMatthias Ringwald } 33910277393SMatthias Ringwald } 34010277393SMatthias Ringwald break; 34110277393SMatthias Ringwald case AUDIO_SOURCE_MODPLAYER: 34210277393SMatthias Ringwald // mod player configured for stereo 343c3e2434dSMatthias Ringwald hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf); 34410277393SMatthias Ringwald if (num_bis == 1) { 34510277393SMatthias Ringwald // stereo -> mono 346c3e2434dSMatthias Ringwald uint16_t i; 34710277393SMatthias Ringwald for (i=0;i<number_samples_per_frame;i++){ 348c3e2434dSMatthias Ringwald pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2); 34910277393SMatthias Ringwald } 35010277393SMatthias Ringwald } 35110277393SMatthias Ringwald break; 35210277393SMatthias Ringwald default: 35310277393SMatthias Ringwald btstack_unreachable(); 35410277393SMatthias Ringwald break; 35510277393SMatthias Ringwald } 35610277393SMatthias Ringwald time_generation_ms = btstack_run_loop_get_time_ms() - start_ms; 35710277393SMatthias Ringwald iso_frame_counter++; 35810277393SMatthias Ringwald } 35910277393SMatthias Ringwald 3603f485d09SMatthias Ringwald static void encode(uint8_t bis_index){ 3613f485d09SMatthias Ringwald // encode as lc3 362da364eecSMatthias Ringwald lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES]); 3633f485d09SMatthias Ringwald } 3643f485d09SMatthias Ringwald 3653f485d09SMatthias Ringwald 3663f485d09SMatthias Ringwald static void send_iso_packet(uint8_t bis_index) { 36710277393SMatthias Ringwald 36810277393SMatthias Ringwald #ifdef COUNT_MODE 36910277393SMatthias Ringwald if (bis_index == 0) { 37010277393SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 37110277393SMatthias Ringwald if (send_last_ms != 0) { 37210277393SMatthias Ringwald uint16_t send_interval_ms = now - send_last_ms; 37310277393SMatthias Ringwald if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) { 37410277393SMatthias Ringwald printf("ERROR: send interval %u\n", send_interval_ms); 37510277393SMatthias Ringwald } else { 37610277393SMatthias Ringwald send_time_bins[send_interval_ms]++; 37710277393SMatthias Ringwald } 37810277393SMatthias Ringwald } 37910277393SMatthias Ringwald send_last_ms = now; 38010277393SMatthias Ringwald } 38110277393SMatthias Ringwald #endif 38210277393SMatthias Ringwald bool ok = hci_reserve_packet_buffer(); 38310277393SMatthias Ringwald btstack_assert(ok); 38410277393SMatthias Ringwald uint8_t * buffer = hci_get_outgoing_packet_buffer(); 38510277393SMatthias Ringwald // complete SDU, no TimeStamp 38610277393SMatthias Ringwald little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12)); 38710277393SMatthias Ringwald // len 38810277393SMatthias Ringwald little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame); 38910277393SMatthias Ringwald // TimeStamp if TS flag is set 39010277393SMatthias Ringwald // packet seq nr 39110277393SMatthias Ringwald little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]); 39210277393SMatthias Ringwald // iso sdu len 39310277393SMatthias Ringwald little_endian_store_16(buffer, 6, octets_per_frame); 39410277393SMatthias Ringwald #ifdef COUNT_MODE 39510277393SMatthias Ringwald // test data: bis_index, counter 39610277393SMatthias Ringwald buffer[8] = bis_index; 39710277393SMatthias Ringwald memset(&buffer[9], iso_frame_counter, octets_per_frame - 1); 39810277393SMatthias Ringwald #else 3993f485d09SMatthias Ringwald // copy encoded payload 4003f485d09SMatthias Ringwald memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame); 40110277393SMatthias Ringwald #endif 40210277393SMatthias Ringwald // send 40310277393SMatthias Ringwald hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame); 40410277393SMatthias Ringwald 4053f485d09SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 40610277393SMatthias Ringwald if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) { 40710277393SMatthias Ringwald printf("Encoding time: %u\n", time_generation_ms); 40810277393SMatthias Ringwald } 4093f485d09SMatthias Ringwald #endif 41010277393SMatthias Ringwald 41110277393SMatthias Ringwald packet_sequence_numbers[bis_index]++; 41210277393SMatthias Ringwald } 41310277393SMatthias Ringwald 4140be46310SMatthias Ringwald static void generate_audio_and_encode(void){ 41510277393SMatthias Ringwald uint8_t i; 41610277393SMatthias Ringwald generate_audio(); 41710277393SMatthias Ringwald for (i = 0; i < num_bis; i++) { 4180be46310SMatthias Ringwald encode(i); 41910277393SMatthias Ringwald bis_has_data[i] = true; 42010277393SMatthias Ringwald } 42110277393SMatthias Ringwald } 42210277393SMatthias Ringwald 42344959aebSMatthias Ringwald static void setup_advertising() { 42444959aebSMatthias Ringwald gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle); 42544959aebSMatthias Ringwald gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data); 42644959aebSMatthias Ringwald gap_periodic_advertising_set_params(adv_handle, &periodic_params); 4274a06e23fSMatthias Ringwald gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data); 42844959aebSMatthias Ringwald gap_periodic_advertising_start(adv_handle, 0); 42944959aebSMatthias Ringwald gap_extended_advertising_start(adv_handle, 0, 0); 43044959aebSMatthias Ringwald } 43144959aebSMatthias Ringwald 43244959aebSMatthias Ringwald static void setup_big(void){ 433cd0bedb1SMatthias Ringwald // Create BIG 434cd0bedb1SMatthias Ringwald big_params.big_handle = 0; 435cd0bedb1SMatthias Ringwald big_params.advertising_handle = adv_handle; 436cd0bedb1SMatthias Ringwald big_params.num_bis = num_bis; 437cd0bedb1SMatthias Ringwald big_params.max_sdu = octets_per_frame; 438cd0bedb1SMatthias Ringwald big_params.max_transport_latency_ms = 31; 439cd0bedb1SMatthias Ringwald big_params.rtn = 2; 440cd0bedb1SMatthias Ringwald big_params.phy = 2; 441cd0bedb1SMatthias Ringwald big_params.packing = 0; 442ac95ea81SMatthias Ringwald big_params.encryption = encryption; 443ac95ea81SMatthias Ringwald if (encryption) { 444ac95ea81SMatthias Ringwald memcpy(big_params.broadcast_code, &broadcast_code[0], 16); 445ac95ea81SMatthias Ringwald } else { 446cd0bedb1SMatthias Ringwald memset(big_params.broadcast_code, 0, 16); 447ac95ea81SMatthias Ringwald } 448cd0bedb1SMatthias Ringwald if (sampling_frequency_hz == 44100){ 449cd0bedb1SMatthias Ringwald // same config as for 48k -> frame is longer by 48/44.1 450cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884; 451cd0bedb1SMatthias Ringwald big_params.framing = 1; 452cd0bedb1SMatthias Ringwald } else { 453cd0bedb1SMatthias Ringwald big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000; 454cd0bedb1SMatthias Ringwald big_params.framing = 0; 455cd0bedb1SMatthias Ringwald } 456cd0bedb1SMatthias Ringwald app_state = APP_W4_CREATE_BIG_COMPLETE; 457cd0bedb1SMatthias Ringwald gap_big_create(&big_storage, &big_params); 458cd0bedb1SMatthias Ringwald } 459cd0bedb1SMatthias Ringwald 46056c77a86SMatthias Ringwald 46156c77a86SMatthias Ringwald static void start_broadcast() {// use values from table 46256c77a86SMatthias Ringwald sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz; 46356c77a86SMatthias Ringwald octets_per_frame = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame; 46456c77a86SMatthias Ringwald frame_duration = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration; 46556c77a86SMatthias Ringwald 46656c77a86SMatthias Ringwald // get num samples per frame 46756c77a86SMatthias Ringwald setup_lc3_encoder(); 46856c77a86SMatthias Ringwald 4694a06e23fSMatthias Ringwald // setup base 4704a06e23fSMatthias Ringwald uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 }; 4714a06e23fSMatthias Ringwald uint8_t subgroup_codec_specific_configuration[] = { 4724a06e23fSMatthias Ringwald 0x02, 0x01, 0x01, 4734a06e23fSMatthias Ringwald 0x02, 0x02, 0x01, 4744a06e23fSMatthias Ringwald 0x03, 0x04, 0x1E, 0x00, 4754a06e23fSMatthias Ringwald }; 4764a06e23fSMatthias Ringwald subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index; 4774a06e23fSMatthias Ringwald subgroup_codec_specific_configuration[5] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;; 4784a06e23fSMatthias Ringwald uint8_t subgroup_metadata[] = { 4794a06e23fSMatthias Ringwald 0x03, 0x02, 0x04, 0x00, // Metadata[i] 4804a06e23fSMatthias Ringwald }; 4814a06e23fSMatthias Ringwald little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame); 4824a06e23fSMatthias Ringwald uint8_t bis_codec_specific_configuration_1[] = { 4834a06e23fSMatthias Ringwald 0x05, 0x03, 0x01, 0x00, 0x00, 0x00 4844a06e23fSMatthias Ringwald }; 4854a06e23fSMatthias Ringwald uint8_t bis_codec_specific_configuration_2[] = { 4864a06e23fSMatthias Ringwald 0x05, 0x03, 0x02, 0x00, 0x00, 0x00 4874a06e23fSMatthias Ringwald }; 488*0f7e8caeSMatthias Ringwald le_audio_base_builder_t builder; 4894a06e23fSMatthias Ringwald le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40); 4904a06e23fSMatthias Ringwald le_audio_base_builder_add_subgroup(&builder, codec_id, 4914a06e23fSMatthias Ringwald sizeof(subgroup_codec_specific_configuration), 4924a06e23fSMatthias Ringwald subgroup_codec_specific_configuration, 4934a06e23fSMatthias Ringwald sizeof(subgroup_metadata), subgroup_metadata); 4944a06e23fSMatthias Ringwald le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1), 4954a06e23fSMatthias Ringwald bis_codec_specific_configuration_1); 4964a06e23fSMatthias Ringwald if (num_bis == 2){ 4974a06e23fSMatthias Ringwald le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2), 4984a06e23fSMatthias Ringwald bis_codec_specific_configuration_2); 4994a06e23fSMatthias Ringwald } 5004a06e23fSMatthias Ringwald period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder); 50156c77a86SMatthias Ringwald 50256c77a86SMatthias Ringwald // setup mod player 50356c77a86SMatthias Ringwald setup_mod_player(); 50456c77a86SMatthias Ringwald 50556c77a86SMatthias Ringwald // setup sine generator 50656c77a86SMatthias Ringwald if (sampling_frequency_hz == 44100){ 50756c77a86SMatthias Ringwald sine_step = 2; 50856c77a86SMatthias Ringwald } else { 50956c77a86SMatthias Ringwald sine_step = 96000 / sampling_frequency_hz; 51056c77a86SMatthias Ringwald } 51156c77a86SMatthias Ringwald 51256c77a86SMatthias Ringwald // setup extended and periodic advertising 51356c77a86SMatthias Ringwald setup_advertising(); 51456c77a86SMatthias Ringwald 51556c77a86SMatthias Ringwald // setup big 51656c77a86SMatthias Ringwald setup_big(); 51756c77a86SMatthias Ringwald } 51856c77a86SMatthias Ringwald 51910277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 52010277393SMatthias Ringwald UNUSED(channel); 52110277393SMatthias Ringwald if (packet_type != HCI_EVENT_PACKET) return; 5220be46310SMatthias Ringwald uint8_t bis_index; 52310277393SMatthias Ringwald 52410277393SMatthias Ringwald switch (packet[0]) { 52510277393SMatthias Ringwald case BTSTACK_EVENT_STATE: 52610277393SMatthias Ringwald switch(btstack_event_state_get_state(packet)) { 52710277393SMatthias Ringwald case HCI_STATE_WORKING: 52856c77a86SMatthias Ringwald #ifdef ENABLE_DEMO_MODE 52956c77a86SMatthias Ringwald // start broadcast automatically, mod player, 48_5_1 53056c77a86SMatthias Ringwald num_bis = 1; 53156c77a86SMatthias Ringwald menu_sampling_frequency = 5; 53256c77a86SMatthias Ringwald menu_variant = 4; 53356c77a86SMatthias Ringwald start_broadcast(); 53456c77a86SMatthias Ringwald #else 53510277393SMatthias Ringwald show_usage(); 53610277393SMatthias Ringwald printf("Please select sample frequency and variation, then start broadcast\n"); 53756c77a86SMatthias Ringwald #endif 53810277393SMatthias Ringwald break; 53910277393SMatthias Ringwald case HCI_STATE_OFF: 54010277393SMatthias Ringwald printf("Goodbye\n"); 54110277393SMatthias Ringwald exit(0); 54210277393SMatthias Ringwald break; 54310277393SMatthias Ringwald default: 54410277393SMatthias Ringwald break; 54510277393SMatthias Ringwald } 54610277393SMatthias Ringwald break; 547cd0bedb1SMatthias Ringwald case HCI_EVENT_META_GAP: 548cd0bedb1SMatthias Ringwald switch (hci_event_gap_meta_get_subevent_code(packet)){ 5490be46310SMatthias Ringwald case GAP_SUBEVENT_BIG_CREATED: 550cd0bedb1SMatthias Ringwald printf("BIG Created with BIS Connection handles: \n"); 5510be46310SMatthias Ringwald for (bis_index=0;bis_index<num_bis;bis_index++){ 5520be46310SMatthias Ringwald bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index); 5530be46310SMatthias Ringwald printf("0x%04x ", bis_con_handles[bis_index]); 55410277393SMatthias Ringwald } 55544959aebSMatthias Ringwald 556cd0bedb1SMatthias Ringwald app_state = APP_STREAMING; 55710277393SMatthias Ringwald printf("Start streaming\n"); 5580be46310SMatthias Ringwald generate_audio_and_encode(); 5590be46310SMatthias Ringwald hci_request_bis_can_send_now_events(big_params.big_handle); 56010277393SMatthias Ringwald break; 56110277393SMatthias Ringwald default: 56210277393SMatthias Ringwald break; 56310277393SMatthias Ringwald } 56410277393SMatthias Ringwald break; 5650be46310SMatthias Ringwald case HCI_EVENT_BIS_CAN_SEND_NOW: 5660d718107SMatthias Ringwald bis_index = hci_event_bis_can_send_now_get_bis_index(packet); 5670d718107SMatthias Ringwald send_iso_packet(bis_index); 5680be46310SMatthias Ringwald bis_index++; 5690be46310SMatthias Ringwald if (bis_index == num_bis){ 5700be46310SMatthias Ringwald generate_audio_and_encode(); 5710be46310SMatthias Ringwald hci_request_bis_can_send_now_events(big_params.big_handle); 57210277393SMatthias Ringwald } 57310277393SMatthias Ringwald break; 57410277393SMatthias Ringwald default: 57510277393SMatthias Ringwald break; 57610277393SMatthias Ringwald } 57710277393SMatthias Ringwald } 57810277393SMatthias Ringwald 57910277393SMatthias Ringwald static void show_usage(void){ 58010277393SMatthias Ringwald printf("\n--- LE Audio Broadcast Source Test Console ---\n"); 58110277393SMatthias Ringwald print_config(); 58210277393SMatthias Ringwald printf("---\n"); 58310277393SMatthias Ringwald printf("c - toggle channels\n"); 584ac95ea81SMatthias Ringwald printf("e - toggle encryption\n"); 58510277393SMatthias Ringwald printf("f - next sampling frequency\n"); 58610277393SMatthias Ringwald printf("v - next codec variant\n"); 58710277393SMatthias Ringwald printf("t - toggle sine / modplayer\n"); 58810277393SMatthias Ringwald printf("s - start broadcast\n"); 58910277393SMatthias Ringwald printf("x - shutdown\n"); 59010277393SMatthias Ringwald printf("---\n"); 59110277393SMatthias Ringwald } 59210277393SMatthias Ringwald static void stdin_process(char c){ 59310277393SMatthias Ringwald switch (c){ 59410277393SMatthias Ringwald case 'c': 59510277393SMatthias Ringwald if (app_state != APP_IDLE){ 59610277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 59710277393SMatthias Ringwald break; 59810277393SMatthias Ringwald } 59910277393SMatthias Ringwald num_bis = 3 - num_bis; 60010277393SMatthias Ringwald print_config(); 60110277393SMatthias Ringwald break; 602ac95ea81SMatthias Ringwald case 'e': 603ac95ea81SMatthias Ringwald if (app_state != APP_IDLE){ 604ac95ea81SMatthias Ringwald printf("Encryption can only be changed in idle state\n"); 605ac95ea81SMatthias Ringwald break; 606ac95ea81SMatthias Ringwald } 607ac95ea81SMatthias Ringwald encryption = 1 - encryption; 608ac95ea81SMatthias Ringwald print_config(); 609ac95ea81SMatthias Ringwald break; 61010277393SMatthias Ringwald case 'f': 61110277393SMatthias Ringwald if (app_state != APP_IDLE){ 61210277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 61310277393SMatthias Ringwald break; 61410277393SMatthias Ringwald } 61510277393SMatthias Ringwald menu_sampling_frequency++; 61610277393SMatthias Ringwald if (menu_sampling_frequency >= 6){ 61710277393SMatthias Ringwald menu_sampling_frequency = 0; 61810277393SMatthias Ringwald } 61910277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 62010277393SMatthias Ringwald menu_variant = 0; 62110277393SMatthias Ringwald } 62210277393SMatthias Ringwald print_config(); 62310277393SMatthias Ringwald break; 62410277393SMatthias Ringwald case 'v': 62510277393SMatthias Ringwald if (app_state != APP_IDLE){ 62610277393SMatthias Ringwald printf("Codec configuration can only be changed in idle state\n"); 62710277393SMatthias Ringwald break; 62810277393SMatthias Ringwald } 62910277393SMatthias Ringwald menu_variant++; 63010277393SMatthias Ringwald if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){ 63110277393SMatthias Ringwald menu_variant = 0; 63210277393SMatthias Ringwald } 63310277393SMatthias Ringwald print_config(); 63410277393SMatthias Ringwald break; 63510277393SMatthias Ringwald case 'x': 63610277393SMatthias Ringwald #ifdef COUNT_MODE 63710277393SMatthias Ringwald printf("Send statistic:\n"); 63810277393SMatthias Ringwald { 63910277393SMatthias Ringwald uint16_t i; 64010277393SMatthias Ringwald for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){ 64110277393SMatthias Ringwald printf("%2u: %5u\n", i, send_time_bins[i]); 64210277393SMatthias Ringwald } 64310277393SMatthias Ringwald } 64410277393SMatthias Ringwald #endif 64510277393SMatthias Ringwald printf("Shutdown...\n"); 646b9b9e477SMatthias Ringwald app_state = APP_W4_POWER_OFF; 64710277393SMatthias Ringwald hci_power_control(HCI_POWER_OFF); 64810277393SMatthias Ringwald break; 64910277393SMatthias Ringwald case 's': 65010277393SMatthias Ringwald if (app_state != APP_IDLE){ 65110277393SMatthias Ringwald printf("Cannot start broadcast - not in idle state\n"); 65210277393SMatthias Ringwald break; 65310277393SMatthias Ringwald } 65456c77a86SMatthias Ringwald start_broadcast(); 65510277393SMatthias Ringwald break; 65610277393SMatthias Ringwald case 't': 65710277393SMatthias Ringwald audio_source = 1 - audio_source; 65810277393SMatthias Ringwald print_config(); 65910277393SMatthias Ringwald break; 66010277393SMatthias Ringwald case '\n': 66110277393SMatthias Ringwald case '\r': 66210277393SMatthias Ringwald break; 66310277393SMatthias Ringwald default: 66410277393SMatthias Ringwald show_usage(); 66510277393SMatthias Ringwald break; 66610277393SMatthias Ringwald } 66710277393SMatthias Ringwald } 66810277393SMatthias Ringwald 66910277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 67010277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 67110277393SMatthias Ringwald (void) argv; 67210277393SMatthias Ringwald (void) argc; 67310277393SMatthias Ringwald 67410277393SMatthias Ringwald // register for HCI events 67510277393SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 67610277393SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 67710277393SMatthias Ringwald 67810277393SMatthias Ringwald // turn on! 67910277393SMatthias Ringwald hci_power_control(HCI_POWER_ON); 68010277393SMatthias Ringwald 68110277393SMatthias Ringwald btstack_stdin_setup(stdin_process); 68210277393SMatthias Ringwald return 0; 68310277393SMatthias Ringwald } 684