Files
H2201_Audio_Mixer/ESP32/main/H2201_a2dp.c
Martijn Scheepers 4ede660f06 a2dp to seperate file
2022-04-25 15:17:50 +02:00

140 lines
4.4 KiB
C

#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;
}
}