Base structure for BLE support on ESP32-S3 boards

This commit is contained in:
Mark Qvist 2024-04-23 00:52:57 +02:00
parent 395e52fd9b
commit 31540410cf
5 changed files with 233 additions and 150 deletions

View File

@ -14,21 +14,30 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#if MCU_VARIANT == MCU_ESP32 #if MCU_VARIANT == MCU_ESP32
#include "BluetoothSerial.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#elif MCU_VARIANT == MCU_NRF52 #elif MCU_VARIANT == MCU_NRF52
#include <bluefruit.h>
#include <math.h>
#endif #endif
#if MCU_VARIANT == MCU_ESP32 #if MCU_VARIANT == MCU_ESP32
BluetoothSerial SerialBT; #if HAS_BLUETOOTH == true
#include "BluetoothSerial.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
BluetoothSerial SerialBT;
#elif HAS_BLE == true
#include "esp_bt_main.h"
#include "esp_bt_device.h"
// TODO: Remove
#define SerialBT Serial
#endif
#elif MCU_VARIANT == MCU_NRF52 #elif MCU_VARIANT == MCU_NRF52
BLEUart SerialBT; #include <bluefruit.h>
BLEDis bledis; #include <math.h>
BLEBas blebas; BLEUart SerialBT;
BLEDis bledis;
BLEBas blebas;
#endif #endif
#define BT_PAIRING_TIMEOUT 35000 #define BT_PAIRING_TIMEOUT 35000
@ -42,114 +51,201 @@ char bt_dh[BT_DEV_HASH_LEN];
char bt_devname[11]; char bt_devname[11];
#if MCU_VARIANT == MCU_ESP32 #if MCU_VARIANT == MCU_ESP32
#if HAS_BLUETOOTH == true
void bt_confirm_pairing(uint32_t numVal) { void bt_confirm_pairing(uint32_t numVal) {
bt_ssp_pin = numVal; bt_ssp_pin = numVal;
kiss_indicate_btpin(); kiss_indicate_btpin();
if (bt_allow_pairing) { if (bt_allow_pairing) {
SerialBT.confirmReply(true); SerialBT.confirmReply(true);
} else { } else {
SerialBT.confirmReply(false); SerialBT.confirmReply(false);
}
} }
}
void bt_stop() { void bt_stop() {
if (bt_state != BT_STATE_OFF) { if (bt_state != BT_STATE_OFF) {
SerialBT.end(); SerialBT.end();
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
}
}
void bt_start() {
if (bt_state == BT_STATE_OFF) {
SerialBT.begin(bt_devname);
bt_state = BT_STATE_ON;
}
}
void bt_enable_pairing() {
if (bt_state == BT_STATE_OFF) bt_start();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
}
void bt_disable_pairing() {
bt_allow_pairing = false; bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
}
}
void bt_start() {
if (bt_state == BT_STATE_OFF) {
SerialBT.begin(bt_devname);
bt_state = BT_STATE_ON;
}
}
void bt_enable_pairing() {
if (bt_state == BT_STATE_OFF) bt_start();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
}
void bt_disable_pairing() {
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_pairing_complete(boolean success) {
if (success) {
bt_disable_pairing();
} else {
bt_ssp_pin = 0; bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
} }
}
void bt_connection_callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param){ void bt_pairing_complete(boolean success) {
if(event == ESP_SPP_SRV_OPEN_EVT) { if (success) {
bt_disable_pairing();
} else {
bt_ssp_pin = 0;
}
}
void bt_connection_callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param){
if(event == ESP_SPP_SRV_OPEN_EVT) {
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
}
if(event == ESP_SPP_CLOSE_EVT ){
bt_state = BT_STATE_ON;
}
}
bool bt_setup_hw() {
if (!bt_ready) {
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
bt_enabled = true;
} else {
bt_enabled = false;
}
if (btStart()) {
if (esp_bluedroid_init() == ESP_OK) {
if (esp_bluedroid_enable() == ESP_OK) {
const uint8_t* bda_ptr = esp_bt_dev_get_address();
char *data = (char*)malloc(BT_DEV_ADDR_LEN+1);
for (int i = 0; i < BT_DEV_ADDR_LEN; i++) {
data[i] = bda_ptr[i];
}
data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE));
unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN);
memcpy(bt_dh, hash, BT_DEV_HASH_LEN);
sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]);
free(data);
SerialBT.enableSSP();
SerialBT.onConfirmRequest(bt_confirm_pairing);
SerialBT.onAuthComplete(bt_pairing_complete);
SerialBT.register_callback(bt_connection_callback);
bt_ready = true;
return true;
} else { return false; }
} else { return false; }
} else { return false; }
} else { return false; }
}
bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
return true;
} else {
return false;
}
}
void update_bt() {
if (bt_allow_pairing && millis()-bt_pairing_started >= BT_PAIRING_TIMEOUT) {
bt_disable_pairing();
}
}
#elif HAS_BLE == true
void bt_stop() {
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
}
}
void bt_disable_pairing() {
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_connect_callback(uint16_t conn_handle) {
bt_state = BT_STATE_CONNECTED; bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED; cable_state = CABLE_STATE_DISCONNECTED;
} }
if(event == ESP_SPP_CLOSE_EVT ){ void bt_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
bt_state = BT_STATE_ON; bt_state = BT_STATE_ON;
} }
}
bool bt_setup_hw() { bool bt_setup_hw() {
if (!bt_ready) { if (!bt_ready) {
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) { if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
bt_enabled = true; bt_enabled = true;
} else { } else {
bt_enabled = false; bt_enabled = false;
} }
if (btStart()) { if (btStart()) {
if (esp_bluedroid_init() == ESP_OK) { if (esp_bluedroid_init() == ESP_OK) {
if (esp_bluedroid_enable() == ESP_OK) { if (esp_bluedroid_enable() == ESP_OK) {
const uint8_t* bda_ptr = esp_bt_dev_get_address(); const uint8_t* bda_ptr = esp_bt_dev_get_address();
char *data = (char*)malloc(BT_DEV_ADDR_LEN+1); char *data = (char*)malloc(BT_DEV_ADDR_LEN+1);
for (int i = 0; i < BT_DEV_ADDR_LEN; i++) { for (int i = 0; i < BT_DEV_ADDR_LEN; i++) {
data[i] = bda_ptr[i]; data[i] = bda_ptr[i];
} }
data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE)); data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE));
unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN); unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN);
memcpy(bt_dh, hash, BT_DEV_HASH_LEN); memcpy(bt_dh, hash, BT_DEV_HASH_LEN);
sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]); sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]);
free(data); free(data);
SerialBT.enableSSP(); // TODO: Implement GAP & GATT for RNode comms over BLE
SerialBT.onConfirmRequest(bt_confirm_pairing);
SerialBT.onAuthComplete(bt_pairing_complete);
SerialBT.register_callback(bt_connection_callback);
bt_ready = true; bt_ready = true;
return true; return true;
} else { return false; }
} else { return false; } } else { return false; }
} else { return false; } } else { return false; }
} else { return false; } } else { return false; }
} else { return false; }
}
bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
return true;
} else {
return false;
}
}
void update_bt() {
if (bt_allow_pairing && millis()-bt_pairing_started >= BT_PAIRING_TIMEOUT) {
bt_disable_pairing();
} }
}
void bt_start() {
if (bt_state == BT_STATE_OFF) {
bt_state = BT_STATE_ON;
// TODO: Implement
}
}
bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
return true;
} else {
return false;
}
}
void bt_enable_pairing() {
if (bt_state == BT_STATE_OFF) bt_start();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
}
void update_bt() {
if (bt_allow_pairing && millis()-bt_pairing_started >= BT_PAIRING_TIMEOUT) {
bt_disable_pairing();
}
}
#endif
#elif MCU_VARIANT == MCU_NRF52 #elif MCU_VARIANT == MCU_NRF52
uint8_t eeprom_read(uint32_t mapped_addr); uint8_t eeprom_read(uint32_t mapped_addr);
@ -244,8 +340,8 @@ bool bt_setup_hw() {
void bt_start() { void bt_start() {
if (bt_state == BT_STATE_OFF) { if (bt_state == BT_STATE_OFF) {
Bluefruit.setName(bt_devname); Bluefruit.setName(bt_devname);
bledis.setManufacturer("Adafruit Industries"); bledis.setManufacturer(BLE_MANUFACTURER);
bledis.setModel("Bluefruit Feather52"); bledis.setModel(BLE_MODEL);
// start device information service // start device information service
bledis.begin(); bledis.begin();

View File

@ -18,14 +18,14 @@
#ifndef BOARDS_H #ifndef BOARDS_H
#define BOARDS_H #define BOARDS_H
#define PLATFORM_AVR 0x90 #define PLATFORM_AVR 0x90
#define PLATFORM_ESP32 0x80 #define PLATFORM_ESP32 0x80
#define PLATFORM_NRF52 0x70 #define PLATFORM_NRF52 0x70
#define MCU_1284P 0x91 #define MCU_1284P 0x91
#define MCU_2560 0x92 #define MCU_2560 0x92
#define MCU_ESP32 0x81 #define MCU_ESP32 0x81
#define MCU_NRF52 0x71 #define MCU_NRF52 0x71
#define BOARD_RNODE 0x31 #define BOARD_RNODE 0x31
#define BOARD_HMBRW 0x32 #define BOARD_HMBRW 0x32
@ -252,14 +252,11 @@
#elif BOARD_MODEL == BOARD_HELTEC32_V3 #elif BOARD_MODEL == BOARD_HELTEC32_V3
#define IS_ESP32S3 true #define IS_ESP32S3 true
#define HAS_DISPLAY true #define HAS_DISPLAY true
//ESP32-S3 no bluetooth classic
#define HAS_BLUETOOTH false #define HAS_BLUETOOTH false
// TODO BLE #define HAS_BLE true
#define HAS_BLE false
// Cannot run wifi and BLE at same time? // Cannot run wifi and BLE at same time?
#define HAS_CONSOLE false #define HAS_CONSOLE false
#define HAS_EEPROM true #define HAS_EEPROM true
// Only one LED on pin 35
#if defined(EXTERNAL_LEDS) #if defined(EXTERNAL_LEDS)
const int pin_led_rx = 13; const int pin_led_rx = 13;
const int pin_led_tx = 14; const int pin_led_tx = 14;
@ -283,8 +280,6 @@
const int pin_miso = 11; const int pin_miso = 11;
const int pin_sclk = 9; const int pin_sclk = 9;
#elif BOARD_MODEL == BOARD_RNODE_NG_20 #elif BOARD_MODEL == BOARD_RNODE_NG_20
#define HAS_DISPLAY true #define HAS_DISPLAY true
#define HAS_BLUETOOTH true #define HAS_BLUETOOTH true
@ -341,9 +336,9 @@
#define HAS_TCXO true #define HAS_TCXO true
#define HAS_DISPLAY true #define HAS_DISPLAY true
#define HAS_CONSOLE false
#define HAS_BLUETOOTH false
#define HAS_BLE true #define HAS_BLE true
#define HAS_BLUETOOTH false // TODO: Implement
#define HAS_CONSOLE false // TODO: Implement
#define HAS_PMU true #define HAS_PMU true
#define HAS_NP false #define HAS_NP false
#define HAS_SD false #define HAS_SD false
@ -384,8 +379,9 @@
#elif MCU_VARIANT == MCU_NRF52 #elif MCU_VARIANT == MCU_NRF52
#if BOARD_MODEL == BOARD_RAK4630 #if BOARD_MODEL == BOARD_RAK4630
#define HAS_EEPROM false #define HAS_EEPROM false
#define HAS_DISPLAY false // set for debugging #define HAS_DISPLAY true
#define HAS_BLUETOOTH true #define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_CONSOLE false #define HAS_CONSOLE false
#define HAS_PMU false #define HAS_PMU false
#define HAS_NP false #define HAS_NP false
@ -398,8 +394,10 @@
#define CONFIG_QUEUE_MAX_LENGTH 200 #define CONFIG_QUEUE_MAX_LENGTH 200
#define EEPROM_SIZE 200 #define EEPROM_SIZE 200
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
#define BLE_MANUFACTURER "RAK Wireless"
#define BLE_MODEL "RAK4640"
// following pins are for the sx1262 // Following pins are for the sx1262
const int pin_rxen = 37; const int pin_rxen = 37;
const int pin_reset = 38; const int pin_reset = 38;
const int pin_cs = 42; const int pin_cs = 42;

View File

@ -154,7 +154,7 @@ bool device_init() {
mbedtls_md_init(&ctx); mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0); mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
mbedtls_md_starts(&ctx); mbedtls_md_starts(&ctx);
#if HAS_BLUETOOTH == true #if HAS_BLUETOOTH == true || HAS_BLE == true
mbedtls_md_update(&ctx, dev_bt_mac, BT_DEV_ADDR_LEN); mbedtls_md_update(&ctx, dev_bt_mac, BT_DEV_ADDR_LEN);
#else #else
// TODO: Get from BLE stack instead // TODO: Get from BLE stack instead

View File

@ -33,7 +33,7 @@ volatile uint16_t queued_bytes = 0;
volatile uint16_t queue_cursor = 0; volatile uint16_t queue_cursor = 0;
volatile uint16_t current_packet_start = 0; volatile uint16_t current_packet_start = 0;
volatile bool serial_buffering = false; volatile bool serial_buffering = false;
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
bool bt_init_ran = false; bool bt_init_ran = false;
#endif #endif
@ -160,12 +160,9 @@ void setup() {
pmu_ready = init_pmu(); pmu_ready = init_pmu();
#endif #endif
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
bt_init(); bt_init();
bt_init_ran = true; bt_init_ran = true;
#elif HAS_BLE
// TODO: Implement BLE on ESP32S3 instead of this hack
bt_ready = true;
#endif #endif
if (console_active) { if (console_active) {
@ -910,7 +907,7 @@ void serialCallback(uint8_t sbyte) {
} }
#endif #endif
} else if (command == CMD_BT_CTRL) { } else if (command == CMD_BT_CTRL) {
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE
if (sbyte == 0x00) { if (sbyte == 0x00) {
bt_stop(); bt_stop();
bt_conf_save(false); bt_conf_save(false);
@ -1111,15 +1108,7 @@ void validate_status() {
if (device_init()) { if (device_init()) {
hw_ready = true; hw_ready = true;
} else { } else {
#if !HAS_BLUETOOTH && !HAS_BLE hw_ready = false;
// Without bluetooth, bt_ready and device_init_done
// are not set
// and neither is hw_ready (see device_init())
hw_ready = true;
device_init_done = true;
#else
hw_ready = false;
#endif
} }
#else #else
hw_ready = true; hw_ready = true;
@ -1297,7 +1286,7 @@ void loop() {
if (pmu_ready) update_pmu(); if (pmu_ready) update_pmu();
#endif #endif
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
if (!console_active && bt_ready) update_bt(); if (!console_active && bt_ready) update_bt();
#endif #endif
} }
@ -1329,7 +1318,7 @@ void buffer_serial() {
uint8_t c = 0; uint8_t c = 0;
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
while ( while (
c < MAX_CYCLES && c < MAX_CYCLES &&
( (bt_state != BT_STATE_CONNECTED && Serial.available()) || (bt_state == BT_STATE_CONNECTED && SerialBT.available()) ) ( (bt_state != BT_STATE_CONNECTED && Serial.available()) || (bt_state == BT_STATE_CONNECTED && SerialBT.available()) )
@ -1344,7 +1333,7 @@ void buffer_serial() {
if (!fifo_isfull_locked(&serialFIFO)) { if (!fifo_isfull_locked(&serialFIFO)) {
fifo_push_locked(&serialFIFO, Serial.read()); fifo_push_locked(&serialFIFO, Serial.read());
} }
#elif HAS_BLUETOOTH #elif HAS_BLUETOOTH || HAS_BLE == true
if (bt_state == BT_STATE_CONNECTED) { if (bt_state == BT_STATE_CONNECTED) {
if (!fifo_isfull(&serialFIFO)) { if (!fifo_isfull(&serialFIFO)) {
fifo_push(&serialFIFO, SerialBT.read()); fifo_push(&serialFIFO, SerialBT.read());

View File

@ -47,7 +47,7 @@ sx128x *LoRa = &sx128x_modem;
#include "Display.h" #include "Display.h"
#endif #endif
#if HAS_BLUETOOTH == true #if HAS_BLUETOOTH == true || HAS_BLE == true
void kiss_indicate_btpin(); void kiss_indicate_btpin();
#include "Bluetooth.h" #include "Bluetooth.h"
#endif #endif
@ -629,7 +629,7 @@ int8_t led_standby_direction = 0;
#endif #endif
void serial_write(uint8_t byte) { void serial_write(uint8_t byte) {
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
if (bt_state != BT_STATE_CONNECTED) { if (bt_state != BT_STATE_CONNECTED) {
Serial.write(byte); Serial.write(byte);
} else { } else {
@ -829,7 +829,7 @@ void kiss_indicate_battery() {
} }
void kiss_indicate_btpin() { void kiss_indicate_btpin() {
#if HAS_BLUETOOTH #if HAS_BLUETOOTH || HAS_BLE == true
serial_write(FEND); serial_write(FEND);
serial_write(CMD_BT_PIN); serial_write(CMD_BT_PIN);
escaped_serial_write(bt_ssp_pin>>24); escaped_serial_write(bt_ssp_pin>>24);