xref: /btstack/platform/embedded/btstack_audio_embedded.c (revision dfa327468763b688f1a3435ddaf983956fd7a7cd)
1*dfa32746SMatthias Ringwald /*
2*dfa32746SMatthias Ringwald  * Copyright (C) 2018 BlueKitchen GmbH
3*dfa32746SMatthias Ringwald  *
4*dfa32746SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*dfa32746SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*dfa32746SMatthias Ringwald  * are met:
7*dfa32746SMatthias Ringwald  *
8*dfa32746SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*dfa32746SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*dfa32746SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*dfa32746SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*dfa32746SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*dfa32746SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*dfa32746SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*dfa32746SMatthias Ringwald  *    from this software without specific prior written permission.
16*dfa32746SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*dfa32746SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*dfa32746SMatthias Ringwald  *    monetary gain.
19*dfa32746SMatthias Ringwald  *
20*dfa32746SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*dfa32746SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*dfa32746SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*dfa32746SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*dfa32746SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*dfa32746SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*dfa32746SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*dfa32746SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*dfa32746SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*dfa32746SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*dfa32746SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*dfa32746SMatthias Ringwald  * SUCH DAMAGE.
32*dfa32746SMatthias Ringwald  *
33*dfa32746SMatthias Ringwald  * Please inquire about commercial licensing options at
34*dfa32746SMatthias Ringwald  * [email protected]
35*dfa32746SMatthias Ringwald  *
36*dfa32746SMatthias Ringwald  */
37*dfa32746SMatthias Ringwald 
38*dfa32746SMatthias Ringwald #define __BTSTACK_FILE__ "btstack_audio_embedded.c"
39*dfa32746SMatthias Ringwald 
40*dfa32746SMatthias Ringwald /*
41*dfa32746SMatthias Ringwald  *  btstack_audio_embedded.c
42*dfa32746SMatthias Ringwald  *
43*dfa32746SMatthias Ringwald  *  Implementation of btstack_audio.h using hal_audio.h for embedded run loop
44*dfa32746SMatthias Ringwald  *
45*dfa32746SMatthias Ringwald  */
46*dfa32746SMatthias Ringwald 
47*dfa32746SMatthias Ringwald #include "btstack_config.h"
48*dfa32746SMatthias Ringwald #include "btstack_debug.h"
49*dfa32746SMatthias Ringwald #include "btstack_audio.h"
50*dfa32746SMatthias Ringwald #include "btstack_run_loop_embedded.h"
51*dfa32746SMatthias Ringwald #include "hal_audio.h"
52*dfa32746SMatthias Ringwald 
53*dfa32746SMatthias Ringwald // allow to compile all files in embedded folder even if there's no audio support
54*dfa32746SMatthias Ringwald #ifdef HAVE_HAL_AUDIO
55*dfa32746SMatthias Ringwald 
56*dfa32746SMatthias Ringwald #define DRIVER_POLL_INTERVAL_MS          5
57*dfa32746SMatthias Ringwald 
58*dfa32746SMatthias Ringwald // client
59*dfa32746SMatthias Ringwald static void (*playback_callback)(int16_t * buffer, uint16_t num_samples);
60*dfa32746SMatthias Ringwald static void (*recording_callback)(const int16_t * buffer, uint16_t num_samples);
61*dfa32746SMatthias Ringwald 
62*dfa32746SMatthias Ringwald // timer to fill output ring buffer
63*dfa32746SMatthias Ringwald static btstack_timer_source_t  driver_timer;
64*dfa32746SMatthias Ringwald 
65*dfa32746SMatthias Ringwald static volatile unsigned int output_buffer_to_play;
66*dfa32746SMatthias Ringwald static          unsigned int output_buffer_to_fill;
67*dfa32746SMatthias Ringwald static          unsigned int output_buffer_count;
68*dfa32746SMatthias Ringwald static          unsigned int output_buffer_samples;
69*dfa32746SMatthias Ringwald 
70*dfa32746SMatthias Ringwald static void btstack_audio_audio_played(uint8_t buffer_index){
71*dfa32746SMatthias Ringwald     output_buffer_to_play = (buffer_index + 1) % output_buffer_count;
72*dfa32746SMatthias Ringwald }
73*dfa32746SMatthias Ringwald 
74*dfa32746SMatthias Ringwald static void btstack_audio_audio_recorded(const int16_t * samples, uint16_t num_samples){
75*dfa32746SMatthias Ringwald     UNUSED(samples);
76*dfa32746SMatthias Ringwald     UNUSED(num_samples);
77*dfa32746SMatthias Ringwald }
78*dfa32746SMatthias Ringwald 
79*dfa32746SMatthias Ringwald static void driver_timer_handler(btstack_timer_source_t * ts){
80*dfa32746SMatthias Ringwald 
81*dfa32746SMatthias Ringwald     // playback buffer ready to fill
82*dfa32746SMatthias Ringwald     if (playback_callback && output_buffer_to_play != output_buffer_to_fill){
83*dfa32746SMatthias Ringwald         // fill buffer
84*dfa32746SMatthias Ringwald         int16_t * buffer = hal_audio_get_output_buffer(output_buffer_to_fill);
85*dfa32746SMatthias Ringwald         (*playback_callback)(buffer, output_buffer_samples);
86*dfa32746SMatthias Ringwald 
87*dfa32746SMatthias Ringwald         // next
88*dfa32746SMatthias Ringwald         output_buffer_to_fill = (output_buffer_to_fill + 1 ) % output_buffer_count;
89*dfa32746SMatthias Ringwald     }
90*dfa32746SMatthias Ringwald 
91*dfa32746SMatthias Ringwald     // recording buffer ready to process
92*dfa32746SMatthias Ringwald     if (recording_callback){
93*dfa32746SMatthias Ringwald     }
94*dfa32746SMatthias Ringwald 
95*dfa32746SMatthias Ringwald     // re-set timer
96*dfa32746SMatthias Ringwald     btstack_run_loop_set_timer(ts, DRIVER_POLL_INTERVAL_MS);
97*dfa32746SMatthias Ringwald     btstack_run_loop_add_timer(ts);
98*dfa32746SMatthias Ringwald }
99*dfa32746SMatthias Ringwald 
100*dfa32746SMatthias Ringwald static int btstack_audio_embedded_init(
101*dfa32746SMatthias Ringwald     uint8_t channels,
102*dfa32746SMatthias Ringwald     uint32_t samplerate,
103*dfa32746SMatthias Ringwald     void (*playback)(int16_t * buffer, uint16_t num_samples),
104*dfa32746SMatthias Ringwald     void (*recording)(const int16_t * buffer, uint16_t num_samples)
105*dfa32746SMatthias Ringwald ){
106*dfa32746SMatthias Ringwald     playback_callback  = playback;
107*dfa32746SMatthias Ringwald     recording_callback = recording;
108*dfa32746SMatthias Ringwald 
109*dfa32746SMatthias Ringwald     void (*buffer_played_callback)  (uint8_t buffer_index)                         = NULL;
110*dfa32746SMatthias Ringwald     void (*buffer_recorded_callback)(const int16_t * buffer, uint16_t num_samples) = NULL;
111*dfa32746SMatthias Ringwald     if (playback) {
112*dfa32746SMatthias Ringwald         buffer_played_callback = &btstack_audio_audio_played;
113*dfa32746SMatthias Ringwald     }
114*dfa32746SMatthias Ringwald     if (recording) {
115*dfa32746SMatthias Ringwald         buffer_recorded_callback = &btstack_audio_audio_recorded;
116*dfa32746SMatthias Ringwald     }
117*dfa32746SMatthias Ringwald     hal_audio_init(channels, samplerate, buffer_played_callback, buffer_recorded_callback);
118*dfa32746SMatthias Ringwald 
119*dfa32746SMatthias Ringwald     return 0;
120*dfa32746SMatthias Ringwald }
121*dfa32746SMatthias Ringwald 
122*dfa32746SMatthias Ringwald static void btstack_audio_embedded_start_stream(void){
123*dfa32746SMatthias Ringwald 
124*dfa32746SMatthias Ringwald     if (playback_callback){
125*dfa32746SMatthias Ringwald 
126*dfa32746SMatthias Ringwald         output_buffer_count   = hal_audio_get_num_output_buffers();
127*dfa32746SMatthias Ringwald         output_buffer_samples = hal_audio_get_num_output_buffer_samples();
128*dfa32746SMatthias Ringwald 
129*dfa32746SMatthias Ringwald         // pre-fill HAL buffers
130*dfa32746SMatthias Ringwald         uint16_t i;
131*dfa32746SMatthias Ringwald         for (i=0;i<output_buffer_count;i++){
132*dfa32746SMatthias Ringwald             int16_t * buffer = hal_audio_get_output_buffer(i);
133*dfa32746SMatthias Ringwald             (*playback_callback)(buffer, output_buffer_samples);
134*dfa32746SMatthias Ringwald         }
135*dfa32746SMatthias Ringwald 
136*dfa32746SMatthias Ringwald         output_buffer_to_play = 0;
137*dfa32746SMatthias Ringwald         output_buffer_to_fill = 0;
138*dfa32746SMatthias Ringwald     }
139*dfa32746SMatthias Ringwald 
140*dfa32746SMatthias Ringwald     // TODO: setup input
141*dfa32746SMatthias Ringwald 
142*dfa32746SMatthias Ringwald     // start playback
143*dfa32746SMatthias Ringwald     hal_audio_start();
144*dfa32746SMatthias Ringwald 
145*dfa32746SMatthias Ringwald     // start timer
146*dfa32746SMatthias Ringwald     btstack_run_loop_set_timer_handler(&driver_timer, &driver_timer_handler);
147*dfa32746SMatthias Ringwald     btstack_run_loop_set_timer(&driver_timer, DRIVER_POLL_INTERVAL_MS);
148*dfa32746SMatthias Ringwald     btstack_run_loop_add_timer(&driver_timer);
149*dfa32746SMatthias Ringwald }
150*dfa32746SMatthias Ringwald 
151*dfa32746SMatthias Ringwald static void btstack_audio_embedded_close(void){
152*dfa32746SMatthias Ringwald     // stop timer
153*dfa32746SMatthias Ringwald     btstack_run_loop_remove_timer(&driver_timer);
154*dfa32746SMatthias Ringwald     // close HAL
155*dfa32746SMatthias Ringwald     hal_audio_close();
156*dfa32746SMatthias Ringwald }
157*dfa32746SMatthias Ringwald 
158*dfa32746SMatthias Ringwald static const btstack_audio_t btstack_audio_embedded = {
159*dfa32746SMatthias Ringwald     /* int (*init)(..);*/                                       &btstack_audio_embedded_init,
160*dfa32746SMatthias Ringwald     /* void (*start_stream(void));*/                            &btstack_audio_embedded_start_stream,
161*dfa32746SMatthias Ringwald     /* void (*close)(void); */                                  &btstack_audio_embedded_close
162*dfa32746SMatthias Ringwald };
163*dfa32746SMatthias Ringwald 
164*dfa32746SMatthias Ringwald const btstack_audio_t * btstack_audio_embedded_get_instance(void){
165*dfa32746SMatthias Ringwald     return &btstack_audio_embedded;
166*dfa32746SMatthias Ringwald }
167*dfa32746SMatthias Ringwald 
168*dfa32746SMatthias Ringwald #endif
169