diff --git a/port/esp32/components/btstack/btstack_audio_esp32.c b/port/esp32/components/btstack/btstack_audio_esp32.c index e68cbcfd3..7180752b4 100644 --- a/port/esp32/components/btstack/btstack_audio_esp32.c +++ b/port/esp32/components/btstack/btstack_audio_esp32.c @@ -63,6 +63,10 @@ #define IIC_CLK (GPIO_NUM_23) #endif +// prototypes +static void btstack_audio_esp32_sink_fill_buffer(void); +static void btstack_audio_esp32_source_process_buffer(void); + #define BTSTACK_AUDIO_I2S_NUM (I2S_NUM_0) #define DRIVER_POLL_INTERVAL_MS 5 @@ -78,6 +82,7 @@ typedef enum { } btstack_audio_esp32_state_t; static bool btstack_audio_esp32_i2s_installed; +static bool btstack_audio_esp32_i2s_streaming; // timer to fill output ring buffer static btstack_timer_source_t btstack_audio_esp32_driver_timer; @@ -86,16 +91,20 @@ static uint8_t btstack_audio_esp32_sink_num_channels; static uint8_t btstack_audio_esp32_sink_bytes_per_sample; static uint32_t btstack_audio_esp32_sink_samplerate; +static uint8_t btstack_audio_esp32_source_num_channels; +static uint8_t btstack_audio_esp32_source_bytes_per_sample; +static uint32_t btstack_audio_esp32_source_samplerate; + static btstack_audio_esp32_state_t btstack_audio_esp32_sink_state; +static btstack_audio_esp32_state_t btstack_audio_esp32_source_state; // client static void (*btstack_audio_esp32_sink_playback_callback)(int16_t * buffer, uint16_t num_samples); -// static void (*btstack_audio_esp32_source_recording_callback)(const int16_t * buffer, uint16_t num_samples); +static void (*btstack_audio_esp32_source_recording_callback)(const int16_t * buffer, uint16_t num_samples); -// queue for TX done events +// queue for RX/TX done events static QueueHandle_t btstack_audio_esp32_i2s_event_queue; - #ifdef CONFIG_ESP_LYRAT_V4_3_BOARD static bool btstack_audio_esp32_es8388_initialized; @@ -121,17 +130,6 @@ void btstack_audio_esp32_es8388_init(void){ } #endif -static void btstack_audio_esp32_sink_fill_buffer(void){ - size_t bytes_written; - uint8_t buffer[DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO]; - if ((btstack_audio_esp32_sink_playback_callback != NULL) && (btstack_audio_esp32_sink_state == BTSTACK_AUDIO_ESP32_STREAMING)){ - (*btstack_audio_esp32_sink_playback_callback)((int16_t *) buffer, DMA_BUFFER_SAMPLES); - } else { - memset(buffer, 0, sizeof(buffer)); - } - i2s_write(BTSTACK_AUDIO_I2S_NUM, buffer, DMA_BUFFER_SAMPLES * btstack_audio_esp32_sink_bytes_per_sample, &bytes_written, portMAX_DELAY); -} - static void btstack_audio_esp32_driver_timer_handler(btstack_timer_source_t * ts){ // read from i2s event queue i2s_event_t i2s_event; @@ -140,6 +138,9 @@ static void btstack_audio_esp32_driver_timer_handler(btstack_timer_source_t * ts if (i2s_event.type == I2S_EVENT_TX_DONE){ btstack_audio_esp32_sink_fill_buffer(); } + if (i2s_event.type == I2S_EVENT_RX_DONE){ + btstack_audio_esp32_source_process_buffer(); + } } // re-set timer @@ -147,6 +148,39 @@ static void btstack_audio_esp32_driver_timer_handler(btstack_timer_source_t * ts btstack_run_loop_add_timer(ts); } +static void btstack_audio_esp32_stream_start(void){ + if (btstack_audio_esp32_i2s_streaming) return; + + // start i2s + log_info("i2s stream start"); + i2s_start(BTSTACK_AUDIO_I2S_NUM); + + // start timer + btstack_run_loop_set_timer_handler(&btstack_audio_esp32_driver_timer, &btstack_audio_esp32_driver_timer_handler); + btstack_run_loop_set_timer(&btstack_audio_esp32_driver_timer, DRIVER_POLL_INTERVAL_MS); + btstack_run_loop_add_timer(&btstack_audio_esp32_driver_timer); + + btstack_audio_esp32_i2s_streaming = true; +} + +static void btstack_audio_esp32_stream_stop(void){ + if (btstack_audio_esp32_i2s_streaming == false) return; + + // check if still needed + bool still_needed = (btstack_audio_esp32_sink_state == BTSTACK_AUDIO_ESP32_STREAMING) + || (btstack_audio_esp32_source_state == BTSTACK_AUDIO_ESP32_STREAMING); + if (still_needed) return; + + // stop timer + btstack_run_loop_remove_timer(&btstack_audio_esp32_driver_timer); + + // stop i2s + log_info("i2s stream stop"); + i2s_stop(BTSTACK_AUDIO_I2S_NUM); + + btstack_audio_esp32_i2s_streaming = false; +} + static void btstack_audio_esp32_init(void){ // de-register driver if already installed @@ -171,6 +205,12 @@ static void btstack_audio_esp32_init(void){ i2s_data_out_pin = 22; #endif } + if (btstack_audio_esp32_source_state != BTSTACK_AUDIO_ESP32_OFF){ + i2s_mode |= I2S_MODE_RX; // recording +#ifdef CONFIG_ESP_LYRAT_V4_3_BOARD + i2s_data_in_pin = GPIO_NUM_35; +#endif + } i2s_config_t config = { @@ -196,6 +236,8 @@ static void btstack_audio_esp32_init(void){ btstack_audio_esp32_set_i2s0_mclk(); #endif + log_info("i2s init mode 0x%2x", i2s_mode); + i2s_driver_install(BTSTACK_AUDIO_I2S_NUM, &config, DMA_BUFFER_COUNT, &btstack_audio_esp32_i2s_event_queue); i2s_set_pin(BTSTACK_AUDIO_I2S_NUM, &pins); i2s_zero_dma_buffer(BTSTACK_AUDIO_I2S_NUM); @@ -207,11 +249,42 @@ static void btstack_audio_esp32_init(void){ btstack_audio_esp32_i2s_installed = true; } +static void btstack_audio_esp32_deinit(void){ + if (btstack_audio_esp32_i2s_installed == false) return; + + // check if still needed + bool still_needed = (btstack_audio_esp32_sink_state != BTSTACK_AUDIO_ESP32_OFF) + || (btstack_audio_esp32_source_state != BTSTACK_AUDIO_ESP32_OFF); + if (still_needed) return; + + // uninstall driver + log_info("i2s close"); + i2s_driver_uninstall(BTSTACK_AUDIO_I2S_NUM); + + btstack_audio_esp32_i2s_installed = false; +} + +// SINK Implementation + +static void btstack_audio_esp32_sink_fill_buffer(void){ + size_t bytes_written; + uint8_t buffer[DMA_BUFFER_SAMPLES * BYTES_PER_SAMPLE_STEREO]; + if (btstack_audio_esp32_sink_state == BTSTACK_AUDIO_ESP32_STREAMING){ + (*btstack_audio_esp32_sink_playback_callback)((int16_t *) buffer, DMA_BUFFER_SAMPLES); + } else { + memset(buffer, 0, sizeof(buffer)); + } + i2s_write(BTSTACK_AUDIO_I2S_NUM, buffer, DMA_BUFFER_SAMPLES * btstack_audio_esp32_sink_bytes_per_sample, &bytes_written, portMAX_DELAY); +} + static int btstack_audio_esp32_sink_init( uint8_t channels, uint32_t samplerate, void (*playback)(int16_t * buffer, uint16_t num_samples)){ + btstack_assert(playback != NULL); + btstack_assert(channels == 2); + // store config btstack_audio_esp32_sink_playback_callback = playback; btstack_audio_esp32_sink_num_channels = channels; @@ -236,39 +309,28 @@ static void btstack_audio_esp32_sink_set_volume(uint8_t gain) { static void btstack_audio_esp32_sink_start_stream(void){ - if (btstack_audio_esp32_sink_playback_callback){ - // pre-fill HAL buffers - log_info("start stream"); - uint16_t i; - for (i=0;i