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