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 601a919128SMatthias Ringwald #define SCO_DEMO_MODE_55 3 611a919128SMatthias 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 811a919128SMatthias 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; 1151a919128SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_55 1161a919128SMatthias Ringwald static int phase = 0; 1171a919128SMatthias 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 } 1661a919128SMatthias 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){ 211*9ec2630cSMatthias Ringwald UNUSED(context); 212*9ec2630cSMatthias Ringwald UNUSED(sample_rate); 213*9ec2630cSMatthias Ringwald 214dbb41bfeSMilanka Ringwald // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels); 215dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 216dbb41bfeSMilanka Ringwald if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= MSBC_PREBUFFER_BYTES){ 217dbb41bfeSMilanka Ringwald /* -- start stream -- */ 218dbb41bfeSMilanka Ringwald PaError err = Pa_StartStream(stream); 219dbb41bfeSMilanka Ringwald if (err != paNoError){ 220dbb41bfeSMilanka Ringwald printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 221dbb41bfeSMilanka Ringwald return; 222dbb41bfeSMilanka Ringwald } 223dbb41bfeSMilanka Ringwald pa_stream_started = 1; 224dbb41bfeSMilanka Ringwald } 225dbb41bfeSMilanka Ringwald btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); 226dbb41bfeSMilanka Ringwald // printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer)); 227*9ec2630cSMatthias Ringwald #else 228*9ec2630cSMatthias Ringwald UNUSED(num_channels); 229dbb41bfeSMilanka Ringwald #endif 230dbb41bfeSMilanka Ringwald 231fcb08cdbSMilanka Ringwald if (!num_samples_to_write) return; 232fcb08cdbSMilanka Ringwald 233fcb08cdbSMilanka Ringwald num_samples = btstack_min(num_samples, num_samples_to_write); 234fcb08cdbSMilanka Ringwald num_samples_to_write -= num_samples; 235fcb08cdbSMilanka Ringwald 236fbc7c9f2SMilanka Ringwald wav_writer_write_int16(num_samples, data); 237fcb08cdbSMilanka Ringwald 238fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 239fcb08cdbSMilanka Ringwald sco_demo_close(); 240fcb08cdbSMilanka Ringwald } 241fcb08cdbSMilanka Ringwald } 242fcb08cdbSMilanka Ringwald 243fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){ 244fbc7c9f2SMilanka Ringwald int sample_rate = 16000; 245fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 246fbc7c9f2SMilanka Ringwald btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL); 247fcb08cdbSMilanka Ringwald 248fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 249220eb563SMilanka Ringwald 250220eb563SMilanka Ringwald hfp_msbc_init(); 251220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 252973d7173SMatthias Ringwald 253d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME 254d5e5f834SMatthias Ringwald msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb"); 255d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in); 256d5e5f834SMatthias Ringwald #endif 2577294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME 258d5e5f834SMatthias Ringwald msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb"); 259d5e5f834SMatthias Ringwald printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out); 2607294d009SMatthias Ringwald #endif 261dbb41bfeSMilanka Ringwald 262dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 263dbb41bfeSMilanka Ringwald PaError err; 264dbb41bfeSMilanka Ringwald PaStreamParameters outputParameters; 265dbb41bfeSMilanka Ringwald 266dbb41bfeSMilanka Ringwald /* -- initialize PortAudio -- */ 267dbb41bfeSMilanka Ringwald err = Pa_Initialize(); 268dbb41bfeSMilanka Ringwald if( err != paNoError ) return; 269dbb41bfeSMilanka Ringwald /* -- setup input and output -- */ 270dbb41bfeSMilanka Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 271dbb41bfeSMilanka Ringwald outputParameters.channelCount = NUM_CHANNELS; 272dbb41bfeSMilanka Ringwald outputParameters.sampleFormat = MSBC_PA_SAMPLE_TYPE; 273dbb41bfeSMilanka Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 274dbb41bfeSMilanka Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 275dbb41bfeSMilanka Ringwald /* -- setup stream -- */ 276dbb41bfeSMilanka Ringwald err = Pa_OpenStream( 277dbb41bfeSMilanka Ringwald &stream, 278dbb41bfeSMilanka Ringwald NULL, // &inputParameters, 279dbb41bfeSMilanka Ringwald &outputParameters, 280dbb41bfeSMilanka Ringwald MSBC_SAMPLE_RATE, 281dbb41bfeSMilanka Ringwald MSBC_FRAMES_PER_BUFFER, 282dbb41bfeSMilanka Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 283dbb41bfeSMilanka Ringwald patestCallback, /* no callback, use blocking API */ 284dbb41bfeSMilanka Ringwald NULL ); /* no callback, so no callback userData */ 285dbb41bfeSMilanka Ringwald if (err != paNoError){ 286dbb41bfeSMilanka Ringwald printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 287dbb41bfeSMilanka Ringwald return; 288dbb41bfeSMilanka Ringwald } 289dbb41bfeSMilanka Ringwald memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); 290dbb41bfeSMilanka Ringwald btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); 291dbb41bfeSMilanka Ringwald pa_stream_started = 0; 292dbb41bfeSMilanka Ringwald #endif 293fcb08cdbSMilanka Ringwald } 294fcb08cdbSMilanka Ringwald 295fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){ 296fcb08cdbSMilanka Ringwald if (num_samples_to_write){ 297d5e5f834SMatthias Ringwald if (msbc_file_in){ 298d5e5f834SMatthias Ringwald // log incoming mSBC data for testing 299d5e5f834SMatthias Ringwald fwrite(packet+3, size-3, 1, msbc_file_in); 300d5e5f834SMatthias Ringwald } 301fcb08cdbSMilanka Ringwald } 302dbb41bfeSMilanka Ringwald btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3); 303fcb08cdbSMilanka Ringwald } 304fcb08cdbSMilanka Ringwald 305fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){ 306fbc7c9f2SMilanka Ringwald int sample_rate = 8000; 307fbc7c9f2SMilanka Ringwald wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate); 308fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_init(&cvsd_plc_state); 309fbc7c9f2SMilanka Ringwald num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS; 310dbb41bfeSMilanka Ringwald 311dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 312dbb41bfeSMilanka Ringwald PaError err; 313dbb41bfeSMilanka Ringwald PaStreamParameters outputParameters; 314dbb41bfeSMilanka Ringwald 315dbb41bfeSMilanka Ringwald /* -- initialize PortAudio -- */ 316dbb41bfeSMilanka Ringwald err = Pa_Initialize(); 317dbb41bfeSMilanka Ringwald if( err != paNoError ) return; 318dbb41bfeSMilanka Ringwald /* -- setup input and output -- */ 319dbb41bfeSMilanka Ringwald outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 320dbb41bfeSMilanka Ringwald outputParameters.channelCount = NUM_CHANNELS; 321dbb41bfeSMilanka Ringwald outputParameters.sampleFormat = CVSD_PA_SAMPLE_TYPE; 322dbb41bfeSMilanka Ringwald outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; 323dbb41bfeSMilanka Ringwald outputParameters.hostApiSpecificStreamInfo = NULL; 324dbb41bfeSMilanka Ringwald /* -- setup stream -- */ 325dbb41bfeSMilanka Ringwald err = Pa_OpenStream( 326dbb41bfeSMilanka Ringwald &stream, 327dbb41bfeSMilanka Ringwald NULL, // &inputParameters, 328dbb41bfeSMilanka Ringwald &outputParameters, 329dbb41bfeSMilanka Ringwald CVSD_SAMPLE_RATE, 330dbb41bfeSMilanka Ringwald CVSD_FRAMES_PER_BUFFER, 331dbb41bfeSMilanka Ringwald paClipOff, /* we won't output out of range samples so don't bother clipping them */ 332dbb41bfeSMilanka Ringwald patestCallback, /* no callback, use blocking API */ 333dbb41bfeSMilanka Ringwald NULL ); /* no callback, so no callback userData */ 334dbb41bfeSMilanka Ringwald if (err != paNoError){ 335dbb41bfeSMilanka Ringwald printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); 336dbb41bfeSMilanka Ringwald return; 337dbb41bfeSMilanka Ringwald } 338dbb41bfeSMilanka Ringwald memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); 339dbb41bfeSMilanka Ringwald btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); 340dbb41bfeSMilanka Ringwald pa_stream_started = 0; 341dbb41bfeSMilanka Ringwald #endif 342fbc7c9f2SMilanka Ringwald } 343fbc7c9f2SMilanka Ringwald 344fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){ 345dbb41bfeSMilanka Ringwald if (!num_samples_to_write) return; 346dbb41bfeSMilanka Ringwald 347fcb08cdbSMilanka Ringwald const int num_samples = size - 3; 348fcb08cdbSMilanka Ringwald const int samples_to_write = btstack_min(num_samples, num_samples_to_write); 34982e01da0SMilanka Ringwald int8_t audio_frame_out[24]; 350379d044eSMilanka Ringwald 351dbb41bfeSMilanka Ringwald 352fbc7c9f2SMilanka Ringwald // memcpy(audio_frame_out, (int8_t*)(packet+3), 24); 353fbc7c9f2SMilanka Ringwald btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out); 3541a919128SMatthias Ringwald // int8_t * audio_frame_out = (int8_t*)&packet[3]; 355379d044eSMilanka Ringwald 356fbc7c9f2SMilanka Ringwald wav_writer_write_int8(samples_to_write, audio_frame_out); 357fcb08cdbSMilanka Ringwald num_samples_to_write -= samples_to_write; 358fcb08cdbSMilanka Ringwald if (num_samples_to_write == 0){ 359fcb08cdbSMilanka Ringwald sco_demo_close(); 360fcb08cdbSMilanka Ringwald } 361dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO 362dbb41bfeSMilanka Ringwald if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= CVSD_PREBUFFER_BYTES){ 363dbb41bfeSMilanka Ringwald /* -- start stream -- */ 364dbb41bfeSMilanka Ringwald PaError err = Pa_StartStream(stream); 365dbb41bfeSMilanka Ringwald if (err != paNoError){ 366dbb41bfeSMilanka Ringwald printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); 367dbb41bfeSMilanka Ringwald return; 368fcb08cdbSMilanka Ringwald } 369dbb41bfeSMilanka Ringwald pa_stream_started = 1; 370dbb41bfeSMilanka Ringwald } 371dbb41bfeSMilanka Ringwald btstack_ring_buffer_write(&ring_buffer, (uint8_t *)audio_frame_out, samples_to_write); 372dbb41bfeSMilanka Ringwald #endif 373fcb08cdbSMilanka Ringwald } 374fcb08cdbSMilanka Ringwald 3758b29cfc6SMatthias Ringwald #endif 3764a96141eSMatthias Ringwald #endif 3778b29cfc6SMatthias Ringwald 378fcb08cdbSMilanka Ringwald void sco_demo_close(void){ 379fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 38026463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 381fbc7c9f2SMilanka Ringwald wav_writer_close(); 38226463303SMilanka Ringwald printf("SCO demo statistics: "); 38326463303SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 38426463303SMilanka 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); 38526463303SMilanka Ringwald } else { 38626463303SMilanka 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); 38726463303SMilanka Ringwald } 38826463303SMilanka Ringwald #endif 38926463303SMilanka Ringwald #endif 39026463303SMilanka Ringwald 391dbb41bfeSMilanka Ringwald #ifdef HAVE_PORTAUDIO 392dbb41bfeSMilanka Ringwald if (pa_stream_started){ 393dbb41bfeSMilanka Ringwald PaError err = Pa_StopStream(stream); 394dbb41bfeSMilanka Ringwald if (err != paNoError){ 395dbb41bfeSMilanka Ringwald printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err)); 396dbb41bfeSMilanka Ringwald return; 397dbb41bfeSMilanka Ringwald } 398dbb41bfeSMilanka Ringwald pa_stream_started = 0; 399dbb41bfeSMilanka Ringwald err = Pa_CloseStream(stream); 400dbb41bfeSMilanka Ringwald if (err != paNoError){ 401dbb41bfeSMilanka Ringwald printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err)); 402dbb41bfeSMilanka Ringwald return; 403dbb41bfeSMilanka Ringwald } 404dbb41bfeSMilanka Ringwald 405dbb41bfeSMilanka Ringwald err = Pa_Terminate(); 406dbb41bfeSMilanka Ringwald if (err != paNoError){ 407dbb41bfeSMilanka Ringwald printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err)); 408dbb41bfeSMilanka Ringwald return; 409dbb41bfeSMilanka Ringwald } 410dbb41bfeSMilanka Ringwald } 411dbb41bfeSMilanka Ringwald #endif 412dbb41bfeSMilanka Ringwald 41326463303SMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 414fcb08cdbSMilanka Ringwald #ifdef SCO_WAV_FILENAME 415fcb08cdbSMilanka Ringwald 416613518d1SMilanka Ringwald #if 0 417fcb08cdbSMilanka Ringwald printf("SCO Demo: closing wav file\n"); 418220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 4196e046a36SMatthias Ringwald wav_writer_state_t * writer_state = &wav_writer_state; 420fcb08cdbSMilanka Ringwald if (!writer_state->wav_file) return; 421fcb08cdbSMilanka Ringwald rewind(writer_state->wav_file); 4222afeea7fSMilanka 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); 423fcb08cdbSMilanka Ringwald fclose(writer_state->wav_file); 424fcb08cdbSMilanka Ringwald writer_state->wav_file = NULL; 425fcb08cdbSMilanka Ringwald } 426613518d1SMilanka Ringwald #endif 427fcb08cdbSMilanka Ringwald #endif 428fcb08cdbSMilanka Ringwald #endif 429fcb08cdbSMilanka Ringwald } 430fcb08cdbSMilanka Ringwald 431fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){ 432fcb08cdbSMilanka Ringwald if (negotiated_codec == codec) return; 433fcb08cdbSMilanka Ringwald negotiated_codec = codec; 434fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 43517cd946eSMatthias Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME) 436220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 437fcb08cdbSMilanka Ringwald sco_demo_init_mSBC(); 438fcb08cdbSMilanka Ringwald } else { 439fcb08cdbSMilanka Ringwald sco_demo_init_CVSD(); 440fcb08cdbSMilanka Ringwald } 441fcb08cdbSMilanka Ringwald #endif 442fcb08cdbSMilanka Ringwald #endif 443fcb08cdbSMilanka Ringwald } 444fcb08cdbSMilanka Ringwald 445f7c85330SMatthias Ringwald void sco_demo_init(void){ 446f7c85330SMatthias Ringwald 447f7c85330SMatthias Ringwald // status 448f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 449f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO 450f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, audio output via portaudio.\n"); 451f7c85330SMatthias Ringwald #else 452f7c85330SMatthias Ringwald printf("SCO Demo: Sending sine wave, hexdump received data.\n"); 453f7c85330SMatthias Ringwald #endif 454f7c85330SMatthias Ringwald #endif 455f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 456f7c85330SMatthias Ringwald printf("SCO Demo: Sending ASCII blocks, print received data.\n"); 457f7c85330SMatthias Ringwald #endif 458f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 459f7c85330SMatthias Ringwald printf("SCO Demo: Sending counter value, hexdump received data.\n"); 460f7c85330SMatthias Ringwald #endif 461f7c85330SMatthias Ringwald 4627294d009SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_SINE 463f7c85330SMatthias Ringwald hci_set_sco_voice_setting(0x03); // linear, unsigned, 8-bit, transparent 4647294d009SMatthias Ringwald #endif 465f7c85330SMatthias Ringwald 466f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 467f7c85330SMatthias Ringwald phase = 'a'; 468f7c85330SMatthias Ringwald #endif 469f7c85330SMatthias Ringwald } 470f7c85330SMatthias Ringwald 4711a919128SMatthias Ringwald void sco_report(void); 4721a919128SMatthias Ringwald void sco_report(void){ 4734a96141eSMatthias Ringwald printf("SCO: sent %u, received %u\n", count_sent, count_received); 4744a96141eSMatthias Ringwald } 475f7c85330SMatthias Ringwald 476f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){ 477f7c85330SMatthias Ringwald 478f7c85330SMatthias Ringwald if (!sco_handle) return; 479f7c85330SMatthias Ringwald 480f7c85330SMatthias Ringwald const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length(); 481f7c85330SMatthias Ringwald const int sco_payload_length = sco_packet_length - 3; 482f7c85330SMatthias Ringwald 483f7c85330SMatthias Ringwald hci_reserve_packet_buffer(); 484f7c85330SMatthias Ringwald uint8_t * sco_packet = hci_get_outgoing_packet_buffer(); 485f7c85330SMatthias Ringwald // set handle + flags 486f7c85330SMatthias Ringwald little_endian_store_16(sco_packet, 0, sco_handle); 487f7c85330SMatthias Ringwald // set len 488f7c85330SMatthias Ringwald sco_packet[2] = sco_payload_length; 489220eb563SMilanka Ringwald const int audio_samples_per_packet = sco_payload_length; // for 8-bit data. for 16-bit data it's /2 490f7c85330SMatthias Ringwald 491f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 492220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 493220eb563SMilanka Ringwald 494220eb563SMilanka Ringwald if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){ 495220eb563SMilanka Ringwald log_error("mSBC stream is empty."); 496220eb563SMilanka Ringwald } 497220eb563SMilanka Ringwald hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length); 498d5e5f834SMatthias Ringwald if (msbc_file_out){ 499d76591efSMatthias Ringwald // log outgoing mSBC data for testing 500d5e5f834SMatthias Ringwald fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out); 501d76591efSMatthias Ringwald } 5027294d009SMatthias Ringwald 503220eb563SMilanka Ringwald sco_demo_fill_audio_frame(); 504220eb563SMilanka Ringwald } else { 50535fd3fb9SMatthias Ringwald sco_demo_sine_wave_int8(audio_samples_per_packet, (int8_t *) (sco_packet+3)); 506220eb563SMilanka Ringwald } 5071a919128SMatthias Ringwald #endif 508f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 509220eb563SMilanka Ringwald memset(&sco_packet[3], phase++, audio_samples_per_packet); 510f7c85330SMatthias Ringwald if (phase > 'z') phase = 'a'; 5111a919128SMatthias Ringwald #endif 5121a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 51338b2eaafSMatthias Ringwald int j; 514220eb563SMilanka Ringwald for (j=0;j<audio_samples_per_packet;j++){ 51538b2eaafSMatthias Ringwald sco_packet[3+j] = phase++; 516f7c85330SMatthias Ringwald } 517f7c85330SMatthias Ringwald #endif 5181a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 5191a919128SMatthias Ringwald int j; 5201a919128SMatthias Ringwald for (j=0;j<audio_samples_per_packet;j++){ 5211a919128SMatthias Ringwald // sco_packet[3+j] = j & 1 ? 0x35 : 0x53; 5221a919128SMatthias Ringwald sco_packet[3+j] = 0x55; 5231a919128SMatthias Ringwald } 5241a919128SMatthias Ringwald #endif 5251a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_00 5261a919128SMatthias Ringwald int j; 5271a919128SMatthias Ringwald for (j=0;j<audio_samples_per_packet;j++){ 5281a919128SMatthias Ringwald sco_packet[3+j] = 0x00; 5291a919128SMatthias Ringwald } 5301a919128SMatthias Ringwald // additional hack 5311a919128SMatthias Ringwald // big_endian_store_16(sco_packet, 5, phase++); 5321a919128SMatthias Ringwald (void) phase; 533f7c85330SMatthias Ringwald #endif 534220eb563SMilanka Ringwald 535f7c85330SMatthias Ringwald hci_send_sco_packet_buffer(sco_packet_length); 536f7c85330SMatthias Ringwald 537f7c85330SMatthias Ringwald // request another send event 538f7c85330SMatthias Ringwald hci_request_sco_can_send_now_event(); 539f7c85330SMatthias Ringwald 5404a96141eSMatthias Ringwald count_sent++; 5411a919128SMatthias Ringwald #if SCO_DEMO_MODE != SCO_DEMO_MODE_55 5424a96141eSMatthias Ringwald if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report(); 5431a919128SMatthias Ringwald #endif 544f7c85330SMatthias Ringwald } 545f7c85330SMatthias Ringwald 546f7c85330SMatthias Ringwald /** 547f7c85330SMatthias Ringwald * @brief Process received data 548f7c85330SMatthias Ringwald */ 5491a919128SMatthias Ringwald #define ANSI_COLOR_RED "\x1b[31m" 5501a919128SMatthias Ringwald #define ANSI_COLOR_GREEN "\x1b[32m" 5511a919128SMatthias Ringwald #define ANSI_COLOR_YELLOW "\x1b[33m" 5521a919128SMatthias Ringwald #define ANSI_COLOR_BLUE "\x1b[34m" 5531a919128SMatthias Ringwald #define ANSI_COLOR_MAGENTA "\x1b[35m" 5541a919128SMatthias Ringwald #define ANSI_COLOR_CYAN "\x1b[36m" 5551a919128SMatthias Ringwald #define ANSI_COLOR_RESET "\x1b[0m" 5561a919128SMatthias Ringwald 557f7c85330SMatthias Ringwald void sco_demo_receive(uint8_t * packet, uint16_t size){ 558f7c85330SMatthias Ringwald 559fcb08cdbSMilanka Ringwald dump_data = 1; 5608b29cfc6SMatthias Ringwald 5614a96141eSMatthias Ringwald count_received++; 5621a919128SMatthias Ringwald static uint32_t packets = 0; 5631a919128SMatthias Ringwald static uint32_t crc_errors = 0; 5641a919128SMatthias Ringwald static uint32_t data_received = 0; 5651a919128SMatthias Ringwald static uint32_t byte_errors = 0; 5664a96141eSMatthias Ringwald 5671a919128SMatthias Ringwald data_received += size - 3; 5681a919128SMatthias Ringwald packets++; 5691a919128SMatthias Ringwald if (data_received > 100000){ 5701a919128SMatthias Ringwald printf("Summary: data %07u, packets %04u, packet with crc errors %0u, byte errors %04u\n", data_received, packets, crc_errors, byte_errors); 5711a919128SMatthias Ringwald crc_errors = 0; 5721a919128SMatthias Ringwald byte_errors = 0; 5731a919128SMatthias Ringwald data_received = 0; 5741a919128SMatthias Ringwald packets = 0; 5751a919128SMatthias Ringwald } 5764a96141eSMatthias Ringwald 5774a96141eSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE 5788b29cfc6SMatthias Ringwald #ifdef SCO_WAV_FILENAME 579220eb563SMilanka Ringwald if (negotiated_codec == HFP_CODEC_MSBC){ 580fcb08cdbSMilanka Ringwald sco_demo_receive_mSBC(packet, size); 581fcb08cdbSMilanka Ringwald } else { 582fcb08cdbSMilanka Ringwald sco_demo_receive_CVSD(packet, size); 5838b29cfc6SMatthias Ringwald } 584dbb41bfeSMilanka Ringwald dump_data = 0; 5858b29cfc6SMatthias Ringwald #endif 5864a96141eSMatthias Ringwald #endif 5878b29cfc6SMatthias Ringwald 588b3f76298SMilanka Ringwald if (packet[1] & 0x30){ 5891a919128SMatthias Ringwald crc_errors++; 5901a919128SMatthias Ringwald // printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4); 5911a919128SMatthias Ringwald // printf_hexdump(&packet[3], size-3); 592f7c85330SMatthias Ringwald return; 593f7c85330SMatthias Ringwald } 5948b29cfc6SMatthias Ringwald if (dump_data){ 595f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII 5961a919128SMatthias Ringwald printf("data: "); 597f7c85330SMatthias Ringwald int i; 598f7c85330SMatthias Ringwald for (i=3;i<size;i++){ 599f7c85330SMatthias Ringwald printf("%c", packet[i]); 600f7c85330SMatthias Ringwald } 601f7c85330SMatthias Ringwald printf("\n"); 6028b29cfc6SMatthias Ringwald dump_data = 0; 6031a919128SMatthias Ringwald #endif 6041a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER 6051a919128SMatthias Ringwald // colored hexdump with expected 6061a919128SMatthias Ringwald static uint8_t expected_byte = 0; 6071a919128SMatthias Ringwald int i; 6081a919128SMatthias Ringwald printf("data: "); 6091a919128SMatthias Ringwald for (i=3;i<size;i++){ 6101a919128SMatthias Ringwald if (packet[i] != expected_byte){ 6111a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 6121a919128SMatthias Ringwald } else { 6131a919128SMatthias Ringwald printf("%02x ", packet[i]); 6141a919128SMatthias Ringwald } 6151a919128SMatthias Ringwald expected_byte = packet[i]+1; 6161a919128SMatthias Ringwald } 6171a919128SMatthias Ringwald printf("\n"); 6181a919128SMatthias Ringwald #endif 6191a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE_00 6201a919128SMatthias Ringwald int i; 6211a919128SMatthias Ringwald int contains_error = 0; 6221a919128SMatthias Ringwald for (i=3;i<size;i++){ 6231a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 6241a919128SMatthias Ringwald contains_error = 1; 6251a919128SMatthias Ringwald byte_errors++; 6261a919128SMatthias Ringwald } 6271a919128SMatthias Ringwald } 6281a919128SMatthias Ringwald if (contains_error){ 6291a919128SMatthias Ringwald printf("data: "); 6301a919128SMatthias Ringwald for (i=0;i<3;i++){ 6311a919128SMatthias Ringwald printf("%02x ", packet[i]); 6321a919128SMatthias Ringwald } 6331a919128SMatthias Ringwald for (i=3;i<size;i++){ 6341a919128SMatthias Ringwald if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){ 6351a919128SMatthias Ringwald printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]); 6361a919128SMatthias Ringwald } else { 6371a919128SMatthias Ringwald printf("%02x ", packet[i]); 6381a919128SMatthias Ringwald } 6391a919128SMatthias Ringwald } 6401a919128SMatthias Ringwald printf("\n"); 6411a919128SMatthias Ringwald } 642f7c85330SMatthias Ringwald #endif 6438b29cfc6SMatthias Ringwald } 644f7c85330SMatthias Ringwald } 645