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