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