Last active
February 22, 2020 16:35
-
-
Save goran-mahovlic/b500f179694215ba0626feea4c0d6743 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Stream musing from I2S to Bluetooth | |
This example code is in the Public Domain (or CC0 licensed, at your option.) | |
Unless required by applicable law or agreed to in writing, this | |
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | |
CONDITIONS OF ANY KIND, either express or implied. | |
*/ | |
#include <string.h> | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "esp_log.h" | |
#include "esp_wifi.h" | |
#include "nvs_flash.h" | |
#include "sdkconfig.h" | |
#include "audio_element.h" | |
#include "audio_pipeline.h" | |
#include "audio_event_iface.h" | |
#include "audio_common.h" | |
#include "esp_peripherals.h" | |
#include "periph_wifi.h" | |
#include "board.h" | |
#include "bluetooth_service.h" | |
#include "i2s_stream.h" | |
#include "driver/i2s.h" | |
static const char *TAG = "BLUETOOTH_SOURCE_EXAMPLE"; | |
void app_main(void) | |
{ | |
audio_pipeline_handle_t pipeline; | |
audio_element_handle_t i2s_stream_reader, bt_stream_writer; | |
esp_err_t err = nvs_flash_init(); | |
if (err == ESP_ERR_NVS_NO_FREE_PAGES) { | |
// NVS partition was truncated and needs to be erased | |
// Retry nvs_flash_init | |
ESP_ERROR_CHECK(nvs_flash_erase()); | |
err = nvs_flash_init(); | |
} | |
tcpip_adapter_init(); | |
esp_log_level_set("*", ESP_LOG_INFO); | |
esp_log_level_set(TAG, ESP_LOG_DEBUG); | |
ESP_LOGI(TAG, "[ 1 ] Create Bluetooth service"); | |
bluetooth_service_cfg_t bt_cfg = { | |
.device_name = "ESP-ADF-SOURCE", | |
.mode = BLUETOOTH_A2DP_SOURCE, | |
.remote_name = "XR 84 PLUS", | |
}; | |
bluetooth_service_start(&bt_cfg); | |
ESP_LOGI(TAG, "[1.1] Get Bluetooth stream"); | |
bt_stream_writer = bluetooth_service_create_stream(); | |
ESP_LOGI(TAG, "[2] Create i2s stream to read audio data from codec chip"); | |
i2s_stream_cfg_t i2s_cfg = I2S_STREAM_CFG_DEFAULT(); | |
// on FPGA set sample rate to 44100 | |
i2s_cfg.i2s_config.sample_rate = 48000; | |
i2s_cfg.i2s_config.mode = I2S_MODE_SLAVE | I2S_MODE_RX; | |
i2s_cfg.type = AUDIO_STREAM_READER; | |
i2s_cfg.i2s_config.bits_per_sample = 16; | |
i2s_cfg.i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; //2-channels | |
i2s_cfg.i2s_config.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB; | |
// Reason of low buffer is that I want sound as fast as possible out to speaker | |
i2s_cfg.i2s_config.dma_buf_count = 2; | |
i2s_cfg.i2s_config.dma_buf_len = 32; | |
i2s_cfg.i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1; //Default interrupt priority | |
i2s_cfg.i2s_config.tx_desc_auto_clear = true; //Auto clear tx descriptor on underflow | |
// Did not make any change | |
I2S0.fifo_conf.dscr_en = 0; | |
I2S0.fifo_conf.rx_fifo_mod_force_en = 0; | |
I2S0.fifo_conf.rx_fifo_mod = 0; | |
I2S0.fifo_conf.rx_fifo_mod = 0; | |
// Using APLL clock output on GPIO0 to drive FPGA | |
i2s_cfg.i2s_config.use_apll = true; | |
i2s_stream_reader = i2s_stream_init(&i2s_cfg); | |
ESP_LOGI(TAG, "[ 3 ] Create audio pipeline for BT Source"); | |
audio_pipeline_cfg_t pipeline_cfg = DEFAULT_AUDIO_PIPELINE_CONFIG(); | |
pipeline = audio_pipeline_init(&pipeline_cfg); | |
ESP_LOGI(TAG, "[3.1] Register all elements to audio pipeline"); | |
audio_pipeline_register(pipeline, i2s_stream_reader, "i2s"); | |
audio_pipeline_register(pipeline, bt_stream_writer, "bt"); | |
ESP_LOGI(TAG, "[3.2] Link it together i2s-->bt_stream_writer"); | |
audio_pipeline_link(pipeline, (const char *[]) {"i2s", "bt"}, 2); | |
ESP_LOGI(TAG, "[ 4 ] Start and wait for Wi-Fi network"); | |
esp_periph_config_t periph_cfg = DEFAULT_ESP_PERIPH_SET_CONFIG(); | |
esp_periph_set_handle_t set = esp_periph_set_init(&periph_cfg); | |
periph_wifi_cfg_t wifi_cfg = { | |
.ssid = CONFIG_WIFI_SSID, | |
.password = CONFIG_WIFI_PASSWORD, | |
}; | |
// If more buffer is needed wifi needs to be turned off | |
// esp_periph_handle_t wifi_handle = periph_wifi_init(&wifi_cfg); | |
// esp_periph_start(set, wifi_handle); | |
// periph_wifi_wait_for_connected(wifi_handle, portMAX_DELAY); | |
// esp_wifi_stop(); | |
// esp_wifi_deinit(); | |
ESP_LOGI(TAG, "[5.1] Create Bluetooth peripheral"); | |
esp_periph_handle_t bt_periph = bluetooth_service_create_periph(); | |
ESP_LOGI(TAG, "[5.2] Start Bluetooth peripheral"); | |
esp_periph_start(set, bt_periph); | |
ESP_LOGI(TAG, "[ 6 ] Set up event listener"); | |
audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG(); | |
audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg); | |
ESP_LOGI(TAG, "[6.1] Listening event from all elements of pipeline"); | |
audio_pipeline_set_listener(pipeline, evt); | |
ESP_LOGI(TAG, "[6.2] Listening event from peripherals"); | |
audio_event_iface_set_listener(esp_periph_set_get_event_iface(set), evt); | |
ESP_LOGI(TAG, "[ 7 ] Start audio_pipeline"); | |
audio_pipeline_run(pipeline); | |
ESP_LOGI(TAG, "[ 8 ] Listen for all pipeline events"); | |
while (1) { | |
audio_event_iface_msg_t msg; | |
esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY); | |
if (ret != ESP_OK) { | |
ESP_LOGE(TAG, "[ * ] Event interface error : %d", ret); | |
continue; | |
} | |
/* Stop when the Bluetooth is disconnected or suspended */ | |
if (msg.source_type == PERIPH_ID_BLUETOOTH | |
&& msg.source == (void *)bt_periph) { | |
if ((msg.cmd == PERIPH_BLUETOOTH_DISCONNECTED) || (msg.cmd == PERIPH_BLUETOOTH_AUDIO_SUSPENDED)) { | |
ESP_LOGW(TAG, "[ * ] Bluetooth disconnected or suspended"); | |
periph_bluetooth_stop(bt_periph); | |
break; | |
} | |
} | |
} | |
ESP_LOGI(TAG, "[ 9 ] Stop audio_pipeline"); | |
audio_pipeline_terminate(pipeline); | |
/* Terminate the pipeline before removing the listener */ | |
audio_pipeline_remove_listener(pipeline); | |
/* Stop all peripherals before removing the listener */ | |
esp_periph_set_stop_all(set); | |
audio_event_iface_remove_listener(esp_periph_set_get_event_iface(set), evt); | |
/* Make sure audio_pipeline_remove_listener & audio_event_iface_remove_listener are called before destroying event_iface */ | |
audio_event_iface_destroy(evt); | |
/* Release all resources */ | |
audio_pipeline_unregister(pipeline, bt_stream_writer); | |
audio_pipeline_unregister(pipeline, i2s_stream_reader); | |
audio_pipeline_deinit(pipeline); | |
audio_element_deinit(bt_stream_writer); | |
audio_element_deinit(i2s_stream_reader); | |
esp_periph_set_destroy(set); | |
bluetooth_service_destroy(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment