xref: /btstack/example/sco_demo_util.c (revision 463c9c89cdd7599d89d8bc1ecdc22cc8db4e19c1)
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 #include <stdio.h>
432ec72fbbSMilanka Ringwald 
44f7c85330SMatthias Ringwald #include "sco_demo_util.h"
45fcb08cdbSMilanka Ringwald #include "btstack_debug.h"
4635fd3fb9SMatthias Ringwald #include "classic/btstack_sbc.h"
4735fd3fb9SMatthias Ringwald #include "classic/btstack_cvsd_plc.h"
4835fd3fb9SMatthias Ringwald #include "classic/hfp_msbc.h"
4935fd3fb9SMatthias Ringwald #include "classic/hfp.h"
50fcb08cdbSMilanka Ringwald 
5135fd3fb9SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO
52fbc7c9f2SMilanka Ringwald #include "wav_util.h"
5335fd3fb9SMatthias Ringwald #endif
54fbc7c9f2SMilanka Ringwald 
55c4e666bcSMatthias Ringwald #ifdef HAVE_PORTAUDIO
56c4e666bcSMatthias Ringwald #include <portaudio.h>
57c4e666bcSMatthias Ringwald #include "btstack_ring_buffer.h"
58c4e666bcSMatthias Ringwald #endif
59c4e666bcSMatthias Ringwald 
60c4e666bcSMatthias Ringwald 
61c4e666bcSMatthias Ringwald // test modes
62f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_SINE		 0
63f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_ASCII		 1
64f7c85330SMatthias Ringwald #define SCO_DEMO_MODE_COUNTER	 2
651a919128SMatthias Ringwald #define SCO_DEMO_MODE_55         3
661a919128SMatthias Ringwald #define SCO_DEMO_MODE_00         4
67*463c9c89SMatthias Ringwald #define SCO_DEMO_MODE_MICROPHONE 5
68f7c85330SMatthias Ringwald 
69f7c85330SMatthias Ringwald // SCO demo configuration
70fcb08cdbSMilanka Ringwald #define SCO_DEMO_MODE               SCO_DEMO_MODE_SINE
71c4e666bcSMatthias Ringwald 
72c4e666bcSMatthias Ringwald // number of sco packets until 'report' on console
73f7c85330SMatthias Ringwald #define SCO_REPORT_PERIOD           100
74f7c85330SMatthias Ringwald 
75c4e666bcSMatthias Ringwald // length and name of wav file on disc
76c4e666bcSMatthias Ringwald #define SCO_WAV_DURATION_IN_SECONDS 15
778b29cfc6SMatthias Ringwald #define SCO_WAV_FILENAME            "sco_input.wav"
78c4e666bcSMatthias Ringwald 
79c4e666bcSMatthias Ringwald // name of sbc test files
80d5e5f834SMatthias Ringwald #define SCO_MSBC_OUT_FILENAME       "sco_output.msbc"
812308e108SMilanka Ringwald #define SCO_MSBC_IN_FILENAME        "sco_input.msbc"
82220eb563SMilanka Ringwald 
83c4e666bcSMatthias Ringwald // pre-buffer for CVSD and mSBC - also defines latency
84c4e666bcSMatthias Ringwald #define SCO_CVSD_PA_PREBUFFER_MS    50
85c4e666bcSMatthias Ringwald #define SCO_MSBC_PA_PREBUFFER_MS    50
868b29cfc6SMatthias Ringwald 
87c4e666bcSMatthias Ringwald // constants
88c4e666bcSMatthias Ringwald #define NUM_CHANNELS            1
89c4e666bcSMatthias Ringwald #define CVSD_BYTES_PER_FRAME    (2*NUM_CHANNELS)
90c4e666bcSMatthias Ringwald #define CVSD_SAMPLE_RATE        8000
91c4e666bcSMatthias Ringwald #define MSBC_SAMPLE_RATE        16000
92c4e666bcSMatthias Ringwald #define MSBC_BYTES_PER_FRAME    (2*NUM_CHANNELS)
93f7c85330SMatthias Ringwald 
94*463c9c89SMatthias Ringwald #if defined(HAVE_PORTAUDIO) && (SCO_DEMO_MODE == SCO_DEMO_MODE_SINE || SCO_DEMO_MODE_MICROPHONE)
95f7c85330SMatthias Ringwald #define USE_PORTAUDIO
96c4e666bcSMatthias Ringwald #define CVSD_PA_PREBUFFER_BYTES (SCO_CVSD_PA_PREBUFFER_MS * CVSD_SAMPLE_RATE/1000 * CVSD_BYTES_PER_FRAME)
97c4e666bcSMatthias Ringwald #define MSBC_PA_PREBUFFER_BYTES (SCO_MSBC_PA_PREBUFFER_MS * MSBC_SAMPLE_RATE/1000 * MSBC_BYTES_PER_FRAME)
98f7c85330SMatthias Ringwald #endif
99f7c85330SMatthias Ringwald 
100f7c85330SMatthias Ringwald #ifdef USE_PORTAUDIO
101*463c9c89SMatthias Ringwald static PaStream *            pa_output_stream;
102*463c9c89SMatthias Ringwald static int                   pa_output_started = 0;
103*463c9c89SMatthias Ringwald static int                   pa_output_paused = 0;
104*463c9c89SMatthias Ringwald static uint8_t               pa_output_ring_buffer_storage[2*MSBC_PA_PREBUFFER_BYTES];
105*463c9c89SMatthias Ringwald static btstack_ring_buffer_t pa_output_ring_buffer;
106f7c85330SMatthias Ringwald #endif
107f7c85330SMatthias Ringwald 
108fcb08cdbSMilanka Ringwald static int dump_data = 1;
109fcb08cdbSMilanka Ringwald static int count_sent = 0;
110fcb08cdbSMilanka Ringwald static int count_received = 0;
111c4e666bcSMatthias Ringwald static int negotiated_codec = -1;
1121a919128SMatthias Ringwald static int phase = 0;
113c4e666bcSMatthias Ringwald static int num_audio_frames = 0;
114c4e666bcSMatthias Ringwald 
115c4e666bcSMatthias Ringwald static btstack_sbc_decoder_state_t decoder_state;
116c4e666bcSMatthias Ringwald static btstack_cvsd_plc_state_t cvsd_plc_state;
117c4e666bcSMatthias Ringwald static int num_samples_to_write;
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, 160 Hz at 16000 kHz
125c4e666bcSMatthias Ringwald static const int16_t sine_int16_at_16000hz[] = {
12635fd3fb9SMatthias Ringwald      0,    2057,    4107,    6140,    8149,   10126,   12062,   13952,   15786,   17557,
12735fd3fb9SMatthias Ringwald  19260,   20886,   22431,   23886,   25247,   26509,   27666,   28714,   29648,   30466,
12835fd3fb9SMatthias Ringwald  31163,   31738,   32187,   32509,   32702,   32767,   32702,   32509,   32187,   31738,
12935fd3fb9SMatthias Ringwald  31163,   30466,   29648,   28714,   27666,   26509,   25247,   23886,   22431,   20886,
13035fd3fb9SMatthias Ringwald  19260,   17557,   15786,   13952,   12062,   10126,    8149,    6140,    4107,    2057,
13135fd3fb9SMatthias Ringwald      0,   -2057,   -4107,   -6140,   -8149,  -10126,  -12062,  -13952,  -15786,  -17557,
13235fd3fb9SMatthias Ringwald -19260,  -20886,  -22431,  -23886,  -25247,  -26509,  -27666,  -28714,  -29648,  -30466,
13335fd3fb9SMatthias Ringwald -31163,  -31738,  -32187,  -32509,  -32702,  -32767,  -32702,  -32509,  -32187,  -31738,
13435fd3fb9SMatthias Ringwald -31163,  -30466,  -29648,  -28714,  -27666,  -26509,  -25247,  -23886,  -22431,  -20886,
13535fd3fb9SMatthias Ringwald -19260,  -17557,  -15786,  -13952,  -12062,  -10126,   -8149,   -6140,   -4107,   -2057,
13635fd3fb9SMatthias Ringwald };
13735fd3fb9SMatthias Ringwald 
138c4e666bcSMatthias Ringwald // ony use every second value from 16khz table
139c4e666bcSMatthias Ringwald static void sco_demo_sine_wave_int16_at_8000_hz(int num_samples, int16_t * data){
14035fd3fb9SMatthias Ringwald     int i;
14135fd3fb9SMatthias Ringwald     for (i=0; i < num_samples; i++){
142c4e666bcSMatthias Ringwald         data[i] = sine_int16_at_16000hz[phase++];
14335fd3fb9SMatthias Ringwald         phase++;
144c4e666bcSMatthias Ringwald         if (phase >= (sizeof(sine_int16_at_16000hz) / sizeof(int16_t))){
14535fd3fb9SMatthias Ringwald             phase = 0;
14635fd3fb9SMatthias Ringwald         }
14735fd3fb9SMatthias Ringwald     }
14835fd3fb9SMatthias Ringwald }
14935fd3fb9SMatthias Ringwald 
15035fd3fb9SMatthias Ringwald static void sco_demo_fill_audio_frame(void){
15135fd3fb9SMatthias Ringwald     if (!hfp_msbc_can_encode_audio_frame_now()) return;
15235fd3fb9SMatthias Ringwald     int num_samples = hfp_msbc_num_audio_samples_per_frame();
15335fd3fb9SMatthias Ringwald     int16_t sample_buffer[num_samples];
154c4e666bcSMatthias Ringwald     sco_demo_sine_wave_int16_at_8000_hz(num_samples, sample_buffer);
15535fd3fb9SMatthias Ringwald     hfp_msbc_encode_audio_frame(sample_buffer);
15635fd3fb9SMatthias Ringwald     num_audio_frames++;
15735fd3fb9SMatthias Ringwald }
158dbb41bfeSMilanka Ringwald 
159c4e666bcSMatthias Ringwald #ifdef SCO_WAV_FILENAME
160dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
161c4e666bcSMatthias Ringwald static int portaudio_callback( const void *inputBuffer, void *outputBuffer,
162dbb41bfeSMilanka Ringwald                            unsigned long framesPerBuffer,
163dbb41bfeSMilanka Ringwald                            const PaStreamCallbackTimeInfo* timeInfo,
164dbb41bfeSMilanka Ringwald                            PaStreamCallbackFlags statusFlags,
165dbb41bfeSMilanka Ringwald                            void *userData ) {
166dbb41bfeSMilanka Ringwald     (void) timeInfo; /* Prevent unused variable warnings. */
167dbb41bfeSMilanka Ringwald     (void) statusFlags;
168dbb41bfeSMilanka Ringwald     (void) inputBuffer;
1693963d036SMatthias Ringwald     (void) userData;
170dbb41bfeSMilanka Ringwald 
171c4e666bcSMatthias Ringwald     // config based on codec
172c4e666bcSMatthias Ringwald     int bytes_to_copy;
173c4e666bcSMatthias Ringwald     int prebuffer_bytes;
174c4e666bcSMatthias Ringwald     switch (negotiated_codec){
175c4e666bcSMatthias Ringwald         case HFP_CODEC_MSBC:
176c4e666bcSMatthias Ringwald             bytes_to_copy   = framesPerBuffer * MSBC_BYTES_PER_FRAME;
177c4e666bcSMatthias Ringwald             prebuffer_bytes = MSBC_PA_PREBUFFER_BYTES;
178c4e666bcSMatthias Ringwald             break;
179c4e666bcSMatthias Ringwald         case HFP_CODEC_CVSD:
180c4e666bcSMatthias Ringwald             bytes_to_copy   = framesPerBuffer * CVSD_BYTES_PER_FRAME;
181c4e666bcSMatthias Ringwald             prebuffer_bytes = CVSD_PA_PREBUFFER_BYTES;
182c4e666bcSMatthias Ringwald             break;
183c4e666bcSMatthias Ringwald         default:
184c4e666bcSMatthias Ringwald             bytes_to_copy   = framesPerBuffer * 2;  // assume 1 channel / 16 bit audio samples
185c4e666bcSMatthias Ringwald             prebuffer_bytes = 0xfffffff;
186c4e666bcSMatthias Ringwald             break;
187dbb41bfeSMilanka Ringwald     }
188dbb41bfeSMilanka Ringwald 
189c4e666bcSMatthias Ringwald     // fill with silence while paused
190*463c9c89SMatthias Ringwald     if (pa_output_paused){
191*463c9c89SMatthias Ringwald         if (btstack_ring_buffer_bytes_available(&pa_output_ring_buffer) < prebuffer_bytes){
192c4e666bcSMatthias Ringwald             memset(outputBuffer, 0, bytes_to_copy);
193c4e666bcSMatthias Ringwald             return 0;
194dbb41bfeSMilanka Ringwald         } else {
195c4e666bcSMatthias Ringwald             // resume playback
196*463c9c89SMatthias Ringwald             pa_output_paused = 0;
197dbb41bfeSMilanka Ringwald         }
198c4e666bcSMatthias Ringwald     }
199c4e666bcSMatthias Ringwald 
200c4e666bcSMatthias Ringwald     // get data from ringbuffer
201c4e666bcSMatthias Ringwald     uint32_t bytes_read = 0;
202*463c9c89SMatthias Ringwald     btstack_ring_buffer_read(&pa_output_ring_buffer, outputBuffer, bytes_to_copy, &bytes_read);
203c4e666bcSMatthias Ringwald     bytes_to_copy -= bytes_read;
204c4e666bcSMatthias Ringwald 
205c4e666bcSMatthias Ringwald     // fill with 0 if not enough
206c4e666bcSMatthias Ringwald     if (bytes_to_copy){
207c4e666bcSMatthias Ringwald         memset(outputBuffer + bytes_read, 0, bytes_to_copy);
208*463c9c89SMatthias Ringwald         pa_output_paused = 1;
209c4e666bcSMatthias Ringwald     }
210dbb41bfeSMilanka Ringwald     return 0;
211dbb41bfeSMilanka Ringwald }
2128b29cfc6SMatthias Ringwald 
213c4e666bcSMatthias Ringwald static void portaudio_start(void){
214*463c9c89SMatthias Ringwald     if (!pa_output_started){
215dbb41bfeSMilanka Ringwald         /* -- start stream -- */
216*463c9c89SMatthias Ringwald         PaError err = Pa_StartStream(pa_output_stream);
217dbb41bfeSMilanka Ringwald         if (err != paNoError){
218dbb41bfeSMilanka Ringwald             printf("Error starting the stream: \"%s\"\n",  Pa_GetErrorText(err));
219dbb41bfeSMilanka Ringwald             return;
220dbb41bfeSMilanka Ringwald         }
221*463c9c89SMatthias Ringwald         pa_output_started = 1;
222*463c9c89SMatthias Ringwald         pa_output_paused  = 1;
223dbb41bfeSMilanka Ringwald     }
224c4e666bcSMatthias Ringwald }
225c4e666bcSMatthias Ringwald 
226c4e666bcSMatthias Ringwald // return 1 if ok
227c4e666bcSMatthias Ringwald static int portaudio_initialize(int sample_rate){
228c4e666bcSMatthias Ringwald     PaError err;
229c4e666bcSMatthias Ringwald     PaStreamParameters outputParameters;
230c4e666bcSMatthias Ringwald 
231c4e666bcSMatthias Ringwald     /* -- initialize PortAudio -- */
232c4e666bcSMatthias Ringwald     printf("PortAudio: Initialize\n");
233c4e666bcSMatthias Ringwald     err = Pa_Initialize();
234c4e666bcSMatthias Ringwald     if( err != paNoError ) return 0;
235c4e666bcSMatthias Ringwald     /* -- setup input and output -- */
236c4e666bcSMatthias Ringwald     outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
237c4e666bcSMatthias Ringwald     outputParameters.channelCount = NUM_CHANNELS;
238c4e666bcSMatthias Ringwald     outputParameters.sampleFormat = paInt16;
239c4e666bcSMatthias Ringwald     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
240c4e666bcSMatthias Ringwald     outputParameters.hostApiSpecificStreamInfo = NULL;
241c4e666bcSMatthias Ringwald     /* -- setup stream -- */
242c4e666bcSMatthias Ringwald     printf("PortAudio: Open stream\n");
243c4e666bcSMatthias Ringwald     err = Pa_OpenStream(
244c4e666bcSMatthias Ringwald            &stream,
245c4e666bcSMatthias Ringwald            NULL, // &inputParameters,
246c4e666bcSMatthias Ringwald            &outputParameters,
247c4e666bcSMatthias Ringwald            sample_rate,
248c4e666bcSMatthias Ringwald            0,
249c4e666bcSMatthias Ringwald            paClipOff, /* we won't output out of range samples so don't bother clipping them */
250c4e666bcSMatthias Ringwald            portaudio_callback,
251c4e666bcSMatthias Ringwald            NULL );
252c4e666bcSMatthias Ringwald     if (err != paNoError){
253c4e666bcSMatthias Ringwald         printf("Error opening portaudio stream: \"%s\"\n",  Pa_GetErrorText(err));
254c4e666bcSMatthias Ringwald         return 0;
255c4e666bcSMatthias Ringwald     }
256*463c9c89SMatthias Ringwald     memset(pa_output_ring_buffer_storage, 0, sizeof(pa_output_ring_buffer_storage));
257*463c9c89SMatthias Ringwald     btstack_ring_buffer_init(&pa_output_ring_buffer, pa_output_ring_buffer_storage, sizeof(pa_output_ring_buffer_storage));
258*463c9c89SMatthias Ringwald     pa_output_started = 0;
259c4e666bcSMatthias Ringwald     return 1;
260c4e666bcSMatthias Ringwald }
261c4e666bcSMatthias Ringwald #endif
262c4e666bcSMatthias Ringwald 
263c4e666bcSMatthias Ringwald 
264c4e666bcSMatthias Ringwald static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
265c4e666bcSMatthias Ringwald     UNUSED(context);
266c4e666bcSMatthias Ringwald     UNUSED(sample_rate);
267c4e666bcSMatthias Ringwald 
268c4e666bcSMatthias Ringwald     // printf("handle_pcm_data num samples %u, sample rate %d\n", num_samples, num_channels);
269c4e666bcSMatthias Ringwald #ifdef HAVE_PORTAUDIO
270c4e666bcSMatthias Ringwald     portaudio_start();
271*463c9c89SMatthias Ringwald     btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
2729ec2630cSMatthias Ringwald #else
2739ec2630cSMatthias Ringwald     UNUSED(num_channels);
274dbb41bfeSMilanka Ringwald #endif
275dbb41bfeSMilanka Ringwald 
276fcb08cdbSMilanka Ringwald     if (!num_samples_to_write) return;
277fcb08cdbSMilanka Ringwald 
278fcb08cdbSMilanka Ringwald     num_samples = btstack_min(num_samples, num_samples_to_write);
279fcb08cdbSMilanka Ringwald     num_samples_to_write -= num_samples;
280fcb08cdbSMilanka Ringwald 
281fbc7c9f2SMilanka Ringwald     wav_writer_write_int16(num_samples, data);
282fcb08cdbSMilanka Ringwald 
283fcb08cdbSMilanka Ringwald     if (num_samples_to_write == 0){
284fcb08cdbSMilanka Ringwald         sco_demo_close();
285fcb08cdbSMilanka Ringwald     }
286fcb08cdbSMilanka Ringwald }
287fcb08cdbSMilanka Ringwald 
288fcb08cdbSMilanka Ringwald static void sco_demo_init_mSBC(void){
289c4e666bcSMatthias Ringwald     printf("SCO Demo: Init mSBC\n");
290c4e666bcSMatthias Ringwald 
291c4e666bcSMatthias Ringwald     wav_writer_open(SCO_WAV_FILENAME, 1, MSBC_SAMPLE_RATE);
292fbc7c9f2SMilanka Ringwald     btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL);
293fcb08cdbSMilanka Ringwald 
294c4e666bcSMatthias Ringwald     num_samples_to_write = MSBC_SAMPLE_RATE * SCO_WAV_DURATION_IN_SECONDS;
295220eb563SMilanka Ringwald 
296220eb563SMilanka Ringwald     hfp_msbc_init();
297220eb563SMilanka Ringwald     sco_demo_fill_audio_frame();
298973d7173SMatthias Ringwald 
299d5e5f834SMatthias Ringwald #ifdef SCO_MSBC_IN_FILENAME
300d5e5f834SMatthias Ringwald     msbc_file_in = fopen(SCO_MSBC_IN_FILENAME, "wb");
301d5e5f834SMatthias Ringwald     printf("SCO Demo: creating mSBC in file %s, %p\n", SCO_MSBC_IN_FILENAME, msbc_file_in);
302d5e5f834SMatthias Ringwald #endif
3037294d009SMatthias Ringwald #ifdef SCO_MSBC_OUT_FILENAME
304d5e5f834SMatthias Ringwald     msbc_file_out = fopen(SCO_MSBC_OUT_FILENAME, "wb");
305d5e5f834SMatthias Ringwald     printf("SCO Demo: creating mSBC out file %s, %p\n", SCO_MSBC_OUT_FILENAME, msbc_file_out);
3067294d009SMatthias Ringwald #endif
307dbb41bfeSMilanka Ringwald 
308dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
309c4e666bcSMatthias Ringwald     portaudio_initialize(MSBC_SAMPLE_RATE);
310dbb41bfeSMilanka Ringwald #endif
311fcb08cdbSMilanka Ringwald }
312fcb08cdbSMilanka Ringwald 
313fcb08cdbSMilanka Ringwald static void sco_demo_receive_mSBC(uint8_t * packet, uint16_t size){
314fcb08cdbSMilanka Ringwald     if (num_samples_to_write){
315d5e5f834SMatthias Ringwald         if (msbc_file_in){
316d5e5f834SMatthias Ringwald             // log incoming mSBC data for testing
317d5e5f834SMatthias Ringwald             fwrite(packet+3, size-3, 1, msbc_file_in);
318d5e5f834SMatthias Ringwald         }
319fcb08cdbSMilanka Ringwald     }
320dbb41bfeSMilanka Ringwald     btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3);
321fcb08cdbSMilanka Ringwald }
322fcb08cdbSMilanka Ringwald 
323fbc7c9f2SMilanka Ringwald static void sco_demo_init_CVSD(void){
324c4e666bcSMatthias Ringwald     printf("SCO Demo: Init CVSD\n");
325c4e666bcSMatthias Ringwald 
326c4e666bcSMatthias Ringwald     wav_writer_open(SCO_WAV_FILENAME, 1, CVSD_SAMPLE_RATE);
327fbc7c9f2SMilanka Ringwald     btstack_cvsd_plc_init(&cvsd_plc_state);
328c4e666bcSMatthias Ringwald 
329c4e666bcSMatthias Ringwald     num_samples_to_write = CVSD_SAMPLE_RATE * SCO_WAV_DURATION_IN_SECONDS;
330dbb41bfeSMilanka Ringwald 
331dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
332c4e666bcSMatthias Ringwald     portaudio_initialize(CVSD_SAMPLE_RATE);
333dbb41bfeSMilanka Ringwald #endif
334fbc7c9f2SMilanka Ringwald }
335fbc7c9f2SMilanka Ringwald 
336fcb08cdbSMilanka Ringwald static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){
337dbb41bfeSMilanka Ringwald     if (!num_samples_to_write) return;
338c4e666bcSMatthias Ringwald     int16_t audio_frame_out[255];    //
3391f8694ccSMatthias Ringwald 
3401f8694ccSMatthias Ringwald     if (size > sizeof(audio_frame_out)){
3411f8694ccSMatthias Ringwald         printf("sco_demo_receive_CVSD: SCO packet larger than local output buffer - dropping data.\n");
3421f8694ccSMatthias Ringwald         return;
3431f8694ccSMatthias Ringwald     }
344c4e666bcSMatthias Ringwald     const int audio_bytes_read = size - 3;
345c4e666bcSMatthias Ringwald     const int num_samples = audio_bytes_read / CVSD_BYTES_PER_FRAME;
346fcb08cdbSMilanka Ringwald     const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
347379d044eSMilanka Ringwald 
348c4e666bcSMatthias Ringwald #if 0
349fbc7c9f2SMilanka Ringwald     btstack_cvsd_plc_process_data(&cvsd_plc_state, (int8_t *)(packet+3), num_samples, audio_frame_out);
350c4e666bcSMatthias Ringwald #else
351c4e666bcSMatthias Ringwald     memcpy(audio_frame_out, packet+3, audio_bytes_read);
352c4e666bcSMatthias Ringwald #endif
353379d044eSMilanka Ringwald 
354c4e666bcSMatthias Ringwald     wav_writer_write_int16(samples_to_write, audio_frame_out);
355fcb08cdbSMilanka Ringwald     num_samples_to_write -= samples_to_write;
356fcb08cdbSMilanka Ringwald     if (num_samples_to_write == 0){
357fcb08cdbSMilanka Ringwald         sco_demo_close();
358fcb08cdbSMilanka Ringwald     }
359dbb41bfeSMilanka Ringwald #ifdef USE_PORTAUDIO
360c4e666bcSMatthias Ringwald     portaudio_start();
361*463c9c89SMatthias Ringwald     btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
362dbb41bfeSMilanka Ringwald #endif
363fcb08cdbSMilanka Ringwald }
364fcb08cdbSMilanka Ringwald 
3658b29cfc6SMatthias Ringwald #endif
3664a96141eSMatthias Ringwald #endif
3678b29cfc6SMatthias Ringwald 
368fcb08cdbSMilanka Ringwald void sco_demo_close(void){
369c4e666bcSMatthias Ringwald     printf("SCO demo close\n");
370fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
37126463303SMilanka Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME)
372fbc7c9f2SMilanka Ringwald     wav_writer_close();
37326463303SMilanka Ringwald     printf("SCO demo statistics: ");
37426463303SMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
37526463303SMilanka 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);
37626463303SMilanka Ringwald     } else {
37726463303SMilanka 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);
37826463303SMilanka Ringwald     }
37926463303SMilanka Ringwald #endif
38026463303SMilanka Ringwald 
381dbb41bfeSMilanka Ringwald #ifdef HAVE_PORTAUDIO
382*463c9c89SMatthias Ringwald     if (pa_output_started){
383c4e666bcSMatthias Ringwald         printf("PortAudio: Stop Stream\n");
384*463c9c89SMatthias Ringwald         PaError err = Pa_StopStream(pa_output_stream);
385dbb41bfeSMilanka Ringwald         if (err != paNoError){
386dbb41bfeSMilanka Ringwald             printf("Error stopping the stream: \"%s\"\n",  Pa_GetErrorText(err));
387dbb41bfeSMilanka Ringwald             return;
388dbb41bfeSMilanka Ringwald         }
389*463c9c89SMatthias Ringwald         pa_output_started = 0;
390c4e666bcSMatthias Ringwald         printf("PortAudio: Close Stream\n");
391*463c9c89SMatthias Ringwald         err = Pa_CloseStream(pa_output_stream);
392dbb41bfeSMilanka Ringwald         if (err != paNoError){
393dbb41bfeSMilanka Ringwald             printf("Error closing the stream: \"%s\"\n",  Pa_GetErrorText(err));
394dbb41bfeSMilanka Ringwald             return;
395dbb41bfeSMilanka Ringwald         }
396dbb41bfeSMilanka Ringwald 
397c4e666bcSMatthias Ringwald         printf("PortAudio: Terminate\n");
398dbb41bfeSMilanka Ringwald         err = Pa_Terminate();
399dbb41bfeSMilanka Ringwald         if (err != paNoError){
400dbb41bfeSMilanka Ringwald             printf("Error terminating portaudio: \"%s\"\n",  Pa_GetErrorText(err));
401dbb41bfeSMilanka Ringwald             return;
402dbb41bfeSMilanka Ringwald         }
403dbb41bfeSMilanka Ringwald     }
404dbb41bfeSMilanka Ringwald #endif
405fcb08cdbSMilanka Ringwald 
406c4e666bcSMatthias Ringwald #ifdef SCO_WAV_FILENAME
407613518d1SMilanka Ringwald #if 0
408fcb08cdbSMilanka Ringwald     printf("SCO Demo: closing wav file\n");
409220eb563SMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
4106e046a36SMatthias Ringwald         wav_writer_state_t * writer_state = &wav_writer_state;
411fcb08cdbSMilanka Ringwald         if (!writer_state->wav_file) return;
412fcb08cdbSMilanka Ringwald         rewind(writer_state->wav_file);
4132afeea7fSMilanka 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);
414fcb08cdbSMilanka Ringwald         fclose(writer_state->wav_file);
415fcb08cdbSMilanka Ringwald         writer_state->wav_file = NULL;
416fcb08cdbSMilanka Ringwald     }
417613518d1SMilanka Ringwald #endif
418fcb08cdbSMilanka Ringwald #endif
419c4e666bcSMatthias Ringwald 
420c4e666bcSMatthias Ringwald     negotiated_codec = -1;
421c4e666bcSMatthias Ringwald 
422fcb08cdbSMilanka Ringwald #endif
423fcb08cdbSMilanka Ringwald }
424fcb08cdbSMilanka Ringwald 
425fcb08cdbSMilanka Ringwald void sco_demo_set_codec(uint8_t codec){
426fcb08cdbSMilanka Ringwald     if (negotiated_codec == codec) return;
427fcb08cdbSMilanka Ringwald     negotiated_codec = codec;
428fcb08cdbSMilanka Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
42917cd946eSMatthias Ringwald #if defined(SCO_WAV_FILENAME) || defined(SCO_SBC_FILENAME)
430220eb563SMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
431fcb08cdbSMilanka Ringwald         sco_demo_init_mSBC();
432fcb08cdbSMilanka Ringwald     } else {
433fcb08cdbSMilanka Ringwald         sco_demo_init_CVSD();
434fcb08cdbSMilanka Ringwald     }
435fcb08cdbSMilanka Ringwald #endif
436fcb08cdbSMilanka Ringwald #endif
437fcb08cdbSMilanka Ringwald }
438fcb08cdbSMilanka Ringwald 
439f7c85330SMatthias Ringwald void sco_demo_init(void){
440f7c85330SMatthias Ringwald 
441f7c85330SMatthias Ringwald 	// status
442f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
443f7c85330SMatthias Ringwald #ifdef HAVE_PORTAUDIO
444f7c85330SMatthias Ringwald 	printf("SCO Demo: Sending sine wave, audio output via portaudio.\n");
445f7c85330SMatthias Ringwald #else
446f7c85330SMatthias Ringwald 	printf("SCO Demo: Sending sine wave, hexdump received data.\n");
447f7c85330SMatthias Ringwald #endif
448f7c85330SMatthias Ringwald #endif
449f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
450f7c85330SMatthias Ringwald 	printf("SCO Demo: Sending ASCII blocks, print received data.\n");
451f7c85330SMatthias Ringwald #endif
452f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
453f7c85330SMatthias Ringwald 	printf("SCO Demo: Sending counter value, hexdump received data.\n");
454f7c85330SMatthias Ringwald #endif
455f7c85330SMatthias Ringwald 
456c4e666bcSMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
457c4e666bcSMatthias Ringwald     hci_set_sco_voice_setting(0x60);    // linear, unsigned, 16-bit, CVSD
458c4e666bcSMatthias Ringwald #else
459f7c85330SMatthias Ringwald     hci_set_sco_voice_setting(0x03);    // linear, unsigned, 8-bit, transparent
4607294d009SMatthias Ringwald #endif
461f7c85330SMatthias Ringwald 
462f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
463f7c85330SMatthias Ringwald     phase = 'a';
464f7c85330SMatthias Ringwald #endif
465f7c85330SMatthias Ringwald }
466f7c85330SMatthias Ringwald 
4671a919128SMatthias Ringwald void sco_report(void);
4681a919128SMatthias Ringwald void sco_report(void){
4694a96141eSMatthias Ringwald     printf("SCO: sent %u, received %u\n", count_sent, count_received);
4704a96141eSMatthias Ringwald }
471f7c85330SMatthias Ringwald 
472f7c85330SMatthias Ringwald void sco_demo_send(hci_con_handle_t sco_handle){
473f7c85330SMatthias Ringwald 
474f7c85330SMatthias Ringwald     if (!sco_handle) return;
475f7c85330SMatthias Ringwald 
476c4e666bcSMatthias Ringwald     int sco_packet_length = hci_get_sco_packet_length();
477c4e666bcSMatthias Ringwald     int sco_payload_length = sco_packet_length - 3;
478f7c85330SMatthias Ringwald 
479f7c85330SMatthias Ringwald     hci_reserve_packet_buffer();
480f7c85330SMatthias Ringwald     uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
481f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
482220eb563SMilanka Ringwald     if (negotiated_codec == HFP_CODEC_MSBC){
483220eb563SMilanka Ringwald 
484c4e666bcSMatthias Ringwald         // overwrite
485c4e666bcSMatthias Ringwald         sco_payload_length = 24;
486c4e666bcSMatthias Ringwald         sco_packet_length = sco_payload_length + 3;
487c4e666bcSMatthias Ringwald 
488220eb563SMilanka Ringwald         if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){
489220eb563SMilanka Ringwald             log_error("mSBC stream is empty.");
490220eb563SMilanka Ringwald         }
491220eb563SMilanka Ringwald         hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length);
492d5e5f834SMatthias Ringwald         if (msbc_file_out){
493d76591efSMatthias Ringwald             // log outgoing mSBC data for testing
494d5e5f834SMatthias Ringwald             fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out);
495d76591efSMatthias Ringwald         }
4967294d009SMatthias Ringwald 
497220eb563SMilanka Ringwald         sco_demo_fill_audio_frame();
498220eb563SMilanka Ringwald     } else {
499c4e666bcSMatthias Ringwald         const int audio_samples_per_packet = sco_payload_length / CVSD_BYTES_PER_FRAME;
500c4e666bcSMatthias Ringwald         sco_demo_sine_wave_int16_at_8000_hz(audio_samples_per_packet, (int16_t *) (sco_packet+3));
501220eb563SMilanka Ringwald     }
5021a919128SMatthias Ringwald #endif
503f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
504c4e666bcSMatthias Ringwald     memset(&sco_packet[3], phase++, sco_payload_length);
505f7c85330SMatthias Ringwald     if (phase > 'z') phase = 'a';
5061a919128SMatthias Ringwald #endif
5071a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
50838b2eaafSMatthias Ringwald     int j;
509c4e666bcSMatthias Ringwald     for (j=0;j<sco_payload_length;j++){
51038b2eaafSMatthias Ringwald         sco_packet[3+j] = phase++;
511f7c85330SMatthias Ringwald     }
512f7c85330SMatthias Ringwald #endif
5131a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55
5141a919128SMatthias Ringwald     int j;
515c4e666bcSMatthias Ringwald     for (j=0;j<sco_payload_length;j++){
5161a919128SMatthias Ringwald         // sco_packet[3+j] = j & 1 ? 0x35 : 0x53;
5171a919128SMatthias Ringwald         sco_packet[3+j] = 0x55;
5181a919128SMatthias Ringwald     }
5191a919128SMatthias Ringwald #endif
5201a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_00
5211a919128SMatthias Ringwald     int j;
522c4e666bcSMatthias Ringwald     for (j=0;j<sco_payload_length;j++){
5231a919128SMatthias Ringwald         sco_packet[3+j] = 0x00;
5241a919128SMatthias Ringwald     }
5251a919128SMatthias Ringwald     // additional hack
5261a919128SMatthias Ringwald     // big_endian_store_16(sco_packet, 5, phase++);
5271a919128SMatthias Ringwald     (void) phase;
528f7c85330SMatthias Ringwald #endif
529220eb563SMilanka Ringwald 
530c4e666bcSMatthias Ringwald     // set handle + flags
531c4e666bcSMatthias Ringwald     little_endian_store_16(sco_packet, 0, sco_handle);
532c4e666bcSMatthias Ringwald     // set len
533c4e666bcSMatthias Ringwald     sco_packet[2] = sco_payload_length;
534c4e666bcSMatthias Ringwald     // finally send packet
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
579c4e666bcSMatthias Ringwald     switch (negotiated_codec){
580c4e666bcSMatthias Ringwald         case HFP_CODEC_MSBC:
581fcb08cdbSMilanka Ringwald         sco_demo_receive_mSBC(packet, size);
582c4e666bcSMatthias Ringwald             break;
583c4e666bcSMatthias Ringwald         case HFP_CODEC_CVSD:
584fcb08cdbSMilanka Ringwald         sco_demo_receive_CVSD(packet, size);
585c4e666bcSMatthias Ringwald             break;
586c4e666bcSMatthias Ringwald         default:
587c4e666bcSMatthias Ringwald             break;
5888b29cfc6SMatthias Ringwald     }
589dbb41bfeSMilanka Ringwald     dump_data = 0;
5908b29cfc6SMatthias Ringwald #endif
5914a96141eSMatthias Ringwald #endif
5928b29cfc6SMatthias Ringwald 
593b3f76298SMilanka Ringwald     if (packet[1] & 0x30){
5941a919128SMatthias Ringwald         crc_errors++;
5951a919128SMatthias Ringwald         // printf("SCO CRC Error: %x - data: ", (packet[1] & 0x30) >> 4);
5961a919128SMatthias Ringwald         // printf_hexdump(&packet[3], size-3);
597f7c85330SMatthias Ringwald         return;
598f7c85330SMatthias Ringwald     }
5998b29cfc6SMatthias Ringwald     if (dump_data){
600f7c85330SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
6011a919128SMatthias Ringwald         printf("data: ");
602f7c85330SMatthias Ringwald         int i;
603f7c85330SMatthias Ringwald         for (i=3;i<size;i++){
604f7c85330SMatthias Ringwald             printf("%c", packet[i]);
605f7c85330SMatthias Ringwald         }
606f7c85330SMatthias Ringwald         printf("\n");
6078b29cfc6SMatthias Ringwald         dump_data = 0;
6081a919128SMatthias Ringwald #endif
6091a919128SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
6101a919128SMatthias Ringwald         // colored hexdump with expected
6111a919128SMatthias Ringwald         static uint8_t expected_byte = 0;
6121a919128SMatthias Ringwald         int i;
6131a919128SMatthias Ringwald         printf("data: ");
6141a919128SMatthias Ringwald         for (i=3;i<size;i++){
6151a919128SMatthias Ringwald             if (packet[i] != expected_byte){
6161a919128SMatthias Ringwald                 printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]);
6171a919128SMatthias Ringwald             } else {
6181a919128SMatthias Ringwald                 printf("%02x ", packet[i]);
6191a919128SMatthias Ringwald             }
6201a919128SMatthias Ringwald             expected_byte = packet[i]+1;
6211a919128SMatthias Ringwald         }
6221a919128SMatthias Ringwald         printf("\n");
6231a919128SMatthias Ringwald #endif
624a11bf416SMatthias Ringwald #if SCO_DEMO_MODE == SCO_DEMO_MODE_55 || SCO_DEMO_MODE == SCO_DEMO_MODE_00
6251a919128SMatthias Ringwald         int i;
6261a919128SMatthias Ringwald         int contains_error = 0;
6271a919128SMatthias Ringwald         for (i=3;i<size;i++){
6281a919128SMatthias Ringwald             if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){
6291a919128SMatthias Ringwald                 contains_error = 1;
6301a919128SMatthias Ringwald                 byte_errors++;
6311a919128SMatthias Ringwald             }
6321a919128SMatthias Ringwald         }
6331a919128SMatthias Ringwald         if (contains_error){
6341a919128SMatthias Ringwald             printf("data: ");
6351a919128SMatthias Ringwald             for (i=0;i<3;i++){
6361a919128SMatthias Ringwald                 printf("%02x ", packet[i]);
6371a919128SMatthias Ringwald             }
6381a919128SMatthias Ringwald             for (i=3;i<size;i++){
6391a919128SMatthias Ringwald                 if (packet[i] != 0x00 && packet[i] != 0x35 && packet[i] != 0x53 && packet[i] != 0x55){
6401a919128SMatthias Ringwald                     printf(ANSI_COLOR_RED "%02x " ANSI_COLOR_RESET, packet[i]);
6411a919128SMatthias Ringwald                 } else {
6421a919128SMatthias Ringwald                     printf("%02x ", packet[i]);
6431a919128SMatthias Ringwald                 }
6441a919128SMatthias Ringwald             }
6451a919128SMatthias Ringwald             printf("\n");
6461a919128SMatthias Ringwald         }
647f7c85330SMatthias Ringwald #endif
6488b29cfc6SMatthias Ringwald     }
649f7c85330SMatthias Ringwald }
650