xref: /btstack/example/sco_demo_util.c (revision 1f8694cc3a397a7497b8bd4505d97fb09054221d)
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;
1903963d036SMatthias Ringwald     (void) userData;
191dbb41bfeSMilanka Ringwald 
192dbb41bfeSMilanka Ringwald     uint32_t bytes_read = 0;
193dbb41bfeSMilanka Ringwald     int bytes_per_buffer = framesPerBuffer;
194dbb41bfeSMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
195dbb41bfeSMilanka Ringwald         bytes_per_buffer *= MSBC_BYTES_PER_FRAME;
196dbb41bfeSMilanka Ringwald     } else {
197dbb41bfeSMilanka Ringwald         bytes_per_buffer *= CVSD_BYTES_PER_FRAME;
198dbb41bfeSMilanka Ringwald     }
199dbb41bfeSMilanka Ringwald 
200dbb41bfeSMilanka Ringwald     if (btstack_ring_buffer_bytes_available(&ring_buffer) >= bytes_per_buffer){
201dbb41bfeSMilanka Ringwald         btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_per_buffer, &bytes_read);
202dbb41bfeSMilanka Ringwald     } else {
203dbb41bfeSMilanka Ringwald         printf("NOT ENOUGH DATA!\n");
204dbb41bfeSMilanka Ringwald         memset(outputBuffer, 0, bytes_per_buffer);
205dbb41bfeSMilanka Ringwald     }
206dbb41bfeSMilanka Ringwald     // printf("bytes avail after read: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer));
207dbb41bfeSMilanka Ringwald     return 0;
208dbb41bfeSMilanka Ringwald }
209dbb41bfeSMilanka Ringwald #endif
2108b29cfc6SMatthias Ringwald 
211fcb08cdbSMilanka Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
2129ec2630cSMatthias Ringwald     UNUSED(context);
2139ec2630cSMatthias Ringwald     UNUSED(sample_rate);
2149ec2630cSMatthias Ringwald 
215dbb41bfeSMilanka Ringwald     // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels);
216dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
217dbb41bfeSMilanka Ringwald     if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= MSBC_PREBUFFER_BYTES){
218dbb41bfeSMilanka Ringwald         /* -- start stream -- */
219dbb41bfeSMilanka Ringwald         PaError err = Pa_StartStream(stream);
220dbb41bfeSMilanka Ringwald         if (err != paNoError){
221dbb41bfeSMilanka Ringwald             printf("Error starting the stream: \"%s\"\n",  Pa_GetErrorText(err));
222dbb41bfeSMilanka Ringwald             return;
223dbb41bfeSMilanka Ringwald         }
224dbb41bfeSMilanka Ringwald         pa_stream_started = 1;
225dbb41bfeSMilanka Ringwald     }
226dbb41bfeSMilanka Ringwald     btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
227dbb41bfeSMilanka Ringwald     // printf("bytes avail after write: %d\n", btstack_ring_buffer_bytes_available(&ring_buffer));
2289ec2630cSMatthias Ringwald #else
2299ec2630cSMatthias Ringwald     UNUSED(num_channels);
230dbb41bfeSMilanka Ringwald #endif
231dbb41bfeSMilanka Ringwald 
232fcb08cdbSMilanka Ringwald     if (!num_samples_to_write) return;
233fcb08cdbSMilanka Ringwald 
234fcb08cdbSMilanka Ringwald     num_samples = btstack_min(num_samples, num_samples_to_write);
235fcb08cdbSMilanka Ringwald     num_samples_to_write -= num_samples;
236fcb08cdbSMilanka Ringwald 
237fbc7c9f2SMilanka Ringwald     wav_writer_write_int16(num_samples, data);
238fcb08cdbSMilanka Ringwald 
239fcb08cdbSMilanka Ringwald     if (num_samples_to_write == 0){
240fcb08cdbSMilanka Ringwald         sco_demo_close();
241fcb08cdbSMilanka Ringwald     }
242fcb08cdbSMilanka Ringwald }
243fcb08cdbSMilanka Ringwald 
244fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){
245fbc7c9f2SMilanka Ringwald     int sample_rate = 16000;
246fbc7c9f2SMilanka Ringwald     wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate);
247fbc7c9f2SMilanka Ringwald     btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL);
248fcb08cdbSMilanka Ringwald 
249fbc7c9f2SMilanka Ringwald     num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS;
250220eb563SMilanka Ringwald 
251220eb563SMilanka Ringwald     hfp_msbc_init();
252220eb563SMilanka Ringwald     sco_demo_fill_audio_frame();
253973d7173SMatthias Ringwald 
254d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME
255d5e5f834SMatthias Ringwald     msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb");
256d5e5f834SMatthias Ringwald     printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in);
257d5e5f834SMatthias Ringwald #endif
2587294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME
259d5e5f834SMatthias Ringwald     msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb");
260d5e5f834SMatthias Ringwald     printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out);
2617294d009SMatthias Ringwald #endif
262dbb41bfeSMilanka Ringwald 
263dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
264dbb41bfeSMilanka Ringwald     PaError err;
265dbb41bfeSMilanka Ringwald     PaStreamParameters outputParameters;
266dbb41bfeSMilanka Ringwald 
267dbb41bfeSMilanka Ringwald     /* -- initialize PortAudio -- */
268dbb41bfeSMilanka Ringwald     err = Pa_Initialize();
269dbb41bfeSMilanka Ringwald     if( err != paNoError ) return;
270dbb41bfeSMilanka Ringwald     /* -- setup input and output -- */
271dbb41bfeSMilanka Ringwald     outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
272dbb41bfeSMilanka Ringwald     outputParameters.channelCount = NUM_CHANNELS;
273dbb41bfeSMilanka Ringwald     outputParameters.sampleFormat = MSBC_PA_SAMPLE_TYPE;
274dbb41bfeSMilanka Ringwald     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
275dbb41bfeSMilanka Ringwald     outputParameters.hostApiSpecificStreamInfo = NULL;
276dbb41bfeSMilanka Ringwald     /* -- setup stream -- */
277dbb41bfeSMilanka Ringwald     err = Pa_OpenStream(
278dbb41bfeSMilanka Ringwald            &stream,
279dbb41bfeSMilanka Ringwald            NULL, // &inputParameters,
280dbb41bfeSMilanka Ringwald            &outputParameters,
281dbb41bfeSMilanka Ringwald            MSBC_SAMPLE_RATE,
282dbb41bfeSMilanka Ringwald            MSBC_FRAMES_PER_BUFFER,
283dbb41bfeSMilanka Ringwald            paClipOff, /* we won't output out of range samples so don't bother clipping them */
284dbb41bfeSMilanka Ringwald            patestCallback,      /* no callback, use blocking API */
285dbb41bfeSMilanka Ringwald            NULL );    /* no callback, so no callback userData */
286dbb41bfeSMilanka Ringwald     if (err != paNoError){
287dbb41bfeSMilanka Ringwald         printf("Error initializing portaudio: \"%s\"\n",  Pa_GetErrorText(err));
288dbb41bfeSMilanka Ringwald         return;
289dbb41bfeSMilanka Ringwald     }
290dbb41bfeSMilanka Ringwald     memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage));
291dbb41bfeSMilanka Ringwald     btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage));
292dbb41bfeSMilanka Ringwald     pa_stream_started = 0;
293dbb41bfeSMilanka Ringwald #endif
294fcb08cdbSMilanka Ringwald }
295fcb08cdbSMilanka Ringwald 
296fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){
297fcb08cdbSMilanka Ringwald     if (num_samples_to_write){
298d5e5f834SMatthias Ringwald         if (msbc_file_in){
299d5e5f834SMatthias Ringwald             // log incoming mSBC data for testing
300d5e5f834SMatthias Ringwald             fwrite(packet+3, size-3, 1, msbc_file_in);
301d5e5f834SMatthias Ringwald         }
302fcb08cdbSMilanka Ringwald     }
303dbb41bfeSMilanka Ringwald     btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3);
304fcb08cdbSMilanka Ringwald }
305fcb08cdbSMilanka Ringwald 
306fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){
307fbc7c9f2SMilanka Ringwald     int sample_rate = 8000;
308fbc7c9f2SMilanka Ringwald     wav_writer_open(SCO_WAV_FILENAME, 1, sample_rate);
309fbc7c9f2SMilanka Ringwald     btstack_cvsd_plc_init(&cvsd_plc_state);
310fbc7c9f2SMilanka Ringwald     num_samples_to_write = sample_rate * SCO_WAV_DURATION_IN_SECONDS;
311dbb41bfeSMilanka Ringwald 
312dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
313dbb41bfeSMilanka Ringwald     PaError err;
314dbb41bfeSMilanka Ringwald     PaStreamParameters outputParameters;
315dbb41bfeSMilanka Ringwald 
316dbb41bfeSMilanka Ringwald     /* -- initialize PortAudio -- */
317dbb41bfeSMilanka Ringwald     err = Pa_Initialize();
318dbb41bfeSMilanka Ringwald     if( err != paNoError ) return;
319dbb41bfeSMilanka Ringwald     /* -- setup input and output -- */
320dbb41bfeSMilanka Ringwald     outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
321dbb41bfeSMilanka Ringwald     outputParameters.channelCount = NUM_CHANNELS;
322dbb41bfeSMilanka Ringwald     outputParameters.sampleFormat = CVSD_PA_SAMPLE_TYPE;
323dbb41bfeSMilanka Ringwald     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
324dbb41bfeSMilanka Ringwald     outputParameters.hostApiSpecificStreamInfo = NULL;
325dbb41bfeSMilanka Ringwald     /* -- setup stream -- */
326dbb41bfeSMilanka Ringwald     err = Pa_OpenStream(
327dbb41bfeSMilanka Ringwald            &stream,
328dbb41bfeSMilanka Ringwald            NULL, // &inputParameters,
329dbb41bfeSMilanka Ringwald            &outputParameters,
330dbb41bfeSMilanka Ringwald            CVSD_SAMPLE_RATE,
331dbb41bfeSMilanka Ringwald            CVSD_FRAMES_PER_BUFFER,
332dbb41bfeSMilanka Ringwald            paClipOff, /* we won't output out of range samples so don't bother clipping them */
333dbb41bfeSMilanka Ringwald            patestCallback,      /* no callback, use blocking API */
334dbb41bfeSMilanka Ringwald            NULL );    /* no callback, so no callback userData */
335dbb41bfeSMilanka Ringwald     if (err != paNoError){
336dbb41bfeSMilanka Ringwald         printf("Error initializing portaudio: \"%s\"\n",  Pa_GetErrorText(err));
337dbb41bfeSMilanka Ringwald         return;
338dbb41bfeSMilanka Ringwald     }
339dbb41bfeSMilanka Ringwald     memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage));
340dbb41bfeSMilanka Ringwald     btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage));
341dbb41bfeSMilanka Ringwald     pa_stream_started = 0;
342dbb41bfeSMilanka Ringwald #endif
343fbc7c9f2SMilanka Ringwald }
344fbc7c9f2SMilanka Ringwald 
345fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){
346dbb41bfeSMilanka Ringwald     if (!num_samples_to_write) return;
347*1f8694ccSMatthias Ringwald     int8_t audio_frame_out[255];    //
348*1f8694ccSMatthias Ringwald 
349*1f8694ccSMatthias Ringwald     if (size > sizeof(audio_frame_out)){
350*1f8694ccSMatthias Ringwald         printf("sco_demo_receive_CVSD: SCO packet larger than local output buffer - dropping data.\n");
351*1f8694ccSMatthias Ringwald         return;
352*1f8694ccSMatthias Ringwald     }
353dbb41bfeSMilanka Ringwald 
354fcb08cdbSMilanka Ringwald     const int num_samples = size - 3;
355fcb08cdbSMilanka Ringwald     const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
356379d044eSMilanka Ringwald 
357fbc7c9f2SMilanka Ringwald     btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out);
358379d044eSMilanka Ringwald 
359fbc7c9f2SMilanka Ringwald     wav_writer_write_int8(samples_to_write, audio_frame_out);
360fcb08cdbSMilanka Ringwald     num_samples_to_write -= samples_to_write;
361fcb08cdbSMilanka Ringwald     if (num_samples_to_write == 0){
362fcb08cdbSMilanka Ringwald         sco_demo_close();
363fcb08cdbSMilanka Ringwald     }
364dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
365dbb41bfeSMilanka Ringwald     if (!pa_stream_started && btstack_ring_buffer_bytes_available(&ring_buffer) >= CVSD_PREBUFFER_BYTES){
366dbb41bfeSMilanka Ringwald         /* -- start stream -- */
367dbb41bfeSMilanka Ringwald         PaError err = Pa_StartStream(stream);
368dbb41bfeSMilanka Ringwald         if (err != paNoError){
369dbb41bfeSMilanka Ringwald             printf("Error starting the stream: \"%s\"\n",  Pa_GetErrorText(err));
370dbb41bfeSMilanka Ringwald             return;
371fcb08cdbSMilanka Ringwald         }
372dbb41bfeSMilanka Ringwald         pa_stream_started = 1;
373dbb41bfeSMilanka Ringwald     }
374dbb41bfeSMilanka Ringwald     btstack_ring_buffer_write(&ring_buffer, (uint8_t *)audio_frame_out, samples_to_write);
375dbb41bfeSMilanka Ringwald #endif
376fcb08cdbSMilanka Ringwald }
377fcb08cdbSMilanka Ringwald 
3788b29cfc6SMatthias Ringwald #endif
3794a96141eSMatthias Ringwald #endif
3808b29cfc6SMatthias Ringwald 
381fcb08cdbSMilanka Ringwald void sco_demo_close(void){
382fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
38326463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME)
384fbc7c9f2SMilanka Ringwald     wav_writer_close();
38526463303SMilanka Ringwald     printf("SCO demo statistics: ");
38626463303SMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
38726463303SMilanka 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);
38826463303SMilanka Ringwald     } else {
38926463303SMilanka 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);
39026463303SMilanka Ringwald     }
39126463303SMilanka Ringwald #endif
39226463303SMilanka Ringwald 
393dbb41bfeSMilanka Ringwald #ifdef HAVE_PORTAUDIO
394dbb41bfeSMilanka Ringwald     if (pa_stream_started){
395dbb41bfeSMilanka Ringwald         PaError err = Pa_StopStream(stream);
396dbb41bfeSMilanka Ringwald         if (err != paNoError){
397dbb41bfeSMilanka Ringwald             printf("Error stopping the stream: \"%s\"\n",  Pa_GetErrorText(err));
398dbb41bfeSMilanka Ringwald             return;
399dbb41bfeSMilanka Ringwald         }
400dbb41bfeSMilanka Ringwald         pa_stream_started = 0;
401dbb41bfeSMilanka Ringwald         err = Pa_CloseStream(stream);
402dbb41bfeSMilanka Ringwald         if (err != paNoError){
403dbb41bfeSMilanka Ringwald             printf("Error closing the stream: \"%s\"\n",  Pa_GetErrorText(err));
404dbb41bfeSMilanka Ringwald             return;
405dbb41bfeSMilanka Ringwald         }
406dbb41bfeSMilanka Ringwald 
407dbb41bfeSMilanka Ringwald         err = Pa_Terminate();
408dbb41bfeSMilanka Ringwald         if (err != paNoError){
409dbb41bfeSMilanka Ringwald             printf("Error terminating portaudio: \"%s\"\n",  Pa_GetErrorText(err));
410dbb41bfeSMilanka Ringwald             return;
411dbb41bfeSMilanka Ringwald         }
412dbb41bfeSMilanka Ringwald     }
413dbb41bfeSMilanka Ringwald #endif
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
619a11bf416SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE == 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