xref: /btstack/example/sco_demo_util.c (revision 9ec2630ce4bfd36adcb438d2e8ba6fc26890f857)
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