merge from master
This commit is contained in:
parent
b013f5d490
commit
14fe6e9bbb
5 changed files with 112 additions and 2 deletions
|
@ -11,4 +11,19 @@ Options choose step:
|
|||
3. enter menu Bluetooth, choose "Classic Bluetooth" and do not choose "Release DRAM from Classic BT controller"
|
||||
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.
|
||||
|
|
43
examples/bluetooth/a2dp_sink/main/Kconfig.projbuild
Normal file
43
examples/bluetooth/a2dp_sink/main/Kconfig.projbuild
Normal file
|
@ -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_avrc_api.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
/* a2dp event handler */
|
||||
static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param);
|
||||
/* 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)
|
||||
{
|
||||
i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY);
|
||||
if (++m_pkt_cnt % 100 == 0) {
|
||||
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);
|
||||
// for now only SBC stream is supported
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_a2dp_api.h"
|
||||
#include "esp_avrc_api.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
/* event for handler "bt_av_hdl_stack_up */
|
||||
enum {
|
||||
|
@ -51,6 +52,37 @@ void app_main()
|
|||
}
|
||||
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();
|
||||
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
# Classic BT is enabled and BT_DRAM_RELEASE is disabled
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_CLASSIC_BT_ENABLED=y
|
||||
|
||||
|
|
Loading…
Reference in a new issue