Skip to content

Commit

Permalink
Support for IDF
Browse files Browse the repository at this point in the history
  • Loading branch information
pschatzmann committed Aug 15, 2021
1 parent c6d5462 commit a730f60
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 143 deletions.
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# -- copyright GPLv3

idf_component_register(
SRCS "src/BluetoothA2DPSink.cpp" "src/BluetoothA2DPSource.cpp"
INCLUDE_DIRS "src")
SRCS "src/BluetoothA2DPCommon.cpp" "src/BluetoothA2DPSink.cpp" "src/BluetoothA2DPSource.cpp"
INCLUDE_DIRS "src"
REQUIRES bt esp_common freertos hal log nvs_flash
)

target_compile_options(${COMPONENT_LIB} PUBLIC "-Wno-unused-variable" "-Wno-missing-field-initializers" "-fpermissive" "-DCURRENT_ESP_IDF" )
57 changes: 1 addition & 56 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,62 +260,7 @@ If you are using a current version of ESP IDF, you will receive compile errors l

## Change History

Main

- add volume control - thanks to [tv4you2016](https://github.com/tv4you2016)
- add set volume control (set_volume(uint8_t volume);)- thanks to [tv4you2016](https://github.com/tv4you2016)
- add get volume control (get_volume()) - thanks to [tv4you2016](https://github.com/tv4you2016)
- Additional functionality for latest IDF release (Not available for Arduino)
- add callback bt_volumechange - thanks to [tv4you2016](https://github.com/tv4you2016)
- fix I2S_COMM_FORMAT_I2S_MSB - thanks to [tv4you2016](https://github.com/tv4you2016)
- setPinCode (int passkey) - thanks to [tv4you2016](https://github.com/tv4you2016)
- Avoiding noise in case of data unavailability - thanks to [alexus2033](https://github.com/alexus2033)

V1.3.0
- provide get_connection_status() method
- provide end() method to shut down bluetooth
- add compile time switch for new ESP IDF
- add additional flag in set_stream_reader to deactivate i2s
- Remove includes of Arduino.h to highlight independence of Arduino API
- New examples with LED and auto shut down on idle
- Clean up compile warnings so that build with warnings ALL will succeed
- Example with set_pin_config
- Correction - Bluetooth devices with address starting 00 did not auto reconnect
- provide set_discoverability() to change BT discovery mode (only for current ESP IDF) thanks to [rbuehlma](https://github.com/rbuehlma)
- Implement mono downmix thanks to [rbuehlma](https://github.com/rbuehlma)
- expand to 24 or 32 bits using i2s_config.bits_per_sample thanks to [riraosan](https://github.com/riraosan)
- Tracknumber and TrackCount added to Metadata thanks to [alexus2033](https://github.com/alexus2033)
- Correction which allows restart after calling end() thanks to [alexus2033](https://github.com/alexus2033)
- Add method to disconnect current connection thanks to [ashthespy](https://github.com/ashthespy)

V1.2.0
- Metadata support with the help of a callback function - Thanks to [JohnyMielony](https://github.com/JohnyMielony)
- AVRC command support thanks to [PeterPark](https://github.com/KIdon-Park)
- Improved init_bluetooth checks, in case bluedroid was already initialized elsewhere - Thanks to [Antonis Katzourakis](https://github.com/ant0nisk)
- No auto reconnect after clean disconnect - Thanks to [Bajczi Levente](https://github.com/leventeBajczi)
- The data is rescaled to when written to the internal DAC - Thanks to [Martin Hron](https://github.com/thinkcz)
- Corrected wrong case of include to Arduino.h - Thanks to [RyanDavis](https://github.com/RyanDavis)
- Added callback to received packets - Thanks to [Mishaux](https://github.com/Mishaux)
- Automatically reconnect to last source - Thanks to [JohnyMielony](https://github.com/JohnyMielony)
- Support for data callback - Thanks to [Mike Mishaux](https://github.com/Mishaux)
- Improved init_bluetooth checks, in case bluedroid was already initialized elsewhere [Antonis Katzourakis](https://github.com/ant0nisk)
- No auto reconnect after clean disconnect thanks to [Bajczi Levente](https://github.com/leventeBajczi)
- Made all methods virtual to enable flexible subclassing
- Error Corrections in BluetoothA2DPSource
- Support for writeData in BluetoothA2DPSource
- Support for multiple alternative BT names in BluetoothA2DPSource
- Redesign to protect internal callbacks in BluetoothA2DPSink
- Generate Documentation with the help of doxygen

V1.1.0
- New functionality: BluetoothA2DPSource
- Renamed project from 'esp32_bt_music_receiver' to 'ESP32-A2DP'
- Corrected Spelling Mistake from Blootooth to Bluetooth in Class names: The correct class name is BluetoothA2DPSink!
- The include h files are now called like the class names (e.g. BluetoothA2DPSink.h and BluetoothA2DPSource.h)

V1.0.0
- Initial Release

The [Change History can be found in the Wiki](https://github.com/pschatzmann/ESP32-A2DP/wiki/Change-History)



4 changes: 4 additions & 0 deletions component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
36 changes: 36 additions & 0 deletions src/BluetoothA2DPCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

#ifndef ARDUINO_ARCH_ESP32

#include "BluetoothA2DPCommon.h"

/**
* @brief Startup logic as implemented by Arduino - This is not available if we use this library outside of Arduino
*
* @return true
* @return false
*/
bool btStart(){
esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
return true;
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
esp_bt_controller_init(&cfg);
while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){}
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) {
ESP_LOGE(APP, "BT Enable failed");
return false;
}
}
if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
return true;
}
ESP_LOGE(APP, "BT Start failed");
return false;
}

#endif


50 changes: 46 additions & 4 deletions src/BluetoothA2DPCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,42 @@
// Copyright 2020 Phil Schatzmann
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD

#ifndef __A2DP_COMMON_H__
#define __A2DP_COMMON_H__
#pragma once

// Enable this if you are using a current version of ESP IDF e.g. 4.3
// #define CURRENT_ESP_IDF
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#include "freertos/xtensa_api.h"
#include "freertos/FreeRTOSConfig.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"
#include "esp_a2dp_api.h"
#include "driver/i2s.h"
#include "esp_avrc_api.h"
#include <esp_gap_ble_api.h>
#include "esp_spp_api.h"
#include "nvs.h"
#include "nvs_flash.h"

#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#include "esp32-hal-bt.h"
#else
#include "esp_log.h"

extern "C" bool btStart();

#endif

/**
* @brief handler for the dispatched work
Expand All @@ -32,4 +63,15 @@ typedef struct {
void *param; /*!< parameter area needs to be last */
} app_msg_t;


#ifndef ARDUINO_ARCH_ESP32
#define delay(millis) const TickType_t xDelay = millis / portTICK_PERIOD_MS; vTaskDelay(xDelay);
#endif

#define BT_APP_CORE_TAG "BT_APP_CORE"
#define APP "BT_APP_CORE"
#define BT_AV_TAG "BT_AV"
#define BT_RC_CT_TAG "RCCT"
#define BT_APP_TAG "BT_API"


21 changes: 8 additions & 13 deletions src/BluetoothA2DPSink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ int connection_rety_count = 0;
esp_bd_addr_t peer_bd_addr = {0};
static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB;

#ifdef CURRENT_ESP_IDF
static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
#endif

static _lock_t s_volume_lock;
static uint8_t s_volume = 0;
static bool is_volume_used = false;
Expand All @@ -41,6 +37,7 @@ extern "C" void app_a2d_callback_2(esp_a2d_cb_event_t event, esp_a2d_cb_param_t
extern "C" void app_rc_ct_callback_2(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param);

#ifdef CURRENT_ESP_IDF
static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
extern "C" void app_rc_tg_callback_2(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param);
#endif

Expand Down Expand Up @@ -177,7 +174,6 @@ void BluetoothA2DPSink::set_on_data_received(void (*callBack)()){
}



void BluetoothA2DPSink::set_on_connected2BT(void (*callBack)()){
this->bt_connected = callBack;
}
Expand Down Expand Up @@ -264,7 +260,7 @@ void BluetoothA2DPSink::start(const char* name, bool auto_reconnect)

esp_err_t BluetoothA2DPSink::i2s_mclk_pin_select(const uint8_t pin) {
if(pin != 0 && pin != 1 && pin != 3) {
ESP_LOGE(TAG, "Only support GPIO0/GPIO1/GPIO3, gpio_num:%d", pin);
ESP_LOGE(APP, "Only support GPIO0/GPIO1/GPIO3, gpio_num:%d", pin);
return ESP_ERR_INVALID_ARG;
}
switch(pin){
Expand Down Expand Up @@ -519,7 +515,7 @@ void BluetoothA2DPSink::app_rc_tg_callback(esp_avrc_tg_cb_event_t event, esp_avr
break;
}
default:
ESP_LOGE(BT_RC_TG_TAG, "Invalid AVRC event: %d", event);
ESP_LOGE(BT_AV_TAG, "Invalid AVRC event: %d", event);
break;
}

Expand Down Expand Up @@ -780,7 +776,7 @@ void BluetoothA2DPSink::av_hdl_avrc_evt(uint16_t event, void *p_param)
break;
}
case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: {
ESP_LOGI(BT_AV_TAG, "AVRC event notification: %d, param: %d", rc->change_ntf.event_id, rc->change_ntf.event_parameter);
//ESP_LOGI(BT_AV_TAG, "AVRC event notification: %d, param: %d", (int)rc->change_ntf.event_id, (int)rc->change_ntf.event_parameter);
av_notify_evt_handler(rc->change_ntf.event_id, rc->change_ntf.event_parameter);
break;
}
Expand Down Expand Up @@ -1067,7 +1063,7 @@ void BluetoothA2DPSink::get_last_connection(){

err = nvs_open("connected_bda", NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE("NVS OPEN ERROR");
ESP_LOGE(BT_AV_TAG,"NVS OPEN ERROR");
}

esp_bd_addr_t bda;
Expand All @@ -1093,7 +1089,7 @@ void BluetoothA2DPSink::set_last_connection(esp_bd_addr_t bda, size_t size){

err = nvs_open("connected_bda", NVS_READWRITE, &my_handle);
if (err != ESP_OK){
ESP_LOGE("NVS OPEN ERROR");
ESP_LOGE(BT_AV_TAG, "NVS OPEN ERROR");
}
err = nvs_set_blob(my_handle, "last_bda", bda, size);
if (err == ESP_OK) {
Expand Down Expand Up @@ -1266,6 +1262,8 @@ void BluetoothA2DPSink::set_discoverability(esp_bt_discovery_mode_t d) {
void BluetoothA2DPSink::av_hdl_avrc_tg_evt(uint16_t event, void *p_param)
{
ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event);
esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(p_param);

switch (event) {

case ESP_AVRC_TG_CONNECTION_STATE_EVT: {
Expand All @@ -1287,8 +1285,6 @@ void BluetoothA2DPSink::av_hdl_avrc_tg_evt(uint16_t event, void *p_param)
break;
}

esp_avrc_tg_cb_param_t *rc = (esp_avrc_tg_cb_param_t *)(p_param);

case ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT: {
ESP_LOGI(BT_AV_TAG, "AVRC register event notification: %d, param: 0x%x", rc->reg_ntf.event_id, rc->reg_ntf.event_parameter);
if (rc->reg_ntf.event_id == ESP_AVRC_RN_VOLUME_CHANGE) {
Expand All @@ -1311,7 +1307,6 @@ void BluetoothA2DPSink::av_hdl_avrc_tg_evt(uint16_t event, void *p_param)
}
}


#else

void BluetoothA2DPSink::set_scan_mode_connectable(bool connectable) {
Expand Down
31 changes: 4 additions & 27 deletions src/BluetoothA2DPSink.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,14 @@
// Copyright 2020 Phil Schatzmann
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD

#ifndef __A2DP_SINK_H__
#define __A2DP_SINK_H__
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"
#include "esp_a2dp_api.h"
#include "driver/i2s.h"
#include "esp_avrc_api.h"
#include "BluetoothA2DPCommon.h"
#include <esp_gap_ble_api.h>
#include "esp_spp_api.h"

#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#include "esp32-hal-bt.h"
#endif

#define APP_CORE_TAG "BT_APP_CORE"
#define APP_SIG_WORK_DISPATCH (0x01)

#ifndef AUTOCONNECT_TRY_NUM
Expand All @@ -56,6 +31,9 @@ extern "C" {
#define I2S_COMM_FORMAT_STAND_I2S (I2S_COMM_FORMAT_I2S |I2S_COMM_FORMAT_I2S_MSB)
#endif

#ifndef BT_AV_TAG
#define BT_AV_TAG "BT_AV"
#endif

/* @brief event for handler "bt_av_hdl_stack_up */
enum {
Expand Down Expand Up @@ -284,4 +262,3 @@ class BluetoothA2DPSink {
#endif


#endif
17 changes: 7 additions & 10 deletions src/BluetoothA2DPSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@
#include "BluetoothA2DPSource.h"

#define BT_APP_SIG_WORK_DISPATCH (0x01)
#define BT_APP_CORE_TAG "BT_APP_CORE"
#define BT_APP_SIG_WORK_DISPATCH (0x01)
#define BT_AV_TAG "BT_AV"
#define BT_RC_CT_TAG "RCCT"
#define BT_APP_TAG "BT_API"

#define APP_RC_CT_TL_GET_CAPS (0)
#define APP_RC_CT_TL_RN_VOLUME_CHANGE (1)
Expand Down Expand Up @@ -108,7 +104,7 @@ extern "C" int32_t ccall_get_data_default(uint8_t *data, int32_t len) {


BluetoothA2DPSource::BluetoothA2DPSource() {
ESP_LOGD(APP, "x%x, ", __func__);
ESP_LOGD(APP, "%s, ", __func__);
self_BluetoothA2DPSource = this;
this->ssp_enabled = false;
this->pin_type = ESP_BT_PIN_TYPE_VARIABLE;
Expand All @@ -135,7 +131,7 @@ bool BluetoothA2DPSource::isConnected(){
}

void BluetoothA2DPSource::setPinCode(char *pin_code, esp_bt_pin_type_t pin_type){
ESP_LOGD(APP, "x%x, ", __func__);
ESP_LOGD(APP, "%s, ", __func__);
this->pin_type = pin_type;
this->pin_code_len = strlen(pin_code);
strcpy((char*)this->pin_code, pin_code);
Expand All @@ -147,7 +143,7 @@ void BluetoothA2DPSource::start(char* name, music_data_channels_cb_t callback, b
}

void BluetoothA2DPSource::start(std::vector<char*> names, music_data_channels_cb_t callback, bool is_ssp_enabled) {
ESP_LOGD(APP, "x%x, ", __func__);
ESP_LOGD(APP, "%s, ", __func__);
if (callback!=NULL){
// we use the indicated callback
this->data_stream_channels_callback = callback;
Expand All @@ -163,8 +159,9 @@ void BluetoothA2DPSource::startRaw(char* name, music_data_cb_t callback, bool is
startRaw(names, callback, is_ssp_enabled);
}


void BluetoothA2DPSource::startRaw(std::vector<char*> names, music_data_cb_t callback, bool is_ssp_enabled) {
ESP_LOGD(APP, "x%x, ", __func__);
ESP_LOGD(APP, "%s, ", __func__);
this->ssp_enabled = is_ssp_enabled;
this->bt_names = names;
this->data_stream_callback = callback;
Expand Down Expand Up @@ -878,10 +875,10 @@ int32_t BluetoothA2DPSource::get_data_default(uint8_t *data, int32_t len) {
sound_data_current_pos+=result_len;
if (result_len<=0){
if (sound_data->doLoop()){
ESP_LOGD(BT_APP_TAG, "x%x - end of data: restarting", __func__);
ESP_LOGD(BT_APP_TAG, "%s - end of data: restarting", __func__);
sound_data_current_pos = 0;
} else {
ESP_LOGD(BT_APP_TAG, "x%x - end of data: stopping", __func__);
ESP_LOGD(BT_APP_TAG, "%s - end of data: stopping", __func__);
has_sound_data = false;
}
}
Expand Down
Loading

0 comments on commit a730f60

Please sign in to comment.