a2dp to seperate file
This commit is contained in:
5
ESP32/.vscode/settings.json
vendored
5
ESP32/.vscode/settings.json
vendored
@@ -12,5 +12,8 @@
|
||||
"idf.portWin": "COM5",
|
||||
"idf.pythonBinPathWin": "C:\\Users\\ms\\.espressif\\python_env\\idf4.4_py3.8_env\\Scripts\\python.exe",
|
||||
"idf.toolsPathWin": "C:\\Users\\ms\\.espressif",
|
||||
"idf.flashType": "UART"
|
||||
"idf.flashType": "UART",
|
||||
"files.associations": {
|
||||
"esp_log.h": "c"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS "H2201_i2s.c" "bt_app_av.c"
|
||||
idf_component_register(SRCS "H2201_a2dp.c" "H2201_i2s.c" "bt_app_av.c"
|
||||
"bt_app_core.c"
|
||||
"main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
140
ESP32/main/H2201_a2dp.c
Normal file
140
ESP32/main/H2201_a2dp.c
Normal file
@@ -0,0 +1,140 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_a2dp_api.h"
|
||||
#include "esp_avrc_api.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#include "sys/lock.h"
|
||||
|
||||
#include "bt_app_core.h"
|
||||
#include "H2201_i2s.h"
|
||||
#include "H2201_a2dp.h"
|
||||
|
||||
static void h2201_a2dp_eventhandler(uint16_t event, void *p_param);
|
||||
|
||||
static uint32_t s_pkt_cnt = 0;
|
||||
static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED;
|
||||
static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"};
|
||||
static const char *s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"};
|
||||
|
||||
/* callback for A2DP sink */
|
||||
void h2201_a2dp_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESP_A2D_CONNECTION_STATE_EVT:
|
||||
case ESP_A2D_AUDIO_STATE_EVT:
|
||||
case ESP_A2D_AUDIO_CFG_EVT:
|
||||
case ESP_A2D_PROF_STATE_EVT:
|
||||
{
|
||||
bt_app_work_dispatch(h2201_a2dp_eventhandler, event, param, sizeof(esp_a2d_cb_param_t), NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(H2201_A2DP_TAG, "Invalid A2DP event: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void h2201_a2dp_data_callback(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
h2201_i2s_write_ringbuf(data, len);
|
||||
// if (++s_pkt_cnt % 100 == 0) {
|
||||
// ESP_LOGI(H2201_A2DP_TAG, "Audio packet count %u", s_pkt_cnt);
|
||||
// }
|
||||
}
|
||||
|
||||
static void h2201_a2dp_eventhandler(uint16_t event, void *p_param)
|
||||
{
|
||||
ESP_LOGD(H2201_A2DP_TAG, "%s evt %d", __func__, event);
|
||||
esp_a2d_cb_param_t *a2d = NULL;
|
||||
switch (event)
|
||||
{
|
||||
case ESP_A2D_CONNECTION_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
uint8_t *bda = a2d->conn_stat.remote_bda;
|
||||
ESP_LOGI(H2201_A2DP_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED)
|
||||
{
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
h2201_i2s_task_shut_down();
|
||||
}
|
||||
else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED)
|
||||
{
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
|
||||
h2201_i2s_task_start_up();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_AUDIO_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
ESP_LOGI(H2201_A2DP_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]);
|
||||
s_audio_state = a2d->audio_stat.state;
|
||||
if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state)
|
||||
{
|
||||
s_pkt_cnt = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_AUDIO_CFG_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
ESP_LOGI(H2201_A2DP_TAG, "A2DP audio stream configuration, 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)
|
||||
{
|
||||
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(H2201_A2DP_TAG, "Configure audio player %x-%x-%x-%x",
|
||||
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(H2201_A2DP_TAG, "Audio player configured, sample rate=%d", sample_rate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_PROF_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state)
|
||||
{
|
||||
ESP_LOGI(H2201_A2DP_TAG, "A2DP PROF STATE: Init Compl\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(H2201_A2DP_TAG, "A2DP PROF STATE: Deinit Compl\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(H2201_A2DP_TAG, "%s unhandled evt %d", __func__, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
19
ESP32/main/H2201_a2dp.h
Normal file
19
ESP32/main/H2201_a2dp.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef __H2201_A2DP_H__
|
||||
#define __H2201_A2DP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_a2dp_api.h"
|
||||
|
||||
#define H2201_A2DP_TAG "A2DP"
|
||||
|
||||
/**
|
||||
* @brief callback function for A2DP sink
|
||||
*/
|
||||
void h2201_a2dp_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief callback function for A2DP sink audio data stream
|
||||
*/
|
||||
void h2201_a2dp_data_callback(const uint8_t *data, uint32_t len);
|
||||
|
||||
#endif /* __H2201_A2DP_H__ */
|
||||
@@ -1,12 +1,3 @@
|
||||
|
||||
/*
|
||||
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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
@@ -36,46 +27,14 @@
|
||||
#define APP_RC_CT_TL_RN_PLAYBACK_CHANGE (3)
|
||||
#define APP_RC_CT_TL_RN_PLAY_POS_CHANGE (4)
|
||||
|
||||
static void h2201_a2dp_eventhandler(uint16_t event, void *p_param);
|
||||
static void h2201_avrcp_controller_eventhandler(uint16_t event, void *p_param);
|
||||
static void h2201_avrcp_target_eventhandler(uint16_t event, void *p_param);
|
||||
|
||||
static uint32_t s_pkt_cnt = 0;
|
||||
static esp_a2d_audio_state_t s_audio_state = ESP_A2D_AUDIO_STATE_STOPPED;
|
||||
static const char *s_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"};
|
||||
static const char *s_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"};
|
||||
static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
|
||||
static _lock_t s_volume_lock;
|
||||
static uint8_t s_volume = 0;
|
||||
static bool s_volume_notify;
|
||||
|
||||
/* callback for A2DP sink */
|
||||
void h2201_a2dp_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESP_A2D_CONNECTION_STATE_EVT:
|
||||
case ESP_A2D_AUDIO_STATE_EVT:
|
||||
case ESP_A2D_AUDIO_CFG_EVT:
|
||||
case ESP_A2D_PROF_STATE_EVT:
|
||||
{
|
||||
bt_app_work_dispatch(h2201_a2dp_eventhandler, event, param, sizeof(esp_a2d_cb_param_t), NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void h2201_a2dp_data_callback(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
h2201_i2s_write_ringbuf(data, len);
|
||||
// if (++s_pkt_cnt % 100 == 0) {
|
||||
// ESP_LOGI(BT_AV_TAG, "Audio packet count %u", s_pkt_cnt);
|
||||
// }
|
||||
}
|
||||
|
||||
void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param)
|
||||
{
|
||||
esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param);
|
||||
@@ -126,92 +85,6 @@ void h2201_avrcp_target_callback(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_pa
|
||||
}
|
||||
}
|
||||
|
||||
static void h2201_a2dp_eventhandler(uint16_t event, void *p_param)
|
||||
{
|
||||
ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event);
|
||||
esp_a2d_cb_param_t *a2d = NULL;
|
||||
switch (event)
|
||||
{
|
||||
case ESP_A2D_CONNECTION_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
uint8_t *bda = a2d->conn_stat.remote_bda;
|
||||
ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
s_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED)
|
||||
{
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
h2201_i2s_task_shut_down();
|
||||
}
|
||||
else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED)
|
||||
{
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_NON_CONNECTABLE, ESP_BT_NON_DISCOVERABLE);
|
||||
h2201_i2s_task_start_up();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_AUDIO_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]);
|
||||
s_audio_state = a2d->audio_stat.state;
|
||||
if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state)
|
||||
{
|
||||
s_pkt_cnt = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_AUDIO_CFG_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, 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)
|
||||
{
|
||||
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",
|
||||
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, sample rate=%d", sample_rate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_PROF_STATE_EVT:
|
||||
{
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
if (ESP_A2D_INIT_SUCCESS == a2d->a2d_prof_stat.init_state)
|
||||
{
|
||||
ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Init Compl\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGI(BT_AV_TAG, "A2DP PROF STATE: Deinit Compl\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ESP_LOGE(BT_AV_TAG, "%s unhandled evt %d", __func__, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void h2201_avrcp_new_track(void)
|
||||
{
|
||||
// request metadata
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __BT_APP_AV_H__
|
||||
#define __BT_APP_AV_H__
|
||||
|
||||
@@ -17,16 +9,6 @@
|
||||
#define BT_RC_TG_TAG "RCTG"
|
||||
#define BT_RC_CT_TAG "RCCT"
|
||||
|
||||
/**
|
||||
* @brief callback function for A2DP sink
|
||||
*/
|
||||
void h2201_a2dp_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief callback function for A2DP sink audio data stream
|
||||
*/
|
||||
void h2201_a2dp_data_callback(const uint8_t *data, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief callback function for AVRCP controller
|
||||
*/
|
||||
|
||||
@@ -24,8 +24,10 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
|
||||
#include "bt_app_core.h"
|
||||
#include "bt_app_av.h"
|
||||
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
@@ -33,6 +35,9 @@
|
||||
#include "esp_avrc_api.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#include "H2201_a2dp.h"
|
||||
|
||||
|
||||
/* event for handler "bt_av_hdl_stack_up */
|
||||
enum
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user