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 422ec72fbbSMilanka Ringwald 432ec72fbbSMilanka Ringwald #include <stdio.h> 442ec72fbbSMilanka Ringwald 45f7c85330SMatthias Ringwald #include "sco_demo_util.h" 46fcb08cdbSMilanka Ringwald #include "btstack_debug.h" 4735fd3fb9SMatthias Ringwald #include "classic/btstack_sbc.h" 4835fd3fb9SMatthias Ringwald #include "classic/btstack_cvsd_plc.h" 4935fd3fb9SMatthias Ringwald #include "classic/hfp_msbc.h" 5035fd3fb9SMatthias Ringwald #include "classic/hfp.h" 51fcb08cdbSMilanka Ringwald 5235fd3fb9SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 53fbc7c9f2SMilanka Ringwald #include "wav_util.h" 5435fd3fb9SMatthias Ringwald #endif 55fbc7c9f2SMilanka Ringwald 56f7c85330SMatthias Ringwald // configure test mode 57f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_SINE 0 58f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_ASCII 1 59f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_COUNTER 2 60*1a919128SMatthias Ringwald #define SCO_DEMO_MODE_55 3 61*1a919128SMatthias Ringwald #define SCO_DEMO_MODE_00 4 62f7c85330SMatthias Ringwald 638b29cfc6SMatthias Ringwald 64f7c85330SMatthias Ringwald // SCO demo configuration 65fcb08cdbSMilanka Ringwald #define SCO_DEMO_MODE SCO_DEMO_MODE_SINE 66f7c85330SMatthias Ringwald #define SCO_REPORT_PERIOD 100 67f7c85330SMatthias Ringwald 688b29cfc6SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO 698b29cfc6SMatthias Ringwald #define SCO_WAV_FILENAME "sco_input.wav" 70d5e5f834SMatthias Ringwald #define SCO_MSBC_OUT_FILENAME "sco_output.msbc" 712308e108SMilanka Ringwald #define SCO_MSBC_IN_FILENAME "sco_input.msbc" 72220eb563SMilanka Ringwald 73202da317SMilanka Ringwald #define SCO_WAV_DURATION_IN_SECONDS 15 748b29cfc6SMatthias Ringwald #endif 758b29cfc6SMatthias Ringwald 76f7c85330SMatthias Ringwald 77f7c85330SMatthias Ringwald #if defined(HAVE_PORTAUDIO) && (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE) 78f7c85330SMatthias Ringwald #define USE_PORTAUDIO 79f7c85330SMatthias Ringwald #endif 80f7c85330SMatthias Ringwald 81*1a919128SMatthias Ringwald 82f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO 83f7c85330SMatthias Ringwald #include <portaudio.h> 84dbb41bfeSMilanka Ringwald #include "btstack_ring_buffer.h" 85dbb41bfeSMilanka Ringwald 868b29cfc6SMatthias Ringwald // portaudio config 878b29cfc6SMatthias Ringwald #define NUM_CHANNELS 1 88dbb41bfeSMilanka Ringwald 89dbb41bfeSMilanka Ringwald #define CVSD_SAMPLE_RATE 8000 90dbb41bfeSMilanka Ringwald #define CVSD_FRAMES_PER_BUFFER 24 91dbb41bfeSMilanka Ringwald #define CVSD_PA_SAMPLE_TYPE paInt8 92dbb41bfeSMilanka Ringwald #define CVSD_BYTES_PER_FRAME (1*NUM_CHANNELS) 93dbb41bfeSMilanka Ringwald #define CVSD_PREBUFFER_MS 5 94dbb41bfeSMilanka Ringwald #define CVSD_PREBUFFER_BYTES (CVSD_PREBUFFER_MS * CVSD_SAMPLE_RATE/1000 * CVSD_BYTES_PER_FRAME) 95dbb41bfeSMilanka Ringwald 96dbb41bfeSMilanka Ringwald #define MSBC_SAMPLE_RATE 16000 97dbb41bfeSMilanka Ringwald #define MSBC_FRAMES_PER_BUFFER 120 98dbb41bfeSMilanka Ringwald #define MSBC_PA_SAMPLE_TYPE paInt16 99dbb41bfeSMilanka Ringwald #define MSBC_BYTES_PER_FRAME (2*NUM_CHANNELS) 100dbb41bfeSMilanka Ringwald #define MSBC_PREBUFFER_MS 50 101dbb41bfeSMilanka Ringwald #define MSBC_PREBUFFER_BYTES (MSBC_PREBUFFER_MS * MSBC_SAMPLE_RATE/1000 * MSBC_BYTES_PER_FRAME) 102dbb41bfeSMilanka Ringwald 103f7c85330SMatthias Ringwald // portaudio globals 104f7c85330SMatthias Ringwald static PaStream * stream; 105dbb41bfeSMilanka Ringwald static uint8_t pa_stream_started = 0; 106dbb41bfeSMilanka Ringwald 107dbb41bfeSMilanka Ringwald static uint8_t ring_buffer_storage[2*MSBC_PREBUFFER_BYTES]; 108dbb41bfeSMilanka Ringwald static btstack_ring_buffer_t ring_buffer; 109f7c85330SMatthias Ringwald #endif 110f7c85330SMatthias Ringwald 111fcb08cdbSMilanka Ringwald static int dump_data = 1; 112fcb08cdbSMilanka Ringwald static int count_sent = 0; 113fcb08cdbSMilanka Ringwald static int count_received = 0; 114d76591efSMatthias Ringwald static uint8_t negotiated_codec = 0; 115*1a919128SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_55 116*1a919128SMatthias Ringwald static int phase = 0; 117*1a919128SMatthias Ringwald #endif 118fcb08cdbSMilanka Ringwald 119d5e5f834SMatthias Ringwald FILE * msbc_file_in; 120d5e5f834SMatthias Ringwald FILE * msbc_file_out; 1217294d009SMatthias Ringwald 122f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 123d6a06398SMatthias Ringwald 12435fd3fb9SMatthias Ringwald // input signal: pre-computed sine wave, at 8000 kz 12535fd3fb9SMatthias Ringwald static const uint8_t sine_uint8[] = { 12635fd3fb9SMatthias Ringwald 0, 15, 31, 46, 61, 74, 86, 97, 107, 114, 12735fd3fb9SMatthias Ringwald 120, 124, 126, 126, 124, 120, 114, 107, 97, 86, 12835fd3fb9SMatthias Ringwald 74, 61, 46, 31, 15, 0, 241, 225, 210, 195, 12935fd3fb9SMatthias Ringwald 182, 170, 159, 149, 142, 136, 132, 130, 130, 132, 13035fd3fb9SMatthias Ringwald 136, 142, 149, 159, 170, 182, 195, 210, 225, 241, 13135fd3fb9SMatthias Ringwald }; 13235fd3fb9SMatthias Ringwald 13335fd3fb9SMatthias Ringwald 13435fd3fb9SMatthias Ringwald // input signal: pre-computed sine wave, 160 Hz at 16000 kHz 13535fd3fb9SMatthias Ringwald static const int16_t sine_int16[] = { 13635fd3fb9SMatthias Ringwald 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, 13735fd3fb9SMatthias Ringwald 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, 13835fd3fb9SMatthias Ringwald 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, 13935fd3fb9SMatthias Ringwald 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, 14035fd3fb9SMatthias Ringwald 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, 14135fd3fb9SMatthias Ringwald 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, 14235fd3fb9SMatthias Ringwald -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, 14335fd3fb9SMatthias Ringwald -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, 14435fd3fb9SMatthias Ringwald -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, 14535fd3fb9SMatthias Ringwald -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, 14635fd3fb9SMatthias Ringwald }; 14735fd3fb9SMatthias Ringwald 14835fd3fb9SMatthias Ringwald static void sco_demo_sine_wave_int8(int num_samples, int8_t * data){ 14935fd3fb9SMatthias Ringwald int i; 15035fd3fb9SMatthias Ringwald for (i=0; i<num_samples; i++){ 15135fd3fb9SMatthias Ringwald data[i] = (int8_t)sine_uint8[phase]; 15235fd3fb9SMatthias Ringwald phase++; 15335fd3fb9SMatthias Ringwald if (phase >= sizeof(sine_uint8)) phase = 0; 15435fd3fb9SMatthias Ringwald } 15535fd3fb9SMatthias Ringwald } 15635fd3fb9SMatthias Ringwald 15735fd3fb9SMatthias Ringwald static void sco_demo_sine_wave_int16(int num_samples, int16_t * data){ 15835fd3fb9SMatthias Ringwald int i; 15935fd3fb9SMatthias Ringwald for (i=0; i < num_samples; i++){ 16035fd3fb9SMatthias Ringwald data[i] = sine_int16[phase++]; 16135fd3fb9SMatthias Ringwald if (phase >= (sizeof(sine_int16) / sizeof(int16_t))){ 16235fd3fb9SMatthias Ringwald phase = 0; 16335fd3fb9SMatthias Ringwald } 16435fd3fb9SMatthias Ringwald } 16535fd3fb9SMatthias Ringwald } 166*1a919128SMatthias Ringwald static int num_audio_frames = 0; 16735fd3fb9SMatthias Ringwald 16835fd3fb9SMatthias Ringwald static void sco_demo_fill_audio_frame(void){ 16935fd3fb9SMatthias Ringwald if (!hfp_msbc_can_encode_audio_frame_now()) return; 17035fd3fb9SMatthias Ringwald int num_samples = hfp_msbc_num_audio_samples_per_frame(); 17135fd3fb9SMatthias Ringwald int16_t sample_buffer[num_samples]; 17235fd3fb9SMatthias Ringwald sco_demo_sine_wave_int16(num_samples, sample_buffer); 17335fd3fb9SMatthias Ringwald hfp_msbc_encode_audio_frame(sample_buffer); 17435fd3fb9SMatthias Ringwald num_audio_frames++; 17535fd3fb9SMatthias Ringwald } 1768b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 1772afeea7fSMilanka Ringwald static btstack_sbc_decoder_state_t decoder_state; 17882e01da0SMilanka Ringwald static btstack_cvsd_plc_state_t cvsd_plc_state; 179dbb41bfeSMilanka Ringwald static int num_samples_to_write; 180dbb41bfeSMilanka Ringwald 181dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 182dbb41bfeSMilanka Ringwald static int patestCallback( const void *inputBuffer, void *outputBuffer, 183dbb41bfeSMilanka Ringwald unsigned long framesPerBuffer, 184dbb41bfeSMilanka Ringwald const PaStreamCallbackTimeInfo* timeInfo, 185dbb41bfeSMilanka Ringwald PaStreamCallbackFlags statusFlags, 186dbb41bfeSMilanka Ringwald void *userData ) { 187dbb41bfeSMilanka Ringwald (void) timeInfo; /* Prevent unused variable warnings. */ 188dbb41bfeSMilanka Ringwald (void) statusFlags; 189dbb41bfeSMilanka Ringwald (void) inputBuffer; 190dbb41bfeSMilanka Ringwald 191dbb41bfeSMilanka Ringwald uint32_t bytes_read = 0; 192dbb41bfeSMilanka Ringwald int bytes_per_buffer = framesPerBuffer; 193dbb41bfeSMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 194dbb41bfeSMilanka Ringwald bytes_per_buffer *= MSBC_BYTES_PER_FRAME; 195dbb41bfeSMilanka Ringwald } else { 196dbb41bfeSMilanka Ringwald bytes_per_buffer *= CVSD_BYTES_PER_FRAME; 197dbb41bfeSMilanka Ringwald } 198dbb41bfeSMilanka Ringwald 199dbb41bfeSMilanka Ringwald if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){ 200dbb41bfeSMilanka Ringwald btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read); 201dbb41bfeSMilanka Ringwald } else { 202dbb41bfeSMilanka Ringwald printf("NOT ENOUGH DATA!\n"); 203dbb41bfeSMilanka Ringwald memset(outputBuffer, 0, bytes_per_buffer); 204dbb41bfeSMilanka Ringwald } 205dbb41bfeSMilanka Ringwald // printf("bytes avail after read: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer)); 206dbb41bfeSMilanka Ringwald return 0; 207dbb41bfeSMilanka Ringwald } 208dbb41bfeSMilanka Ringwald #endif 2098b29cfc6SMatthias Ringwald 210fcb08cdbSMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ 211dbb41bfeSMilanka Ringwald // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels); 212dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 213dbb41bfeSMilanka Ringwald if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= MSBC_PREBUFFER_BYTES){ 214dbb41bfeSMilanka Ringwald /* -- start stream -- */ 215dbb41bfeSMilanka Ringwald PaError err = Pa_StartStream(stream); 216dbb41bfeSMilanka Ringwald if (err != paNoError){ 217dbb41bfeSMilanka Ringwald printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 218dbb41bfeSMilanka Ringwald return; 219dbb41bfeSMilanka Ringwald } 220dbb41bfeSMilanka Ringwald pa_stream_started = 1; 221dbb41bfeSMilanka Ringwald } 222dbb41bfeSMilanka Ringwald btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); 223dbb41bfeSMilanka Ringwald // printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer)); 224dbb41bfeSMilanka Ringwald #endif 225dbb41bfeSMilanka Ringwald 226fcb08cdbSMilanka Ringwald if (!num_samples_to_write) return; 227fcb08cdbSMilanka Ringwald 228fcb08cdbSMilanka Ringwald num_samples = btstack_min(num_samples, num_samples_to_write); 229fcb08cdbSMilanka Ringwald num_samples_to_write -= num_samples; 230fcb08cdbSMilanka Ringwald 231fbc7c9f2SMilanka Ringwald wav_writer_write_int16(num_samples, data); 232fcb08cdbSMilanka Ringwald 233fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 234fcb08cdbSMilanka Ringwald sco_demo_close(); 235fcb08cdbSMilanka Ringwald } 236fcb08cdbSMilanka Ringwald } 237fcb08cdbSMilanka Ringwald 238fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){ 239fbc7c9f2SMilanka Ringwald int sample_rate = 16000; 240fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 241fbc7c9f2SMilanka Ringwald btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL); 242fcb08cdbSMilanka Ringwald 243fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 244220eb563SMilanka Ringwald 245220eb563SMilanka Ringwald hfp_msbc_init(); 246220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 247973d7173SMatthias Ringwald 248d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME 249d5e5f834SMatthias Ringwald msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb"); 250d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in); 251d5e5f834SMatthias Ringwald #endif 2527294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME 253d5e5f834SMatthias Ringwald msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb"); 254d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out); 2557294d009SMatthias Ringwald #endif 256dbb41bfeSMilanka Ringwald 257dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 258dbb41bfeSMilanka Ringwald PaError err; 259dbb41bfeSMilanka Ringwald PaStreamParameters outputParameters; 260dbb41bfeSMilanka Ringwald 261dbb41bfeSMilanka Ringwald /* -- initialize PortAudio -- */ 262dbb41bfeSMilanka Ringwald err = Pa_Initialize(); 263dbb41bfeSMilanka Ringwald if( err != paNoError ) return; 264dbb41bfeSMilanka Ringwald /* -- setup input and output -- */ 265dbb41bfeSMilanka Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 266dbb41bfeSMilanka Ringwald outputParameters.channelCount = NUM_CHANNELS; 267dbb41bfeSMilanka Ringwald outputParameters.sampleFormat = MSBC_PA_SAMPLE_TYPE; 268dbb41bfeSMilanka Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 269dbb41bfeSMilanka Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 270dbb41bfeSMilanka Ringwald /* -- setup stream -- */ 271dbb41bfeSMilanka Ringwald err = Pa_OpenStream( 272dbb41bfeSMilanka Ringwald &stream, 273dbb41bfeSMilanka Ringwald NULL, // &inputParameters, 274dbb41bfeSMilanka Ringwald &outputParameters, 275dbb41bfeSMilanka Ringwald MSBC_SAMPLE_RATE, 276dbb41bfeSMilanka Ringwald MSBC_FRAMES_PER_BUFFER, 277dbb41bfeSMilanka Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 278dbb41bfeSMilanka Ringwald patestCallback, /* no callback, use blocking API */ 279dbb41bfeSMilanka Ringwald NULL ); /* no callback, so no callback userData */ 280dbb41bfeSMilanka Ringwald if (err != paNoError){ 281dbb41bfeSMilanka Ringwald printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 282dbb41bfeSMilanka Ringwald return; 283dbb41bfeSMilanka Ringwald } 284dbb41bfeSMilanka Ringwald memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); 285dbb41bfeSMilanka Ringwald btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); 286dbb41bfeSMilanka Ringwald pa_stream_started = 0; 287dbb41bfeSMilanka Ringwald #endif 288fcb08cdbSMilanka Ringwald } 289fcb08cdbSMilanka Ringwald 290fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){ 291fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 292d5e5f834SMatthias Ringwald if (msbc_file_in){ 293d5e5f834SMatthias Ringwald // log incoming mSBC data for testing 294d5e5f834SMatthias Ringwald fwrite(packet+3, size-3, 1, msbc_file_in); 295d5e5f834SMatthias Ringwald } 296fcb08cdbSMilanka Ringwald } 297dbb41bfeSMilanka Ringwald btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3); 298fcb08cdbSMilanka Ringwald } 299fcb08cdbSMilanka Ringwald 300fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){ 301fbc7c9f2SMilanka Ringwald int sample_rate = 8000; 302fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 303fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_init(&cvsd_plc_state); 304fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 305dbb41bfeSMilanka Ringwald 306dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 307dbb41bfeSMilanka Ringwald PaError err; 308dbb41bfeSMilanka Ringwald PaStreamParameters outputParameters; 309dbb41bfeSMilanka Ringwald 310dbb41bfeSMilanka Ringwald /* -- initialize PortAudio -- */ 311dbb41bfeSMilanka Ringwald err = Pa_Initialize(); 312dbb41bfeSMilanka Ringwald if( err != paNoError ) return; 313dbb41bfeSMilanka Ringwald /* -- setup input and output -- */ 314dbb41bfeSMilanka Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 315dbb41bfeSMilanka Ringwald outputParameters.channelCount = NUM_CHANNELS; 316dbb41bfeSMilanka Ringwald outputParameters.sampleFormat = CVSD_PA_SAMPLE_TYPE; 317dbb41bfeSMilanka Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 318dbb41bfeSMilanka Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 319dbb41bfeSMilanka Ringwald /* -- setup stream -- */ 320dbb41bfeSMilanka Ringwald err = Pa_OpenStream( 321dbb41bfeSMilanka Ringwald &stream, 322dbb41bfeSMilanka Ringwald NULL, // &inputParameters, 323dbb41bfeSMilanka Ringwald &outputParameters, 324dbb41bfeSMilanka Ringwald CVSD_SAMPLE_RATE, 325dbb41bfeSMilanka Ringwald CVSD_FRAMES_PER_BUFFER, 326dbb41bfeSMilanka Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 327dbb41bfeSMilanka Ringwald patestCallback, /* no callback, use blocking API */ 328dbb41bfeSMilanka Ringwald NULL ); /* no callback, so no callback userData */ 329dbb41bfeSMilanka Ringwald if (err != paNoError){ 330dbb41bfeSMilanka Ringwald printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 331dbb41bfeSMilanka Ringwald return; 332dbb41bfeSMilanka Ringwald } 333dbb41bfeSMilanka Ringwald memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); 334dbb41bfeSMilanka Ringwald btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); 335dbb41bfeSMilanka Ringwald pa_stream_started = 0; 336dbb41bfeSMilanka Ringwald #endif 337fbc7c9f2SMilanka Ringwald } 338fbc7c9f2SMilanka Ringwald 339fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){ 340dbb41bfeSMilanka Ringwald if (!num_samples_to_write) return; 341dbb41bfeSMilanka Ringwald 342fcb08cdbSMilanka Ringwald const int num_samples = size - 3; 343fcb08cdbSMilanka Ringwald const int samples_to_write = btstack_min(num_samples, num_samples_to_write); 34482e01da0SMilanka Ringwald int8_t audio_frame_out[24]; 345379d044eSMilanka Ringwald 346dbb41bfeSMilanka Ringwald 347fbc7c9f2SMilanka Ringwald // memcpy(audio_frame_out, (int8_t*)(packet+3), 24); 348fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out); 349*1a919128SMatthias Ringwald // int8_t * audio_frame_out = (int8_t*)&packet[3]; 350379d044eSMilanka Ringwald 351fbc7c9f2SMilanka Ringwald wav_writer_write_int8(samples_to_write, audio_frame_out); 352fcb08cdbSMilanka Ringwald num_samples_to_write -= samples_to_write; 353fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 354fcb08cdbSMilanka Ringwald sco_demo_close(); 355fcb08cdbSMilanka Ringwald } 356dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 357dbb41bfeSMilanka Ringwald if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= CVSD_PREBUFFER_BYTES){ 358dbb41bfeSMilanka Ringwald /* -- start stream -- */ 359dbb41bfeSMilanka Ringwald PaError err = Pa_StartStream(stream); 360dbb41bfeSMilanka Ringwald if (err != paNoError){ 361dbb41bfeSMilanka Ringwald printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 362dbb41bfeSMilanka Ringwald return; 363fcb08cdbSMilanka Ringwald } 364dbb41bfeSMilanka Ringwald pa_stream_started = 1; 365dbb41bfeSMilanka Ringwald } 366dbb41bfeSMilanka Ringwald btstack_ring_buffer_write(&ring_buffer, (uint8_t *)audio_frame_out, samples_to_write); 367dbb41bfeSMilanka Ringwald #endif 368fcb08cdbSMilanka Ringwald } 369fcb08cdbSMilanka Ringwald 3708b29cfc6SMatthias Ringwald #endif 3714a96141eSMatthias Ringwald #endif 3728b29cfc6SMatthias Ringwald 373fcb08cdbSMilanka Ringwald void sco_demo_close(void){ 374fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 37526463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 376fbc7c9f2SMilanka Ringwald wav_writer_close(); 37726463303SMilanka Ringwald printf("SCO demo statistics: "); 37826463303SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 37926463303SMilanka Ringwald printf("Used mSBC with PLC, number of processed frames: \n - %d good frames, \n - %d zero frames, \n - %d bad frames.", decoder_state.good_frames_nr, decoder_state.zero_frames_nr, decoder_state.bad_frames_nr); 38026463303SMilanka Ringwald } else { 38126463303SMilanka Ringwald printf("Used CVSD with PLC, number of proccesed frames: \n - %d good frames, \n - %d bad frames.", cvsd_plc_state.good_frames_nr, cvsd_plc_state.bad_frames_nr); 38226463303SMilanka Ringwald } 38326463303SMilanka Ringwald #endif 38426463303SMilanka Ringwald #endif 38526463303SMilanka Ringwald 386dbb41bfeSMilanka Ringwald #ifdef HAVE_PORTAUDIO 387dbb41bfeSMilanka Ringwald if (pa_stream_started){ 388dbb41bfeSMilanka Ringwald PaError err = Pa_StopStream(stream); 389dbb41bfeSMilanka Ringwald if (err != paNoError){ 390dbb41bfeSMilanka Ringwald printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err)); 391dbb41bfeSMilanka Ringwald return; 392dbb41bfeSMilanka Ringwald } 393dbb41bfeSMilanka Ringwald pa_stream_started = 0; 394dbb41bfeSMilanka Ringwald err = Pa_CloseStream(stream); 395dbb41bfeSMilanka Ringwald if (err != paNoError){ 396dbb41bfeSMilanka Ringwald printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err)); 397dbb41bfeSMilanka Ringwald return; 398dbb41bfeSMilanka Ringwald } 399dbb41bfeSMilanka Ringwald 400dbb41bfeSMilanka Ringwald err = Pa_Terminate(); 401dbb41bfeSMilanka Ringwald if (err != paNoError){ 402dbb41bfeSMilanka Ringwald printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err)); 403dbb41bfeSMilanka Ringwald return; 404dbb41bfeSMilanka Ringwald } 405dbb41bfeSMilanka Ringwald } 406dbb41bfeSMilanka Ringwald #endif 407dbb41bfeSMilanka Ringwald 40826463303SMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 409fcb08cdbSMilanka Ringwald #ifdef SCO_WAV_FILENAME 410fcb08cdbSMilanka Ringwald 411613518d1SMilanka Ringwald #if 0 412fcb08cdbSMilanka Ringwald printf("SCO Demo: closing wav file\n"); 413220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 4146e046a36SMatthias Ringwald wav_writer_state_t * writer_state = &wav_writer_state; 415fcb08cdbSMilanka Ringwald if (!writer_state->wav_file) return; 416fcb08cdbSMilanka Ringwald rewind(writer_state->wav_file); 4172afeea7fSMilanka Ringwald write_wav_header(writer_state->wav_file, writer_state->total_num_samples, btstack_sbc_decoder_num_channels(&decoder_state), btstack_sbc_decoder_sample_rate(&decoder_state),2); 418fcb08cdbSMilanka Ringwald fclose(writer_state->wav_file); 419fcb08cdbSMilanka Ringwald writer_state->wav_file = NULL; 420fcb08cdbSMilanka Ringwald } 421613518d1SMilanka Ringwald #endif 422fcb08cdbSMilanka Ringwald #endif 423fcb08cdbSMilanka Ringwald #endif 424fcb08cdbSMilanka Ringwald } 425fcb08cdbSMilanka Ringwald 426fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){ 427fcb08cdbSMilanka Ringwald if (negotiated_codec == codec) return; 428fcb08cdbSMilanka Ringwald negotiated_codec = codec; 429fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 43017cd946eSMatthias Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 431220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 432fcb08cdbSMilanka Ringwald sco_demo_init_mSBC(); 433fcb08cdbSMilanka Ringwald } else { 434fcb08cdbSMilanka Ringwald sco_demo_init_CVSD(); 435fcb08cdbSMilanka Ringwald } 436fcb08cdbSMilanka Ringwald #endif 437fcb08cdbSMilanka Ringwald #endif 438fcb08cdbSMilanka Ringwald } 439fcb08cdbSMilanka Ringwald 440f7c85330SMatthias Ringwald void sco_demo_init(void){ 441f7c85330SMatthias Ringwald 442f7c85330SMatthias Ringwald // status 443f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 444f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO 445f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, audio output via portaudio.\n"); 446f7c85330SMatthias Ringwald #else 447f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, hexdump received data.\n"); 448f7c85330SMatthias Ringwald #endif 449f7c85330SMatthias Ringwald #endif 450f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 451f7c85330SMatthias Ringwald printf("SCO Demo: Sending ASCII blocks, print received data.\n"); 452f7c85330SMatthias Ringwald #endif 453f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 454f7c85330SMatthias Ringwald printf("SCO Demo: Sending counter value, hexdump received data.\n"); 455f7c85330SMatthias Ringwald #endif 456f7c85330SMatthias Ringwald 4577294d009SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_SINE 458f7c85330SMatthias Ringwald hci_set_sco_voice_setting(0x03); // linear, unsigned, 8-bit, transparent 4597294d009SMatthias Ringwald #endif 460f7c85330SMatthias Ringwald 461f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 462f7c85330SMatthias Ringwald phase = 'a'; 463f7c85330SMatthias Ringwald #endif 464f7c85330SMatthias Ringwald } 465f7c85330SMatthias Ringwald 466*1a919128SMatthias Ringwald void sco_report(void); 467*1a919128SMatthias Ringwald void sco_report(void){ 4684a96141eSMatthias Ringwald printf("SCO: sent %u, received %u\n", count_sent, count_received); 4694a96141eSMatthias Ringwald } 470f7c85330SMatthias Ringwald 471f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){ 472f7c85330SMatthias Ringwald 473f7c85330SMatthias Ringwald if (!sco_handle) return; 474f7c85330SMatthias Ringwald 475f7c85330SMatthias Ringwald const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length(); 476f7c85330SMatthias Ringwald const int sco_payload_length = sco_packet_length - 3; 477f7c85330SMatthias Ringwald 478f7c85330SMatthias Ringwald hci_reserve_packet_buffer(); 479f7c85330SMatthias Ringwald uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); 480f7c85330SMatthias Ringwald // set handle + flags 481f7c85330SMatthias Ringwald little_endian_store_16(sco_packet, 0, sco_handle); 482f7c85330SMatthias Ringwald // set len 483f7c85330SMatthias Ringwald sco_packet[2] = sco_payload_length; 484220eb563SMilanka Ringwald const int audio_samples_per_packet = sco_payload_length; // for 8-bit data. for 16-bit data it's /2 485f7c85330SMatthias Ringwald 486f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 487220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 488220eb563SMilanka Ringwald 489220eb563SMilanka Ringwald if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){ 490220eb563SMilanka Ringwald log_error("mSBC stream is empty."); 491220eb563SMilanka Ringwald } 492220eb563SMilanka Ringwald hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length); 493d5e5f834SMatthias Ringwald if (msbc_file_out){ 494d76591efSMatthias Ringwald // log outgoing mSBC data for testing 495d5e5f834SMatthias Ringwald fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out); 496d76591efSMatthias Ringwald } 4977294d009SMatthias Ringwald 498220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 499220eb563SMilanka Ringwald } else { 50035fd3fb9SMatthias Ringwald sco_demo_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3)); 501220eb563SMilanka Ringwald } 502*1a919128SMatthias Ringwald #endif 503f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 504220eb563SMilanka Ringwald memset(&sco_packet[3], phase++, audio_samples_per_packet); 505f7c85330SMatthias Ringwald if (phase > 'z') phase = 'a'; 506*1a919128SMatthias Ringwald #endif 507*1a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 50838b2eaafSMatthias Ringwald int j; 509220eb563SMilanka Ringwald for (j=0;j<audio_samples_per_packet;j++){ 51038b2eaafSMatthias Ringwald sco_packet[3+j] = phase++; 511f7c85330SMatthias Ringwald } 512f7c85330SMatthias Ringwald #endif 513*1a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 514*1a919128SMatthias Ringwald int j; 515*1a919128SMatthias Ringwald for (j=0;j<audio_samples_per_packet;j++){ 516*1a919128SMatthias Ringwald // sco_packet[3+j] = j & 1 ? 0x35 : 0x53; 517*1a919128SMatthias Ringwald sco_packet[3+j] = 0x55; 518*1a919128SMatthias Ringwald } 519*1a919128SMatthias Ringwald #endif 520*1a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_00 521*1a919128SMatthias Ringwald int j; 522*1a919128SMatthias Ringwald for (j=0;j<audio_samples_per_packet;j++){ 523*1a919128SMatthias Ringwald sco_packet[3+j] = 0x00; 524*1a919128SMatthias Ringwald } 525*1a919128SMatthias Ringwald // additional hack 526*1a919128SMatthias Ringwald // big_endian_store_16(sco_packet, 5, phase++); 527*1a919128SMatthias Ringwald (void) phase; 528f7c85330SMatthias Ringwald #endif 529220eb563SMilanka Ringwald 530f7c85330SMatthias Ringwald hci_send_sco_packet_buffer(sco_packet_length); 531f7c85330SMatthias Ringwald 532f7c85330SMatthias Ringwald // request another send event 533f7c85330SMatthias Ringwald hci_request_sco_can_send_now_event(); 534f7c85330SMatthias Ringwald 5354a96141eSMatthias Ringwald count_sent++; 536*1a919128SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_55 5374a96141eSMatthias Ringwald if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report(); 538*1a919128SMatthias Ringwald #endif 539f7c85330SMatthias Ringwald } 540f7c85330SMatthias Ringwald 541f7c85330SMatthias Ringwald /** 542f7c85330SMatthias Ringwald * @brief Process received data 543f7c85330SMatthias Ringwald */ 544*1a919128SMatthias Ringwald #define ANSI_COLOR_RED "\x1b[31m" 545*1a919128SMatthias Ringwald #define ANSI_COLOR_GREEN "\x1b[32m" 546*1a919128SMatthias Ringwald #define ANSI_COLOR_YELLOW "\x1b[33m" 547*1a919128SMatthias Ringwald #define ANSI_COLOR_BLUE "\x1b[34m" 548*1a919128SMatthias Ringwald #define ANSI_COLOR_MAGENTA "\x1b[35m" 549*1a919128SMatthias Ringwald #define ANSI_COLOR_CYAN "\x1b[36m" 550*1a919128SMatthias Ringwald #define ANSI_COLOR_RESET "\x1b[0m" 551*1a919128SMatthias Ringwald 552f7c85330SMatthias Ringwald void sco_demo_receive(uint8_t * packet, uint16_t size){ 553f7c85330SMatthias Ringwald 554fcb08cdbSMilanka Ringwald dump_data = 1; 5558b29cfc6SMatthias Ringwald 5564a96141eSMatthias Ringwald count_received++; 557*1a919128SMatthias Ringwald static uint32_t packets = 0; 558*1a919128SMatthias Ringwald static uint32_t crc_errors = 0; 559*1a919128SMatthias Ringwald static uint32_t data_received = 0; 560*1a919128SMatthias Ringwald static uint32_t byte_errors = 0; 5614a96141eSMatthias Ringwald 562*1a919128SMatthias Ringwald data_received += size - 3; 563*1a919128SMatthias Ringwald packets++; 564*1a919128SMatthias Ringwald if (data_received > 100000){ 565*1a919128SMatthias Ringwald printf("Summary: data %07u, packets %04u, packet with crc errors %0u, byte errors %04u\n", data_received, packets, crc_errors, byte_errors); 566*1a919128SMatthias Ringwald crc_errors = 0; 567*1a919128SMatthias Ringwald byte_errors = 0; 568*1a919128SMatthias Ringwald data_received = 0; 569*1a919128SMatthias Ringwald packets = 0; 570*1a919128SMatthias Ringwald } 5714a96141eSMatthias Ringwald 5724a96141eSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 5738b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 574220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 575fcb08cdbSMilanka Ringwald sco_demo_receive_mSBC(packet, size); 576fcb08cdbSMilanka Ringwald } else { 577fcb08cdbSMilanka Ringwald sco_demo_receive_CVSD(packet, size); 5788b29cfc6SMatthias Ringwald } 579dbb41bfeSMilanka Ringwald dump_data = 0; 5808b29cfc6SMatthias Ringwald #endif 5814a96141eSMatthias Ringwald #endif 5828b29cfc6SMatthias Ringwald 583b3f76298SMilanka Ringwald if (packet[1] & 0x30){ 584*1a919128SMatthias Ringwald crc_errors++; 585*1a919128SMatthias Ringwald // printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4); 586*1a919128SMatthias Ringwald // printf_hexdump(&packet[3], size-3); 587f7c85330SMatthias Ringwald return; 588f7c85330SMatthias Ringwald } 5898b29cfc6SMatthias Ringwald if (dump_data){ 590f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 591*1a919128SMatthias Ringwald printf("data: "); 592f7c85330SMatthias Ringwald int i; 593f7c85330SMatthias Ringwald for (i=3;i<size;i++){ 594f7c85330SMatthias Ringwald printf("%c", packet[i]); 595f7c85330SMatthias Ringwald } 596f7c85330SMatthias Ringwald printf("\n"); 5978b29cfc6SMatthias Ringwald dump_data = 0; 598*1a919128SMatthias Ringwald #endif 599*1a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 600*1a919128SMatthias Ringwald // colored hexdump with expected 601*1a919128SMatthias Ringwald static uint8_t expected_byte = 0; 602*1a919128SMatthias Ringwald int i; 603*1a919128SMatthias Ringwald printf("data: "); 604*1a919128SMatthias Ringwald for (i=3;i<size;i++){ 605*1a919128SMatthias Ringwald if (packet[i] != expected_byte){ 606*1a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 607*1a919128SMatthias Ringwald } else { 608*1a919128SMatthias Ringwald printf("%02x ", packet[i]); 609*1a919128SMatthias Ringwald } 610*1a919128SMatthias Ringwald expected_byte = packet[i]+1; 611*1a919128SMatthias Ringwald } 612*1a919128SMatthias Ringwald printf("\n"); 613*1a919128SMatthias Ringwald #endif 614*1a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE_00 615*1a919128SMatthias Ringwald int i; 616*1a919128SMatthias Ringwald int contains_error = 0; 617*1a919128SMatthias Ringwald for (i=3;i<size;i++){ 618*1a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 619*1a919128SMatthias Ringwald contains_error = 1; 620*1a919128SMatthias Ringwald byte_errors++; 621*1a919128SMatthias Ringwald } 622*1a919128SMatthias Ringwald } 623*1a919128SMatthias Ringwald if (contains_error){ 624*1a919128SMatthias Ringwald printf("data: "); 625*1a919128SMatthias Ringwald for (i=0;i<3;i++){ 626*1a919128SMatthias Ringwald printf("%02x ", packet[i]); 627*1a919128SMatthias Ringwald } 628*1a919128SMatthias Ringwald for (i=3;i<size;i++){ 629*1a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 630*1a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 631*1a919128SMatthias Ringwald } else { 632*1a919128SMatthias Ringwald printf("%02x ", packet[i]); 633*1a919128SMatthias Ringwald } 634*1a919128SMatthias Ringwald } 635*1a919128SMatthias Ringwald printf("\n"); 636*1a919128SMatthias Ringwald } 637f7c85330SMatthias Ringwald #endif 6388b29cfc6SMatthias Ringwald } 639f7c85330SMatthias Ringwald } 640