1f7c85330SMatthias Ringwald /* 2f7c85330SMatthias Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3f7c85330SMatthias Ringwald * 4f7c85330SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5f7c85330SMatthias Ringwald * modification, are permitted provided that the following conditions 6f7c85330SMatthias Ringwald * are met: 7f7c85330SMatthias Ringwald * 8f7c85330SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10f7c85330SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11f7c85330SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12f7c85330SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13f7c85330SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14f7c85330SMatthias Ringwald * contributors may be used to endorse or promote products derived 15f7c85330SMatthias Ringwald * from this software without specific prior written permission. 16f7c85330SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17f7c85330SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18f7c85330SMatthias Ringwald * monetary gain. 19f7c85330SMatthias Ringwald * 20f7c85330SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21f7c85330SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22f7c85330SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23f7c85330SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24f7c85330SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25f7c85330SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26f7c85330SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27f7c85330SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28f7c85330SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29f7c85330SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30f7c85330SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31f7c85330SMatthias Ringwald * SUCH DAMAGE. 32f7c85330SMatthias Ringwald * 33f7c85330SMatthias Ringwald * Please inquire about commercial licensing options at 34f7c85330SMatthias Ringwald * [email protected] 35f7c85330SMatthias Ringwald * 36f7c85330SMatthias Ringwald */ 37f7c85330SMatthias Ringwald 38f7c85330SMatthias Ringwald /* 39f7c85330SMatthias Ringwald * sco_demo_util.c - send/receive test data via SCO, used by hfp_*_demo and hsp_*_demo 40f7c85330SMatthias Ringwald */ 41f7c85330SMatthias Ringwald 42f7c85330SMatthias Ringwald #include "sco_demo_util.h" 43fcb08cdbSMilanka Ringwald #include "btstack_debug.h" 44fcb08cdbSMilanka Ringwald #include "sbc_decoder.h" 45fcb08cdbSMilanka Ringwald 46f7c85330SMatthias Ringwald #include <stdio.h> 47f7c85330SMatthias Ringwald 48f7c85330SMatthias Ringwald // configure test mode 49f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_SINE 0 50f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_ASCII 1 51f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_COUNTER 2 52f7c85330SMatthias Ringwald 538b29cfc6SMatthias Ringwald 54f7c85330SMatthias Ringwald // SCO demo configuration 55fcb08cdbSMilanka Ringwald #define SCO_DEMO_MODE SCO_DEMO_MODE_SINE 56f7c85330SMatthias Ringwald #define SCO_REPORT_PERIOD 100 57f7c85330SMatthias Ringwald 588b29cfc6SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 598b29cfc6SMatthias Ringwald #define SCO_WAV_FILENAME "sco_input.wav" 608b29cfc6SMatthias Ringwald #define SCO_WAV_DURATION_IN_SECONDS 30 618b29cfc6SMatthias Ringwald #endif 628b29cfc6SMatthias Ringwald 63f7c85330SMatthias Ringwald 64f7c85330SMatthias Ringwald #if defined(HAVE_PORTAUDIO) && (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE) 65f7c85330SMatthias Ringwald #define USE_PORTAUDIO 66f7c85330SMatthias Ringwald #endif 67f7c85330SMatthias Ringwald 68f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 69f7c85330SMatthias Ringwald #include <portaudio.h> 708b29cfc6SMatthias Ringwald // portaudio config 718b29cfc6SMatthias Ringwald #define NUM_CHANNELS 1 728b29cfc6SMatthias Ringwald #define SAMPLE_RATE 8000 738b29cfc6SMatthias Ringwald #define FRAMES_PER_BUFFER 24 748b29cfc6SMatthias Ringwald #define PA_SAMPLE_TYPE paInt8 75f7c85330SMatthias Ringwald // portaudio globals 76f7c85330SMatthias Ringwald static PaStream * stream; 77f7c85330SMatthias Ringwald #endif 78f7c85330SMatthias Ringwald 79fcb08cdbSMilanka Ringwald typedef struct wav_writer_state { 80fcb08cdbSMilanka Ringwald FILE * wav_file; 81fcb08cdbSMilanka Ringwald int total_num_samples; 82fcb08cdbSMilanka Ringwald int frame_count; 83fcb08cdbSMilanka Ringwald } wav_writer_state_t; 84fcb08cdbSMilanka Ringwald 85fcb08cdbSMilanka Ringwald static int dump_data = 1; 86fcb08cdbSMilanka Ringwald 87fcb08cdbSMilanka Ringwald static int phase; 88fcb08cdbSMilanka Ringwald static int count_sent = 0; 89fcb08cdbSMilanka Ringwald static int count_received = 0; 90fcb08cdbSMilanka Ringwald static uint8_t negotiated_codec = 0; // CVSD 91fcb08cdbSMilanka Ringwald 92f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 93f7c85330SMatthias Ringwald // input signal: pre-computed sine wave, 160 Hz 94f7c85330SMatthias Ringwald static const uint8_t sine[] = { 95f7c85330SMatthias Ringwald 0, 15, 31, 46, 61, 74, 86, 97, 107, 114, 96f7c85330SMatthias Ringwald 120, 124, 126, 126, 124, 120, 114, 107, 97, 86, 97f7c85330SMatthias Ringwald 74, 61, 46, 31, 15, 0, 241, 225, 210, 195, 98f7c85330SMatthias Ringwald 182, 170, 159, 149, 142, 136, 132, 130, 130, 132, 99f7c85330SMatthias Ringwald 136, 142, 149, 159, 170, 182, 195, 210, 225, 241, 100f7c85330SMatthias Ringwald }; 101f7c85330SMatthias Ringwald 102f7c85330SMatthias Ringwald 1038b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 1048b29cfc6SMatthias Ringwald 1058b29cfc6SMatthias Ringwald static int num_samples_to_write; 106fcb08cdbSMilanka Ringwald static wav_writer_state_t wav_writer_state; 1078b29cfc6SMatthias Ringwald 108fcb08cdbSMilanka Ringwald static sbc_decoder_state_t decoder_state; 1098b29cfc6SMatthias Ringwald 1108b29cfc6SMatthias Ringwald static void little_endian_fstore_16(FILE * file, uint16_t value){ 1118b29cfc6SMatthias Ringwald uint8_t buf[2]; 1128b29cfc6SMatthias Ringwald little_endian_store_32(buf, 0, value); 1138b29cfc6SMatthias Ringwald fwrite(&buf, 1, 2, file); 1148b29cfc6SMatthias Ringwald } 1158b29cfc6SMatthias Ringwald 1168b29cfc6SMatthias Ringwald static void little_endian_fstore_32(FILE * file, uint32_t value){ 1178b29cfc6SMatthias Ringwald uint8_t buf[4]; 1188b29cfc6SMatthias Ringwald little_endian_store_32(buf, 0, value); 1198b29cfc6SMatthias Ringwald fwrite(&buf, 1, 4, file); 1208b29cfc6SMatthias Ringwald } 1218b29cfc6SMatthias Ringwald 1228b29cfc6SMatthias Ringwald static FILE * wav_init(const char * filename){ 123fcb08cdbSMilanka Ringwald FILE * f = fopen(filename, "wb"); 124fcb08cdbSMilanka Ringwald printf("SCO Demo: creating wav file %s, %p\n", filename, f); 125fcb08cdbSMilanka Ringwald return f; 1268b29cfc6SMatthias Ringwald } 1278b29cfc6SMatthias Ringwald 1288b29cfc6SMatthias Ringwald static void write_wav_header(FILE * file, int sample_rate, int num_channels, int num_samples, int bytes_per_sample){ 1298b29cfc6SMatthias Ringwald /* write RIFF header */ 1308b29cfc6SMatthias Ringwald fwrite("RIFF", 1, 4, file); 1318b29cfc6SMatthias Ringwald // num_samples = blocks * subbands 1328b29cfc6SMatthias Ringwald uint32_t data_bytes = (uint32_t) (bytes_per_sample * num_samples * num_channels); 1338b29cfc6SMatthias Ringwald little_endian_fstore_32(file, data_bytes + 36); 1348b29cfc6SMatthias Ringwald fwrite("WAVE", 1, 4, file); 1358b29cfc6SMatthias Ringwald 1368b29cfc6SMatthias Ringwald int byte_rate = sample_rate * num_channels * bytes_per_sample; 1378b29cfc6SMatthias Ringwald int bits_per_sample = 8 * bytes_per_sample; 1388b29cfc6SMatthias Ringwald int block_align = num_channels * bits_per_sample; 1398b29cfc6SMatthias Ringwald int fmt_length = 16; 1408b29cfc6SMatthias Ringwald int fmt_format_tag = 1; // PCM 1418b29cfc6SMatthias Ringwald 1428b29cfc6SMatthias Ringwald /* write fmt chunk */ 1438b29cfc6SMatthias Ringwald fwrite("fmt ", 1, 4, file); 1448b29cfc6SMatthias Ringwald little_endian_fstore_32(file, fmt_length); 1458b29cfc6SMatthias Ringwald little_endian_fstore_16(file, fmt_format_tag); 1468b29cfc6SMatthias Ringwald little_endian_fstore_16(file, num_channels); 1478b29cfc6SMatthias Ringwald little_endian_fstore_32(file, sample_rate); 1488b29cfc6SMatthias Ringwald little_endian_fstore_32(file, byte_rate); 1498b29cfc6SMatthias Ringwald little_endian_fstore_16(file, block_align); 1508b29cfc6SMatthias Ringwald little_endian_fstore_16(file, bits_per_sample); 1518b29cfc6SMatthias Ringwald 1528b29cfc6SMatthias Ringwald /* write data chunk */ 1538b29cfc6SMatthias Ringwald fwrite("data", 1, 4, file); 1548b29cfc6SMatthias Ringwald little_endian_fstore_32(file, data_bytes); 1558b29cfc6SMatthias Ringwald } 1568b29cfc6SMatthias Ringwald 1578b29cfc6SMatthias Ringwald static void write_wav_data_uint8(FILE * file, unsigned long num_samples, uint8_t * data){ 1588b29cfc6SMatthias Ringwald fwrite(data, num_samples, 1, file); 1598b29cfc6SMatthias Ringwald } 1608b29cfc6SMatthias Ringwald 161fcb08cdbSMilanka Ringwald static void write_wav_data_int16(FILE * file, int num_samples, int16_t * data){ 162fcb08cdbSMilanka Ringwald fwrite(data, num_samples, 2, file); 163fcb08cdbSMilanka Ringwald } 164fcb08cdbSMilanka Ringwald 165fcb08cdbSMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 166fcb08cdbSMilanka Ringwald log_info("handle_pcm_data num samples %u / %u", num_samples, num_samples_to_write); 167fcb08cdbSMilanka Ringwald if (!num_samples_to_write) return; 168fcb08cdbSMilanka Ringwald 169fcb08cdbSMilanka Ringwald wav_writer_state_t * writer_state = (wav_writer_state_t*) context; 170fcb08cdbSMilanka Ringwald num_samples = btstack_min(num_samples, num_samples_to_write); 171fcb08cdbSMilanka Ringwald num_samples_to_write -= num_samples; 172fcb08cdbSMilanka Ringwald 173fcb08cdbSMilanka Ringwald write_wav_data_int16(writer_state->wav_file, num_samples, data); 174fcb08cdbSMilanka Ringwald writer_state->total_num_samples+=num_samples; 175fcb08cdbSMilanka Ringwald writer_state->frame_count++; 176fcb08cdbSMilanka Ringwald 177fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 178fcb08cdbSMilanka Ringwald sco_demo_close(); 179fcb08cdbSMilanka Ringwald } 180fcb08cdbSMilanka Ringwald } 181fcb08cdbSMilanka Ringwald 182fcb08cdbSMilanka Ringwald 183fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){ 184fcb08cdbSMilanka Ringwald wav_writer_state.wav_file = wav_init(SCO_WAV_FILENAME); 185fcb08cdbSMilanka Ringwald wav_writer_state.frame_count = 0; 186fcb08cdbSMilanka Ringwald wav_writer_state.total_num_samples = 0; 187fcb08cdbSMilanka Ringwald 188fcb08cdbSMilanka Ringwald sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, (void*)&wav_writer_state); 189fcb08cdbSMilanka Ringwald 190fcb08cdbSMilanka Ringwald const int sample_rate = 16000; 191fcb08cdbSMilanka Ringwald const int num_samples = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 192fcb08cdbSMilanka Ringwald const int bytes_per_sample = 2; 193fcb08cdbSMilanka Ringwald const int num_channels = 1; 194fcb08cdbSMilanka Ringwald num_samples_to_write = num_samples; 195fcb08cdbSMilanka Ringwald 196fcb08cdbSMilanka Ringwald write_wav_header(wav_writer_state.wav_file, sample_rate, num_channels, num_samples, bytes_per_sample); 197fcb08cdbSMilanka Ringwald } 198fcb08cdbSMilanka Ringwald 199fcb08cdbSMilanka Ringwald static void sco_demo_init_CVSD(void){ 200fcb08cdbSMilanka Ringwald wav_writer_state.wav_file = wav_init(SCO_WAV_FILENAME); 201fcb08cdbSMilanka Ringwald wav_writer_state.frame_count = 0; 202fcb08cdbSMilanka Ringwald wav_writer_state.total_num_samples = 0; 203fcb08cdbSMilanka Ringwald 204fcb08cdbSMilanka Ringwald const int sample_rate = 8000; 205fcb08cdbSMilanka Ringwald const int num_samples = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 206fcb08cdbSMilanka Ringwald const int num_channels = 1; 207fcb08cdbSMilanka Ringwald const int bytes_per_sample = 1; 208fcb08cdbSMilanka Ringwald num_samples_to_write = num_samples; 209fcb08cdbSMilanka Ringwald write_wav_header(wav_writer_state.wav_file, sample_rate, num_channels, num_samples, bytes_per_sample); 210fcb08cdbSMilanka Ringwald } 211fcb08cdbSMilanka Ringwald 212fcb08cdbSMilanka Ringwald 213fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){ 214fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 215fcb08cdbSMilanka Ringwald sbc_decoder_process_data(&decoder_state, packet+3, size-3); 216fcb08cdbSMilanka Ringwald dump_data = 0; 217fcb08cdbSMilanka Ringwald } 218fcb08cdbSMilanka Ringwald } 219fcb08cdbSMilanka Ringwald 220fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){ 221fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 222fcb08cdbSMilanka Ringwald const int num_samples = size - 3; 223fcb08cdbSMilanka Ringwald const int samples_to_write = btstack_min(num_samples, num_samples_to_write); 224fcb08cdbSMilanka Ringwald // convert 8 bit signed to 8 bit unsigned 225fcb08cdbSMilanka Ringwald int i; 226fcb08cdbSMilanka Ringwald for (i=0;i<samples_to_write;i++){ 227fcb08cdbSMilanka Ringwald packet[3+i] += 128; 228fcb08cdbSMilanka Ringwald } 229*613518d1SMilanka Ringwald 230*613518d1SMilanka Ringwald wav_writer_state_t * writer_state = (wav_writer_state_t*) decoder_state.context; 231*613518d1SMilanka Ringwald write_wav_data_uint8(writer_state->wav_file, samples_to_write, &packet[3]); 232fcb08cdbSMilanka Ringwald num_samples_to_write -= samples_to_write; 233fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 234fcb08cdbSMilanka Ringwald sco_demo_close(); 235fcb08cdbSMilanka Ringwald } 236fcb08cdbSMilanka Ringwald dump_data = 0; 237fcb08cdbSMilanka Ringwald } 238fcb08cdbSMilanka Ringwald } 239fcb08cdbSMilanka Ringwald 2408b29cfc6SMatthias Ringwald #endif 2414a96141eSMatthias Ringwald #endif 2428b29cfc6SMatthias Ringwald 243fcb08cdbSMilanka Ringwald void sco_demo_close(void){ 244fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 245fcb08cdbSMilanka Ringwald #ifdef SCO_WAV_FILENAME 246fcb08cdbSMilanka Ringwald 247*613518d1SMilanka Ringwald #if 0 248fcb08cdbSMilanka Ringwald printf("SCO Demo: closing wav file\n"); 249fcb08cdbSMilanka Ringwald if (negotiated_codec == 0x02){ 250fcb08cdbSMilanka Ringwald wav_writer_state_t * writer_state = (wav_writer_state_t*) decoder_state.context; 251fcb08cdbSMilanka Ringwald if (!writer_state->wav_file) return; 252fcb08cdbSMilanka Ringwald rewind(writer_state->wav_file); 253fcb08cdbSMilanka Ringwald write_wav_header(writer_state->wav_file, writer_state->total_num_samples, sbc_decoder_num_channels(&decoder_state), sbc_decoder_sample_rate(&decoder_state),2); 254fcb08cdbSMilanka Ringwald fclose(writer_state->wav_file); 255fcb08cdbSMilanka Ringwald writer_state->wav_file = NULL; 256fcb08cdbSMilanka Ringwald } 257*613518d1SMilanka Ringwald #endif 258fcb08cdbSMilanka Ringwald #endif 259fcb08cdbSMilanka Ringwald #endif 260fcb08cdbSMilanka Ringwald } 261fcb08cdbSMilanka Ringwald 262fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){ 263fcb08cdbSMilanka Ringwald if (negotiated_codec == codec) return; 264fcb08cdbSMilanka Ringwald negotiated_codec = codec; 265fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 266fcb08cdbSMilanka Ringwald #ifdef SCO_WAV_FILENAME 267fcb08cdbSMilanka Ringwald if (negotiated_codec == 0x02){ 268fcb08cdbSMilanka Ringwald sco_demo_init_mSBC(); 269fcb08cdbSMilanka Ringwald } else { 270fcb08cdbSMilanka Ringwald sco_demo_init_CVSD(); 271fcb08cdbSMilanka Ringwald } 272fcb08cdbSMilanka Ringwald #endif 273fcb08cdbSMilanka Ringwald #endif 274fcb08cdbSMilanka Ringwald } 275fcb08cdbSMilanka Ringwald 276f7c85330SMatthias Ringwald void sco_demo_init(void){ 277f7c85330SMatthias Ringwald 278f7c85330SMatthias Ringwald // status 279f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 280f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO 281f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, audio output via portaudio.\n"); 282f7c85330SMatthias Ringwald #else 283f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, hexdump received data.\n"); 284f7c85330SMatthias Ringwald #endif 285f7c85330SMatthias Ringwald #endif 286f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 287f7c85330SMatthias Ringwald printf("SCO Demo: Sending ASCII blocks, print received data.\n"); 288f7c85330SMatthias Ringwald #endif 289f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 290f7c85330SMatthias Ringwald printf("SCO Demo: Sending counter value, hexdump received data.\n"); 291f7c85330SMatthias Ringwald #endif 292f7c85330SMatthias Ringwald 293f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 294f7c85330SMatthias Ringwald int err; 295f7c85330SMatthias Ringwald PaStreamParameters outputParameters; 296f7c85330SMatthias Ringwald 297f7c85330SMatthias Ringwald /* -- initialize PortAudio -- */ 298f7c85330SMatthias Ringwald err = Pa_Initialize(); 299f7c85330SMatthias Ringwald if( err != paNoError ) return; 300f7c85330SMatthias Ringwald /* -- setup input and output -- */ 301f7c85330SMatthias Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 302f7c85330SMatthias Ringwald outputParameters.channelCount = NUM_CHANNELS; 303f7c85330SMatthias Ringwald outputParameters.sampleFormat = PA_SAMPLE_TYPE; 304f7c85330SMatthias Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 305f7c85330SMatthias Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 306f7c85330SMatthias Ringwald /* -- setup stream -- */ 307f7c85330SMatthias Ringwald err = Pa_OpenStream( 308f7c85330SMatthias Ringwald &stream, 309f7c85330SMatthias Ringwald NULL, // &inputParameters, 310f7c85330SMatthias Ringwald &outputParameters, 311f7c85330SMatthias Ringwald SAMPLE_RATE, 312f7c85330SMatthias Ringwald FRAMES_PER_BUFFER, 313f7c85330SMatthias Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 314f7c85330SMatthias Ringwald NULL, /* no callback, use blocking API */ 315f7c85330SMatthias Ringwald NULL ); /* no callback, so no callback userData */ 316f7c85330SMatthias Ringwald if( err != paNoError ) return; 317f7c85330SMatthias Ringwald /* -- start stream -- */ 318f7c85330SMatthias Ringwald err = Pa_StartStream( stream ); 319f7c85330SMatthias Ringwald if( err != paNoError ) return; 320f7c85330SMatthias Ringwald #endif 321f7c85330SMatthias Ringwald 322fcb08cdbSMilanka Ringwald //#if SCO_DEMO_MODE != SCO_DEMO_MODE_SINE 323f7c85330SMatthias Ringwald hci_set_sco_voice_setting(0x03); // linear, unsigned, 8-bit, transparent 324fcb08cdbSMilanka Ringwald //#endif 325f7c85330SMatthias Ringwald 326f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 327f7c85330SMatthias Ringwald phase = 'a'; 328f7c85330SMatthias Ringwald #endif 329f7c85330SMatthias Ringwald } 330f7c85330SMatthias Ringwald 3314a96141eSMatthias Ringwald static void sco_report(void){ 3324a96141eSMatthias Ringwald printf("SCO: sent %u, received %u\n", count_sent, count_received); 3334a96141eSMatthias Ringwald } 334f7c85330SMatthias Ringwald 335f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){ 336f7c85330SMatthias Ringwald 337f7c85330SMatthias Ringwald if (!sco_handle) return; 338f7c85330SMatthias Ringwald 339f7c85330SMatthias Ringwald const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length(); 340f7c85330SMatthias Ringwald const int sco_payload_length = sco_packet_length - 3; 341f7c85330SMatthias Ringwald 342f7c85330SMatthias Ringwald hci_reserve_packet_buffer(); 343f7c85330SMatthias Ringwald uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); 344f7c85330SMatthias Ringwald // set handle + flags 345f7c85330SMatthias Ringwald little_endian_store_16(sco_packet, 0, sco_handle); 346f7c85330SMatthias Ringwald // set len 347f7c85330SMatthias Ringwald sco_packet[2] = sco_payload_length; 348f7c85330SMatthias Ringwald const int frames_per_packet = sco_payload_length; // for 8-bit data. for 16-bit data it's /2 349f7c85330SMatthias Ringwald 350f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 351f7c85330SMatthias Ringwald int i; 352f7c85330SMatthias Ringwald for (i=0;i<frames_per_packet;i++){ 353f7c85330SMatthias Ringwald sco_packet[3+i] = sine[phase]; 354f7c85330SMatthias Ringwald phase++; 355f7c85330SMatthias Ringwald if (phase >= sizeof(sine)) phase = 0; 356f7c85330SMatthias Ringwald } 357f7c85330SMatthias Ringwald #else 358f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 359f7c85330SMatthias Ringwald memset(&sco_packet[3], phase++, frames_per_packet); 360f7c85330SMatthias Ringwald if (phase > 'z') phase = 'a'; 361f7c85330SMatthias Ringwald #else 36238b2eaafSMatthias Ringwald int j; 36338b2eaafSMatthias Ringwald for (j=0;j<frames_per_packet;j++){ 36438b2eaafSMatthias Ringwald sco_packet[3+j] = phase++; 365f7c85330SMatthias Ringwald } 366f7c85330SMatthias Ringwald #endif 367f7c85330SMatthias Ringwald #endif 368f7c85330SMatthias Ringwald hci_send_sco_packet_buffer(sco_packet_length); 369f7c85330SMatthias Ringwald 370f7c85330SMatthias Ringwald // request another send event 371f7c85330SMatthias Ringwald hci_request_sco_can_send_now_event(); 372f7c85330SMatthias Ringwald 3734a96141eSMatthias Ringwald count_sent++; 3744a96141eSMatthias Ringwald if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report(); 375f7c85330SMatthias Ringwald } 376f7c85330SMatthias Ringwald 377fcb08cdbSMilanka Ringwald 378f7c85330SMatthias Ringwald /** 379f7c85330SMatthias Ringwald * @brief Process received data 380f7c85330SMatthias Ringwald */ 381f7c85330SMatthias Ringwald void sco_demo_receive(uint8_t * packet, uint16_t size){ 382f7c85330SMatthias Ringwald 3838b29cfc6SMatthias Ringwald 384fcb08cdbSMilanka Ringwald dump_data = 1; 3858b29cfc6SMatthias Ringwald 3864a96141eSMatthias Ringwald count_received++; 3874a96141eSMatthias Ringwald // if ((count_received % SCO_REPORT_PERIOD) == 0) sco_report(); 3884a96141eSMatthias Ringwald 3894a96141eSMatthias Ringwald 3904a96141eSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 3918b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 392fcb08cdbSMilanka Ringwald if (negotiated_codec == 0x02){ 393fcb08cdbSMilanka Ringwald sco_demo_receive_mSBC(packet, size); 394fcb08cdbSMilanka Ringwald } else { 395fcb08cdbSMilanka Ringwald sco_demo_receive_CVSD(packet, size); 3968b29cfc6SMatthias Ringwald } 3978b29cfc6SMatthias Ringwald #endif 3984a96141eSMatthias Ringwald #endif 3998b29cfc6SMatthias Ringwald 400f7c85330SMatthias Ringwald if (packet[1] & 0xf0){ 401f7c85330SMatthias Ringwald printf("SCO CRC Error: %x - data: ", packet[1] >> 4); 402f7c85330SMatthias Ringwald printf_hexdump(&packet[3], size-3); 403f7c85330SMatthias Ringwald return; 404f7c85330SMatthias Ringwald } 405f7c85330SMatthias Ringwald 406f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 407f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 408f7c85330SMatthias Ringwald uint32_t start = btstack_run_loop_get_time_ms(); 409f7c85330SMatthias Ringwald Pa_WriteStream( stream, &packet[3], size -3); 410f7c85330SMatthias Ringwald uint32_t end = btstack_run_loop_get_time_ms(); 411f7c85330SMatthias Ringwald if (end - start > 5){ 412f7c85330SMatthias Ringwald printf("Portaudio: write stream took %u ms\n", end - start); 413f7c85330SMatthias Ringwald } 4148b29cfc6SMatthias Ringwald dump_data = 0; 415f7c85330SMatthias Ringwald #endif 4168b29cfc6SMatthias Ringwald #endif 4178b29cfc6SMatthias Ringwald 4188b29cfc6SMatthias Ringwald if (dump_data){ 419f7c85330SMatthias Ringwald printf("data: "); 420f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 421f7c85330SMatthias Ringwald int i; 422f7c85330SMatthias Ringwald for (i=3;i<size;i++){ 423f7c85330SMatthias Ringwald printf("%c", packet[i]); 424f7c85330SMatthias Ringwald } 425f7c85330SMatthias Ringwald printf("\n"); 4268b29cfc6SMatthias Ringwald dump_data = 0; 4278b29cfc6SMatthias Ringwald #else 428f7c85330SMatthias Ringwald printf_hexdump(&packet[3], size-3); 429f7c85330SMatthias Ringwald #endif 4308b29cfc6SMatthias Ringwald } 431f7c85330SMatthias Ringwald } 432