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