xref: /btstack/test/le_audio/le_audio_broadcast_source.c (revision 0be46310fbdd756527d85a0289ee4b4085eab944)
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,
8510277393SMatthias 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
23010277393SMatthias Ringwald static uint32_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 
25610277393SMatthias Ringwald // audio producer
25710277393SMatthias Ringwald static enum {
25810277393SMatthias Ringwald     AUDIO_SOURCE_SINE,
25910277393SMatthias Ringwald     AUDIO_SOURCE_MODPLAYER
26010277393SMatthias Ringwald } audio_source = AUDIO_SOURCE_MODPLAYER;
26110277393SMatthias Ringwald 
26210277393SMatthias Ringwald static enum {
26310277393SMatthias Ringwald     APP_IDLE,
26410277393SMatthias Ringwald     APP_W4_PERIODIC_ENABLED,
26510277393SMatthias Ringwald     APP_W4_CREATE_BIG_COMPLETE,
266b9b9e477SMatthias Ringwald     APP_STREAMING,
267b9b9e477SMatthias Ringwald     APP_W4_POWER_OFF,
26810277393SMatthias Ringwald } app_state = APP_IDLE;
26910277393SMatthias Ringwald 
27010277393SMatthias Ringwald // enumerate default codec configs
27110277393SMatthias Ringwald static struct {
27210277393SMatthias Ringwald     uint32_t samplingrate_hz;
27310277393SMatthias Ringwald     uint8_t  samplingrate_index;
27410277393SMatthias Ringwald     uint8_t  num_variants;
27510277393SMatthias Ringwald     struct {
27610277393SMatthias Ringwald         const char * name;
2772fd68da2SMatthias Ringwald         btstack_lc3_frame_duration_t frame_duration;
27810277393SMatthias Ringwald         uint16_t octets_per_frame;
27910277393SMatthias Ringwald     } variants[6];
28010277393SMatthias Ringwald } codec_configurations[] = {
28110277393SMatthias Ringwald     {
28210277393SMatthias Ringwald         8000, 0x01, 2,
28310277393SMatthias Ringwald         {
2842fd68da2SMatthias Ringwald             {  "8_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 26},
2852fd68da2SMatthias Ringwald             {  "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30}
28610277393SMatthias Ringwald         }
28710277393SMatthias Ringwald     },
28810277393SMatthias Ringwald     {
28910277393SMatthias Ringwald        16000, 0x03, 2,
29010277393SMatthias Ringwald        {
2912fd68da2SMatthias Ringwald             {  "16_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 30},
2922fd68da2SMatthias Ringwald             {  "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40}
29310277393SMatthias Ringwald        }
29410277393SMatthias Ringwald     },
29510277393SMatthias Ringwald     {
29610277393SMatthias Ringwald         24000, 0x05, 2,
29710277393SMatthias Ringwald         {
2982fd68da2SMatthias Ringwald             {  "24_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 45},
2992fd68da2SMatthias Ringwald             {  "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60}
30010277393SMatthias Ringwald        }
30110277393SMatthias Ringwald     },
30210277393SMatthias Ringwald     {
30310277393SMatthias Ringwald         32000, 0x06, 2,
30410277393SMatthias Ringwald         {
3052fd68da2SMatthias Ringwald             {  "32_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 60},
3062fd68da2SMatthias Ringwald             {  "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80}
30710277393SMatthias Ringwald         }
30810277393SMatthias Ringwald     },
30910277393SMatthias Ringwald     {
31010277393SMatthias Ringwald         44100, 0x07, 2,
31110277393SMatthias Ringwald         {
3122fd68da2SMatthias Ringwald             { "441_1",  BTSTACK_LC3_FRAME_DURATION_7500US,  97},
3132fd68da2SMatthias Ringwald             { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130}
31410277393SMatthias Ringwald         }
31510277393SMatthias Ringwald     },
31610277393SMatthias Ringwald     {
31710277393SMatthias Ringwald         48000, 0x08, 6,
31810277393SMatthias Ringwald         {
3192fd68da2SMatthias Ringwald             {  "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75},
3202fd68da2SMatthias Ringwald             {  "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100},
3212fd68da2SMatthias Ringwald             {  "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90},
3222fd68da2SMatthias Ringwald             {  "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120},
3232fd68da2SMatthias Ringwald             {  "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117},
3242fd68da2SMatthias Ringwald             {  "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155}
32510277393SMatthias Ringwald         }
32610277393SMatthias Ringwald     },
32710277393SMatthias Ringwald };
32810277393SMatthias Ringwald 
32910277393SMatthias Ringwald static void show_usage(void);
33010277393SMatthias Ringwald 
33110277393SMatthias Ringwald static void print_config(void) {
33210277393SMatthias Ringwald     printf("Config '%s_%u': %u, %s ms, %u octets - %s\n",
33310277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].name,
33410277393SMatthias Ringwald            num_bis,
33510277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].samplingrate_hz,
3362fd68da2SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
33710277393SMatthias Ringwald            codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame,
33810277393SMatthias Ringwald            audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer");
33910277393SMatthias Ringwald }
34010277393SMatthias Ringwald 
34110277393SMatthias Ringwald static void setup_lc3_encoder(void){
34210277393SMatthias Ringwald     uint8_t channel;
34310277393SMatthias Ringwald     for (channel = 0 ; channel < num_bis ; channel++){
344e40ee29aSMatthias Ringwald         btstack_lc3_encoder_google_t * context = &encoder_contexts[channel];
345e40ee29aSMatthias Ringwald         lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
34610277393SMatthias Ringwald         lc3_encoder->configure(context, sampling_frequency_hz, frame_duration);
34710277393SMatthias Ringwald     }
34810277393SMatthias Ringwald     number_samples_per_frame = lc3_encoder->get_number_samples_per_frame(&encoder_contexts[0]);
34910277393SMatthias Ringwald     btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
35010277393SMatthias Ringwald     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
3512fd68da2SMatthias Ringwald            sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
35210277393SMatthias Ringwald            number_samples_per_frame, octets_per_frame);
35310277393SMatthias Ringwald }
35410277393SMatthias Ringwald 
35510277393SMatthias Ringwald static void setup_mod_player(void){
35610277393SMatthias Ringwald     if (!hxcmod_initialized) {
35710277393SMatthias Ringwald         hxcmod_initialized = hxcmod_init(&mod_context);
35810277393SMatthias Ringwald         btstack_assert(hxcmod_initialized != 0);
35910277393SMatthias Ringwald     }
36010277393SMatthias Ringwald     hxcmod_unload(&mod_context);
36110277393SMatthias Ringwald     hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1);
36210277393SMatthias Ringwald     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
36310277393SMatthias Ringwald }
36410277393SMatthias Ringwald 
36510277393SMatthias Ringwald static void generate_audio(void){
36610277393SMatthias Ringwald     uint32_t start_ms = btstack_run_loop_get_time_ms();
36710277393SMatthias Ringwald     uint16_t sample;
36810277393SMatthias Ringwald     switch (audio_source) {
36910277393SMatthias Ringwald         case AUDIO_SOURCE_SINE:
37010277393SMatthias Ringwald             // generate sine wave for all channels
37110277393SMatthias Ringwald             for (sample = 0 ; sample < number_samples_per_frame ; sample++){
37210277393SMatthias Ringwald                 uint8_t channel;
37310277393SMatthias Ringwald                 for (channel = 0; channel < num_bis; channel++) {
37410277393SMatthias Ringwald                     int16_t value = sine_int16[sine_phases[channel]] / 4;
375c3e2434dSMatthias Ringwald                     pcm[sample * num_bis + channel] = value;
37610277393SMatthias Ringwald                     sine_phases[channel] += sine_step * (1+channel);    // second channel, double frequency
37710277393SMatthias Ringwald                     if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) {
37810277393SMatthias Ringwald                         sine_phases[channel] = 0;
37910277393SMatthias Ringwald                     }
38010277393SMatthias Ringwald                 }
38110277393SMatthias Ringwald             }
38210277393SMatthias Ringwald             break;
38310277393SMatthias Ringwald         case AUDIO_SOURCE_MODPLAYER:
38410277393SMatthias Ringwald             // mod player configured for stereo
385c3e2434dSMatthias Ringwald             hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf);
38610277393SMatthias Ringwald             if (num_bis == 1) {
38710277393SMatthias Ringwald                 // stereo -> mono
388c3e2434dSMatthias Ringwald                 uint16_t i;
38910277393SMatthias Ringwald                 for (i=0;i<number_samples_per_frame;i++){
390c3e2434dSMatthias Ringwald                     pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2);
39110277393SMatthias Ringwald                 }
39210277393SMatthias Ringwald             }
39310277393SMatthias Ringwald             break;
39410277393SMatthias Ringwald         default:
39510277393SMatthias Ringwald             btstack_unreachable();
39610277393SMatthias Ringwald             break;
39710277393SMatthias Ringwald     }
39810277393SMatthias Ringwald     time_generation_ms = btstack_run_loop_get_time_ms() - start_ms;
39910277393SMatthias Ringwald     iso_frame_counter++;
40010277393SMatthias Ringwald }
40110277393SMatthias Ringwald 
4023f485d09SMatthias Ringwald static void encode(uint8_t bis_index){
4033f485d09SMatthias Ringwald     // encode as lc3
4043f485d09SMatthias 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);
4053f485d09SMatthias Ringwald }
4063f485d09SMatthias Ringwald 
4073f485d09SMatthias Ringwald 
4083f485d09SMatthias Ringwald static void send_iso_packet(uint8_t bis_index) {
40910277393SMatthias Ringwald 
41010277393SMatthias Ringwald #ifdef COUNT_MODE
41110277393SMatthias Ringwald     if (bis_index == 0) {
41210277393SMatthias Ringwald         uint32_t now = btstack_run_loop_get_time_ms();
41310277393SMatthias Ringwald         if (send_last_ms != 0) {
41410277393SMatthias Ringwald             uint16_t send_interval_ms = now - send_last_ms;
41510277393SMatthias Ringwald             if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) {
41610277393SMatthias Ringwald                 printf("ERROR: send interval %u\n", send_interval_ms);
41710277393SMatthias Ringwald             } else {
41810277393SMatthias Ringwald                 send_time_bins[send_interval_ms]++;
41910277393SMatthias Ringwald             }
42010277393SMatthias Ringwald         }
42110277393SMatthias Ringwald         send_last_ms = now;
42210277393SMatthias Ringwald     }
42310277393SMatthias Ringwald #endif
42410277393SMatthias Ringwald     bool ok = hci_reserve_packet_buffer();
42510277393SMatthias Ringwald     btstack_assert(ok);
42610277393SMatthias Ringwald     uint8_t * buffer = hci_get_outgoing_packet_buffer();
42710277393SMatthias Ringwald     // complete SDU, no TimeStamp
42810277393SMatthias Ringwald     little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12));
42910277393SMatthias Ringwald     // len
43010277393SMatthias Ringwald     little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame);
43110277393SMatthias Ringwald     // TimeStamp if TS flag is set
43210277393SMatthias Ringwald     // packet seq nr
43310277393SMatthias Ringwald     little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]);
43410277393SMatthias Ringwald     // iso sdu len
43510277393SMatthias Ringwald     little_endian_store_16(buffer, 6, octets_per_frame);
43610277393SMatthias Ringwald #ifdef COUNT_MODE
43710277393SMatthias Ringwald     // test data: bis_index, counter
43810277393SMatthias Ringwald     buffer[8] = bis_index;
43910277393SMatthias Ringwald     memset(&buffer[9], iso_frame_counter, octets_per_frame - 1);
44010277393SMatthias Ringwald #else
4413f485d09SMatthias Ringwald     // copy encoded payload
4423f485d09SMatthias Ringwald     memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame);
44310277393SMatthias Ringwald #endif
44410277393SMatthias Ringwald     // send
44510277393SMatthias Ringwald     hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame);
44610277393SMatthias Ringwald 
4473f485d09SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO
44810277393SMatthias Ringwald     if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) {
44910277393SMatthias Ringwald         printf("Encoding time: %u\n", time_generation_ms);
45010277393SMatthias Ringwald     }
45110277393SMatthias Ringwald     if ((packet_sequence_numbers[bis_index] & 0x7c) == 0){
45210277393SMatthias Ringwald         printf("%04x %10u %u ", packet_sequence_numbers[bis_index], btstack_run_loop_get_time_ms(), bis_index);
45310277393SMatthias Ringwald         printf_hexdump(&buffer[8], octets_per_frame);
45410277393SMatthias Ringwald     }
4553f485d09SMatthias Ringwald #endif
45610277393SMatthias Ringwald 
45710277393SMatthias Ringwald     packet_sequence_numbers[bis_index]++;
45810277393SMatthias Ringwald }
45910277393SMatthias Ringwald 
460*0be46310SMatthias Ringwald static void generate_audio_and_encode(void){
46110277393SMatthias Ringwald     uint8_t i;
46210277393SMatthias Ringwald     generate_audio();
46310277393SMatthias Ringwald     for (i = 0; i < num_bis; i++) {
464*0be46310SMatthias Ringwald         encode(i);
46510277393SMatthias Ringwald         bis_has_data[i] = true;
46610277393SMatthias Ringwald     }
46710277393SMatthias Ringwald }
46810277393SMatthias Ringwald 
469cd0bedb1SMatthias Ringwald static void create_big(void){
470cd0bedb1SMatthias Ringwald     // Create BIG
471cd0bedb1SMatthias Ringwald     big_params.big_handle = 0;
472cd0bedb1SMatthias Ringwald     big_params.advertising_handle = adv_handle;
473cd0bedb1SMatthias Ringwald     big_params.num_bis = num_bis;
474cd0bedb1SMatthias Ringwald     big_params.max_sdu = octets_per_frame;
475cd0bedb1SMatthias Ringwald     big_params.max_transport_latency_ms = 31;
476cd0bedb1SMatthias Ringwald     big_params.rtn = 2;
477cd0bedb1SMatthias Ringwald     big_params.phy = 2;
478cd0bedb1SMatthias Ringwald     big_params.packing = 0;
479cd0bedb1SMatthias Ringwald     big_params.encryption = 0;
480cd0bedb1SMatthias Ringwald     memset(big_params.broadcast_code, 0, 16);
481cd0bedb1SMatthias Ringwald     if (sampling_frequency_hz == 44100){
482cd0bedb1SMatthias Ringwald         // same config as for 48k -> frame is longer by 48/44.1
483cd0bedb1SMatthias Ringwald         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884;
484cd0bedb1SMatthias Ringwald         big_params.framing = 1;
485cd0bedb1SMatthias Ringwald     } else {
486cd0bedb1SMatthias Ringwald         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000;
487cd0bedb1SMatthias Ringwald         big_params.framing = 0;
488cd0bedb1SMatthias Ringwald     }
489cd0bedb1SMatthias Ringwald     app_state = APP_W4_CREATE_BIG_COMPLETE;
490cd0bedb1SMatthias Ringwald     gap_big_create(&big_storage, &big_params);
491cd0bedb1SMatthias Ringwald }
492cd0bedb1SMatthias Ringwald 
49310277393SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
49410277393SMatthias Ringwald     UNUSED(channel);
49510277393SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
496*0be46310SMatthias Ringwald     uint8_t bis_index;
49710277393SMatthias Ringwald 
49810277393SMatthias Ringwald     switch (packet[0]) {
49910277393SMatthias Ringwald         case BTSTACK_EVENT_STATE:
50010277393SMatthias Ringwald             switch(btstack_event_state_get_state(packet)) {
50110277393SMatthias Ringwald                 case HCI_STATE_WORKING:
50210277393SMatthias Ringwald                     show_usage();
50310277393SMatthias Ringwald                     printf("Please select sample frequency and variation, then start broadcast\n");
50410277393SMatthias Ringwald                     break;
50510277393SMatthias Ringwald                 case HCI_STATE_OFF:
50610277393SMatthias Ringwald                     printf("Goodbye\n");
50710277393SMatthias Ringwald                     exit(0);
50810277393SMatthias Ringwald                     break;
50910277393SMatthias Ringwald                 default:
51010277393SMatthias Ringwald                     break;
51110277393SMatthias Ringwald             }
51210277393SMatthias Ringwald             break;
51310277393SMatthias Ringwald         case HCI_EVENT_COMMAND_COMPLETE:
51410277393SMatthias Ringwald             switch (hci_event_command_complete_get_command_opcode(packet)){
51510277393SMatthias Ringwald                 case HCI_OPCODE_HCI_LE_SET_PERIODIC_ADVERTISING_ENABLE:
51610277393SMatthias Ringwald                     if (app_state != APP_W4_PERIODIC_ENABLED) break;
517cd0bedb1SMatthias Ringwald                     create_big();
51810277393SMatthias Ringwald                     break;
519cd0bedb1SMatthias Ringwald                 default:
520cd0bedb1SMatthias Ringwald                     break;
521cd0bedb1SMatthias Ringwald             }
522cd0bedb1SMatthias Ringwald             break;
523cd0bedb1SMatthias Ringwald         case HCI_EVENT_META_GAP:
524cd0bedb1SMatthias Ringwald             switch (hci_event_gap_meta_get_subevent_code(packet)){
525*0be46310SMatthias Ringwald                 case GAP_SUBEVENT_BIG_CREATED:
526cd0bedb1SMatthias Ringwald                     printf("BIG Created with BIS Connection handles: \n");
527*0be46310SMatthias Ringwald                     for (bis_index=0;bis_index<num_bis;bis_index++){
528*0be46310SMatthias Ringwald                         bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index);
529*0be46310SMatthias Ringwald                         printf("0x%04x ", bis_con_handles[bis_index]);
53010277393SMatthias Ringwald                     }
531cd0bedb1SMatthias Ringwald                     app_state = APP_STREAMING;
53210277393SMatthias Ringwald                     printf("Start streaming\n");
533*0be46310SMatthias Ringwald                     generate_audio_and_encode();
534*0be46310SMatthias Ringwald                     hci_request_bis_can_send_now_events(big_params.big_handle);
53510277393SMatthias Ringwald                     break;
53610277393SMatthias Ringwald                 default:
53710277393SMatthias Ringwald                     break;
53810277393SMatthias Ringwald             }
53910277393SMatthias Ringwald             break;
540*0be46310SMatthias Ringwald         case HCI_EVENT_BIS_CAN_SEND_NOW:
541*0be46310SMatthias Ringwald             send_iso_packet(hci_event_bis_can_send_now_get_bis_index(packet));
542*0be46310SMatthias Ringwald             bis_index++;
543*0be46310SMatthias Ringwald             if (bis_index == num_bis){
544*0be46310SMatthias Ringwald                 generate_audio_and_encode();
545*0be46310SMatthias Ringwald                 hci_request_bis_can_send_now_events(big_params.big_handle);
54610277393SMatthias Ringwald             }
54710277393SMatthias Ringwald             break;
54810277393SMatthias Ringwald         default:
54910277393SMatthias Ringwald             break;
55010277393SMatthias Ringwald     }
55110277393SMatthias Ringwald }
55210277393SMatthias Ringwald 
55310277393SMatthias Ringwald static void show_usage(void){
55410277393SMatthias Ringwald     printf("\n--- LE Audio Broadcast Source Test Console ---\n");
55510277393SMatthias Ringwald     print_config();
55610277393SMatthias Ringwald     printf("---\n");
55710277393SMatthias Ringwald     printf("c - toggle channels\n");
55810277393SMatthias Ringwald     printf("f - next sampling frequency\n");
55910277393SMatthias Ringwald     printf("v - next codec variant\n");
56010277393SMatthias Ringwald     printf("t - toggle sine / modplayer\n");
56110277393SMatthias Ringwald     printf("s - start broadcast\n");
56210277393SMatthias Ringwald     printf("x - shutdown\n");
56310277393SMatthias Ringwald     printf("---\n");
56410277393SMatthias Ringwald }
56510277393SMatthias Ringwald 
56610277393SMatthias Ringwald static void stdin_process(char c){
56710277393SMatthias Ringwald     switch (c){
56810277393SMatthias Ringwald         case 'c':
56910277393SMatthias Ringwald             if (app_state != APP_IDLE){
57010277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
57110277393SMatthias Ringwald                 break;
57210277393SMatthias Ringwald             }
57310277393SMatthias Ringwald             num_bis = 3 - num_bis;
57410277393SMatthias Ringwald             print_config();
57510277393SMatthias Ringwald             break;
57610277393SMatthias Ringwald         case 'f':
57710277393SMatthias Ringwald             if (app_state != APP_IDLE){
57810277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
57910277393SMatthias Ringwald                 break;
58010277393SMatthias Ringwald             }
58110277393SMatthias Ringwald             menu_sampling_frequency++;
58210277393SMatthias Ringwald             if (menu_sampling_frequency >= 6){
58310277393SMatthias Ringwald                 menu_sampling_frequency = 0;
58410277393SMatthias Ringwald             }
58510277393SMatthias Ringwald             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
58610277393SMatthias Ringwald                 menu_variant = 0;
58710277393SMatthias Ringwald             }
58810277393SMatthias Ringwald             print_config();
58910277393SMatthias Ringwald             break;
59010277393SMatthias Ringwald         case 'v':
59110277393SMatthias Ringwald             if (app_state != APP_IDLE){
59210277393SMatthias Ringwald                 printf("Codec configuration can only be changed in idle state\n");
59310277393SMatthias Ringwald                 break;
59410277393SMatthias Ringwald             }
59510277393SMatthias Ringwald             menu_variant++;
59610277393SMatthias Ringwald             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
59710277393SMatthias Ringwald                 menu_variant = 0;
59810277393SMatthias Ringwald             }
59910277393SMatthias Ringwald             print_config();
60010277393SMatthias Ringwald             break;
60110277393SMatthias Ringwald         case 'x':
60210277393SMatthias Ringwald #ifdef COUNT_MODE
60310277393SMatthias Ringwald             printf("Send statistic:\n");
60410277393SMatthias Ringwald             {
60510277393SMatthias Ringwald                 uint16_t i;
60610277393SMatthias Ringwald                 for (i=0;i<MAX_PACKET_INTERVAL_BINS_MS;i++){
60710277393SMatthias Ringwald                     printf("%2u: %5u\n", i, send_time_bins[i]);
60810277393SMatthias Ringwald                 }
60910277393SMatthias Ringwald             }
61010277393SMatthias Ringwald #endif
61110277393SMatthias Ringwald             printf("Shutdown...\n");
612b9b9e477SMatthias Ringwald             app_state = APP_W4_POWER_OFF;
61310277393SMatthias Ringwald             hci_power_control(HCI_POWER_OFF);
61410277393SMatthias Ringwald             break;
61510277393SMatthias Ringwald         case 's':
61610277393SMatthias Ringwald             if (app_state != APP_IDLE){
61710277393SMatthias Ringwald                 printf("Cannot start broadcast - not in idle state\n");
61810277393SMatthias Ringwald                 break;
61910277393SMatthias Ringwald             }
62010277393SMatthias Ringwald             // use values from table
62110277393SMatthias Ringwald             sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz;
62210277393SMatthias Ringwald             octets_per_frame      = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame;
62310277393SMatthias Ringwald             frame_duration        = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration;
62410277393SMatthias Ringwald 
62510277393SMatthias Ringwald             // get num samples per frame
62610277393SMatthias Ringwald             setup_lc3_encoder();
62710277393SMatthias Ringwald 
62810277393SMatthias Ringwald             // update BASEs
62910277393SMatthias Ringwald             periodic_adv_data_1[17] = codec_configurations[menu_sampling_frequency].samplingrate_index;
6302fd68da2SMatthias Ringwald             periodic_adv_data_1[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;
63110277393SMatthias Ringwald             little_endian_store_16(periodic_adv_data_1, 23, octets_per_frame);
63210277393SMatthias Ringwald 
63310277393SMatthias Ringwald             periodic_adv_data_2[17] = codec_configurations[menu_sampling_frequency].samplingrate_index;
6342fd68da2SMatthias Ringwald             periodic_adv_data_2[20] = (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;
63510277393SMatthias Ringwald             little_endian_store_16(periodic_adv_data_2, 23, octets_per_frame);
63610277393SMatthias Ringwald 
63710277393SMatthias Ringwald             // setup mod player
63810277393SMatthias Ringwald             setup_mod_player();
63910277393SMatthias Ringwald 
64010277393SMatthias Ringwald             // setup sine generator
64110277393SMatthias Ringwald             if (sampling_frequency_hz == 44100){
64210277393SMatthias Ringwald                 sine_step = 2;
64310277393SMatthias Ringwald             } else {
64410277393SMatthias Ringwald                 sine_step = 96000 / sampling_frequency_hz;
64510277393SMatthias Ringwald             }
64610277393SMatthias Ringwald 
64710277393SMatthias Ringwald             // setup
64810277393SMatthias Ringwald             app_state = APP_W4_PERIODIC_ENABLED;
64910277393SMatthias Ringwald             gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle);
65010277393SMatthias Ringwald             gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data);
65110277393SMatthias Ringwald             gap_periodic_advertising_set_params(adv_handle, &periodic_params);
65210277393SMatthias Ringwald             switch(num_bis){
65310277393SMatthias Ringwald                 case 1:
65410277393SMatthias Ringwald                     gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_1), periodic_adv_data_1);
65510277393SMatthias Ringwald                     printf("BASE: ");
65610277393SMatthias Ringwald                     printf_hexdump(periodic_adv_data_1, sizeof(periodic_adv_data_1));
65710277393SMatthias Ringwald                     break;
65810277393SMatthias Ringwald                 case 2:
65910277393SMatthias Ringwald                     gap_periodic_advertising_set_data(adv_handle, sizeof(periodic_adv_data_2), periodic_adv_data_2);
66010277393SMatthias Ringwald                     printf("BASE: ");
66110277393SMatthias Ringwald                     printf_hexdump(periodic_adv_data_2, sizeof(periodic_adv_data_2));
66210277393SMatthias Ringwald                     break;
66310277393SMatthias Ringwald                 default:
66410277393SMatthias Ringwald                     btstack_unreachable();
66510277393SMatthias Ringwald                     break;
66610277393SMatthias Ringwald             }
66710277393SMatthias Ringwald             gap_periodic_advertising_start(adv_handle, 0);
66810277393SMatthias Ringwald             gap_extended_advertising_start(adv_handle, 0, 0);
66910277393SMatthias Ringwald             break;
67010277393SMatthias Ringwald         case 't':
67110277393SMatthias Ringwald             audio_source = 1 - audio_source;
67210277393SMatthias Ringwald             print_config();
67310277393SMatthias Ringwald             break;
67410277393SMatthias Ringwald         case '\n':
67510277393SMatthias Ringwald         case '\r':
67610277393SMatthias Ringwald             break;
67710277393SMatthias Ringwald         default:
67810277393SMatthias Ringwald             show_usage();
67910277393SMatthias Ringwald             break;
68010277393SMatthias Ringwald     }
68110277393SMatthias Ringwald }
68210277393SMatthias Ringwald 
68310277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]);
68410277393SMatthias Ringwald int btstack_main(int argc, const char * argv[]){
68510277393SMatthias Ringwald     (void) argv;
68610277393SMatthias Ringwald     (void) argc;
68710277393SMatthias Ringwald 
68810277393SMatthias Ringwald     // register for HCI events
68910277393SMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
69010277393SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
69110277393SMatthias Ringwald 
69210277393SMatthias Ringwald     // turn on!
69310277393SMatthias Ringwald     hci_power_control(HCI_POWER_ON);
69410277393SMatthias Ringwald 
69510277393SMatthias Ringwald     btstack_stdin_setup(stdin_process);
69610277393SMatthias Ringwald     return 0;
69710277393SMatthias Ringwald }
698