kopia lustrzana https://github.com/espressif/esp-idf
merge from master
rodzic
b013f5d490
commit
14fe6e9bbb
|
@ -11,4 +11,19 @@ Options choose step:
|
||||||
3. enter menu Bluetooth, choose "Classic Bluetooth" and do not choose "Release DRAM from Classic BT controller"
|
3. enter menu Bluetooth, choose "Classic Bluetooth" and do not choose "Release DRAM from Classic BT controller"
|
||||||
4. choose your options.
|
4. choose your options.
|
||||||
|
|
||||||
|
For the I2S codec, pick whatever chip or board works for you; this code was written using a PCM5102 chip, but other I2S boards and chips will probably work as well. The default I2S connections are shown below, but these can be changed in menuconfig:
|
||||||
|
|
||||||
|
+-----------+--------------+
|
||||||
|
| ESP pin | I2S signal |
|
||||||
|
+===========+==============+
|
||||||
|
| GPIO22 | LRCK |
|
||||||
|
+-----------+--------------+
|
||||||
|
| GPIO25 | DATA |
|
||||||
|
+-----------+--------------+
|
||||||
|
| GPIO26 | BCK |
|
||||||
|
+-----------+--------------+
|
||||||
|
|
||||||
|
If the internal DAC is selected, analog audio will be available on GPIO25 and GPIO26. The output resolution on these pins will always be limited to 8 bit because of the internal structure of the DACs.
|
||||||
|
|
||||||
|
|
||||||
After the program started, other bluetooth devices such as smart phones can discover this device named "ESP_SPEAKER", and after connection is established, audio data can be transmitted and there will occur a count of audio data packets printed.
|
After the program started, other bluetooth devices such as smart phones can discover this device named "ESP_SPEAKER", and after connection is established, audio data can be transmitted and there will occur a count of audio data packets printed.
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
menu "A2DP Example Configuration"
|
||||||
|
|
||||||
|
choice A2DP_SINK_OUTPUT
|
||||||
|
prompt "A2DP Sink Output"
|
||||||
|
default A2DP_SINK_OUTPUT_EXTERNAL_I2S
|
||||||
|
help
|
||||||
|
Select to use Internal DAC or external I2S driver
|
||||||
|
|
||||||
|
config A2DP_SINK_OUTPUT_INTERNAL_DAC
|
||||||
|
bool "Internal DAC"
|
||||||
|
help
|
||||||
|
Select this to use Internal DAC sink output
|
||||||
|
|
||||||
|
config A2DP_SINK_OUTPUT_EXTERNAL_I2S
|
||||||
|
bool "External I2S Codec"
|
||||||
|
help
|
||||||
|
Select this to use External I2S sink output
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config I2S_LRCK_PIN
|
||||||
|
int "I2S LRCK (WS) GPIO"
|
||||||
|
default 22
|
||||||
|
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
|
||||||
|
help
|
||||||
|
GPIO number to use for I2S LRCK(WS) Driver.
|
||||||
|
|
||||||
|
config I2S_BCK_PIN
|
||||||
|
int "I2S BCK GPIO"
|
||||||
|
default 26
|
||||||
|
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
|
||||||
|
help
|
||||||
|
GPIO number to use for I2S BCK Driver.
|
||||||
|
|
||||||
|
config I2S_DATA_PIN
|
||||||
|
int "I2S DATA GPIO"
|
||||||
|
default 25
|
||||||
|
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
|
||||||
|
help
|
||||||
|
GPIO number to use for I2S Data Driver.
|
||||||
|
|
||||||
|
|
||||||
|
endmenu
|
|
@ -26,6 +26,10 @@
|
||||||
#include "esp_a2dp_api.h"
|
#include "esp_a2dp_api.h"
|
||||||
#include "esp_avrc_api.h"
|
#include "esp_avrc_api.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/i2s.h"
|
||||||
|
|
||||||
/* a2dp event handler */
|
/* a2dp event handler */
|
||||||
static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param);
|
static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param);
|
||||||
/* avrc event handler */
|
/* avrc event handler */
|
||||||
|
@ -53,6 +57,7 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||||
|
|
||||||
void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
|
void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
|
||||||
{
|
{
|
||||||
|
i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY);
|
||||||
if (++m_pkt_cnt % 100 == 0) {
|
if (++m_pkt_cnt % 100 == 0) {
|
||||||
ESP_LOGE(BT_AV_TAG, "audio data pkt cnt %u", m_pkt_cnt);
|
ESP_LOGE(BT_AV_TAG, "audio data pkt cnt %u", m_pkt_cnt);
|
||||||
}
|
}
|
||||||
|
@ -96,7 +101,23 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param)
|
||||||
ESP_LOGI(BT_AV_TAG, "a2dp audio_cfg_cb , codec type %d", a2d->audio_cfg.mcc.type);
|
ESP_LOGI(BT_AV_TAG, "a2dp audio_cfg_cb , codec type %d", a2d->audio_cfg.mcc.type);
|
||||||
// for now only SBC stream is supported
|
// for now only SBC stream is supported
|
||||||
if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) {
|
if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) {
|
||||||
ESP_LOGI(BT_AV_TAG, "audio player configured");
|
int sample_rate = 16000;
|
||||||
|
char oct0 = a2d->audio_cfg.mcc.cie.sbc[0];
|
||||||
|
if (oct0 & (0x01 << 6)) {
|
||||||
|
sample_rate = 32000;
|
||||||
|
} else if (oct0 & (0x01 << 5)) {
|
||||||
|
sample_rate = 44100;
|
||||||
|
} else if (oct0 & (0x01 << 4)) {
|
||||||
|
sample_rate = 48000;
|
||||||
|
}
|
||||||
|
i2s_set_clk(0, sample_rate, 16, 2);
|
||||||
|
|
||||||
|
ESP_LOGI(BT_AV_TAG, "configure audio player %x-%x-%x-%x\n",
|
||||||
|
a2d->audio_cfg.mcc.cie.sbc[0],
|
||||||
|
a2d->audio_cfg.mcc.cie.sbc[1],
|
||||||
|
a2d->audio_cfg.mcc.cie.sbc[2],
|
||||||
|
a2d->audio_cfg.mcc.cie.sbc[3]);
|
||||||
|
ESP_LOGI(BT_AV_TAG, "audio player configured, samplerate=%d", sample_rate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "esp_gap_bt_api.h"
|
#include "esp_gap_bt_api.h"
|
||||||
#include "esp_a2dp_api.h"
|
#include "esp_a2dp_api.h"
|
||||||
#include "esp_avrc_api.h"
|
#include "esp_avrc_api.h"
|
||||||
|
#include "driver/i2s.h"
|
||||||
|
|
||||||
/* event for handler "bt_av_hdl_stack_up */
|
/* event for handler "bt_av_hdl_stack_up */
|
||||||
enum {
|
enum {
|
||||||
|
@ -51,6 +52,37 @@ void app_main()
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK( ret );
|
ESP_ERROR_CHECK( ret );
|
||||||
|
|
||||||
|
i2s_config_t i2s_config = {
|
||||||
|
#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
||||||
|
.mode = I2S_MODE_DAC_BUILT_IN,
|
||||||
|
#else
|
||||||
|
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||||
|
#endif
|
||||||
|
.sample_rate = 44100,
|
||||||
|
.bits_per_sample = 16,
|
||||||
|
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
|
||||||
|
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
|
||||||
|
.dma_buf_count = 6,
|
||||||
|
.dma_buf_len = 60, //
|
||||||
|
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
i2s_driver_install(0, &i2s_config, 0, NULL);
|
||||||
|
#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC
|
||||||
|
i2s_set_pin(0, NULL);
|
||||||
|
#else
|
||||||
|
i2s_pin_config_t pin_config = {
|
||||||
|
.bck_io_num = CONFIG_I2S_BCK_PIN,
|
||||||
|
.ws_io_num = CONFIG_I2S_LRCK_PIN,
|
||||||
|
.data_out_num = CONFIG_I2S_DATA_PIN,
|
||||||
|
.data_in_num = -1 //Not used
|
||||||
|
};
|
||||||
|
|
||||||
|
i2s_set_pin(0, &pin_config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||||
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
||||||
|
|
|
@ -2,4 +2,3 @@
|
||||||
# Classic BT is enabled and BT_DRAM_RELEASE is disabled
|
# Classic BT is enabled and BT_DRAM_RELEASE is disabled
|
||||||
CONFIG_BT_ENABLED=y
|
CONFIG_BT_ENABLED=y
|
||||||
CONFIG_CLASSIC_BT_ENABLED=y
|
CONFIG_CLASSIC_BT_ENABLED=y
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue