Compare commits

...

32 Commits
1.81 ... master

Author SHA1 Message Date
Mark Qvist
23c580d0df Cleanup 2025-04-15 16:45:24 +02:00
Mark Qvist
dd35c067b4 Updated readme 2025-04-15 16:28:02 +02:00
Mark Qvist
1ec84743f4 Cleanup 2025-04-15 16:27:01 +02:00
Mark Qvist
e157f82b8e Cleanup 2025-04-15 16:26:16 +02:00
Mark Qvist
d80f866418 Cleanup 2025-04-13 18:46:20 +02:00
Mark Qvist
c56df7e8b5 Updated version 2025-04-13 17:54:17 +02:00
Mark Qvist
e0fc80f2cb Cleanup 2025-04-13 17:32:29 +02:00
Mark Qvist
9ef504392b Improved ESP32 BLE pairing. Added unpair command. 2025-04-13 16:56:45 +02:00
Mark Qvist
e1a2cc02bb Improved nRF BLE pairing 2025-04-13 14:47:31 +02:00
Mark Qvist
0a95f6f107 Added nRF hardware RNG 2025-04-13 14:45:31 +02:00
Mark Qvist
16dedc72c2 BLE improvements 2025-04-13 02:23:01 +02:00
Mark Qvist
9d2da569c9 Cleanup 2025-04-13 01:28:19 +02:00
Mark Qvist
4ba0965931 Updated readme 2025-04-13 00:23:11 +02:00
Mark Qvist
e291f3bcae Added XIAO ESP32S3 to release 2025-04-13 00:21:43 +02:00
Mark Qvist
7d868b4db6 Support for XIAO ESP32S3 2025-04-13 00:11:21 +02:00
Mark Qvist
6ae99dccb0 Merge branch 'master' of github.com:markqvist/RNode_Firmware 2025-04-12 21:07:27 +02:00
markqvist
698c6faa3f
Merge pull request #106 from cobraPA/seeed_esp32s3_1
Seeed esp32s3 with Wio-SX1262 board support
2025-04-12 21:07:15 +02:00
Mark Qvist
f48e99a033 Re-enable BLE battery service 2025-04-12 21:04:32 +02:00
Mark Qvist
e8e6e2bcbf Merge branch 'master' of github.com:markqvist/RNode_Firmware 2025-04-12 21:03:27 +02:00
markqvist
b16772cf52
Merge pull request #103 from jacobeva/nrf52-ble-revamp
Revamp NRF52 BLE pairing to resemble ESP32
2025-04-12 21:03:13 +02:00
markqvist
6e38a1317b
Merge pull request #104 from jacobeva/nrf52-ble-fix
Guard against BT power cycle object duplication bug
2025-04-12 21:02:01 +02:00
Mark Qvist
33dedb202f Cleanup 2025-04-12 20:59:00 +02:00
Mark Qvist
3df940c791 Fixed typo 2025-04-10 13:02:10 +02:00
Kevin Brosius
cbedd72993 Seeed ESP32S3 - enable button sleep, stopRadio at sleep
to sleep sx1262 also.
2025-02-23 18:52:17 -05:00
Kevin Brosius
c3fe3713b0 Seeed ESP32S3 - Enable user button, tied to yellow LED on
ESP32S3 board.  Can be shared, but configure as button
input only for now.  Top LED for TX indication.
2025-02-23 16:57:36 -05:00
Kevin Brosius
bc97e513e8 Initial support for Seeed ESP32S3 with Wio-SX1262
Work in progress
Status: Boots, display works on Xiao espansion base,
radio is recognized
Todo:
  PMU
  Firmware hash fails even if generated and then written
  Radio testing
  Buttons / LEDs
  other?
2025-02-23 06:52:27 -05:00
jacob.eva
149dff2ee2
Guard against BT power cycle object duplication bug 2025-01-30 16:54:34 +00:00
jacob.eva
245434b9fd
Revamp NRF52 BLE pairing to resemble ESP32 2025-01-30 16:42:56 +00:00
Mark Qvist
de35a9dda0 Updated readme 2025-01-24 13:21:24 +01:00
Mark Qvist
e230c73ee0 Updated console build 2025-01-19 22:14:15 +01:00
Mark Qvist
6bbcaa0ba9 Report battery percentage over BLE battery service 2025-01-18 15:20:58 +01:00
Mark Qvist
9473b9df82 Updated readme 2025-01-18 13:12:02 +01:00
16 changed files with 350 additions and 123 deletions

View File

@ -96,6 +96,17 @@ void BLESerial::flush() {
}
}
void BLESerial::disconnect() {
if (ble_server->getConnectedCount() > 0) {
uint16_t conn_id = ble_server->getConnId();
// Serial.printf("Have connected: %d\n", conn_id);
ble_server->disconnect(conn_id);
// Serial.println("Disconnected");
} else {
// Serial.println("No connected");
}
}
void BLESerial::begin(const char *name) {
ConnectedDeviceCount = 0;
BLEDevice::init(name);
@ -110,7 +121,10 @@ void BLESerial::begin(const char *name) {
BLEDevice::setSecurityCallbacks(this);
SetupSerialService();
this->startAdvertising();
}
void BLESerial::startAdvertising() {
ble_adv = BLEDevice::getAdvertising();
ble_adv->addServiceUUID(BLE_SERIAL_SERVICE_UUID);
ble_adv->setMinPreferred(0x20);
@ -119,6 +133,11 @@ void BLESerial::begin(const char *name) {
ble_adv->start();
}
void BLESerial::stopAdvertising() {
ble_adv = BLEDevice::getAdvertising();
ble_adv->stop();
}
void BLESerial::end() { BLEDevice::deinit(); }
void BLESerial::onWrite(BLECharacteristic *characteristic) {

View File

@ -78,6 +78,9 @@ public:
void begin(const char *name);
void end();
void disconnect();
void startAdvertising();
void stopAdvertising();
void onWrite(BLECharacteristic *characteristic);
int available();
int peek();

View File

@ -38,6 +38,7 @@
BLEUart SerialBT(BLE_RX_BUF);
BLEDis bledis;
BLEBas blebas;
bool SerialBT_init = false;
#endif
#define BT_PAIRING_TIMEOUT 35000
@ -169,31 +170,42 @@ char bt_devname[11];
}
#elif HAS_BLE == true
bool bt_setup_hw(); void bt_security_setup();
BLESecurity *ble_security = new BLESecurity();
bool ble_authenticated = false;
uint32_t pairing_pin = 0;
void bt_flush() { if (bt_state == BT_STATE_CONNECTED) { SerialBT.flush(); } }
void bt_disable_pairing() {
void bt_start() {
// Serial.println("BT start");
display_unblank();
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
if (bt_state == BT_STATE_OFF) {
bt_state = BT_STATE_ON;
SerialBT.begin(bt_devname);
SerialBT.setTimeout(10);
}
}
void bt_passkey_notify_callback(uint32_t passkey) {
// Serial.printf("Got passkey notification: %d\n", passkey);
bt_ssp_pin = passkey;
bt_state = BT_STATE_PAIRING;
bt_allow_pairing = true;
bt_pairing_started = millis();
kiss_indicate_btpin();
void bt_stop() {
// Serial.println("BT stop");
display_unblank();
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
SerialBT.end();
}
}
bool bt_confirm_pin_callback(uint32_t pin) {
// Serial.printf("Confirm PIN callback: %d\n", pin);
return true;
bool bt_init() {
// Serial.println("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_debond_all() {
@ -205,6 +217,44 @@ char bt_devname[11];
free(dev_list);
}
void bt_enable_pairing() {
// Serial.println("BT enable pairing");
display_unblank();
if (bt_state == BT_STATE_OFF) bt_start();
bt_security_setup();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
bt_ssp_pin = pairing_pin;
}
void bt_disable_pairing() {
// Serial.println("BT disable pairing");
display_unblank();
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_passkey_notify_callback(uint32_t passkey) {
// Serial.printf("Got passkey notification: %d\n", passkey);
if (bt_allow_pairing) {
bt_ssp_pin = passkey;
bt_pairing_started = millis();
kiss_indicate_btpin();
} else {
// Serial.println("Pairing not allowed, re-init");
SerialBT.disconnect();
}
}
bool bt_confirm_pin_callback(uint32_t pin) {
// Serial.printf("Confirm PIN callback: %d\n", pin);
return true;
}
void bt_update_passkey() {
// Serial.println("Updating passkey");
pairing_pin = random(899999)+100000;
@ -221,31 +271,6 @@ char bt_devname[11];
return ble_authenticated;
}
void bt_security_setup() {
uint32_t passkey = bt_passkey_callback();
// Serial.printf("Executing BT security setup, passkey is %d\n", passkey);
uint8_t key_size = 16;
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND;
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE;
uint8_t oob_support = ESP_BLE_OOB_DISABLE;
esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
}
bool bt_security_request_callback() {
if (bt_allow_pairing) {
// Serial.println("Accepting security request");
@ -260,11 +285,15 @@ char bt_devname[11];
if (auth_result.success == true) {
// Serial.println("Authentication success");
ble_authenticated = true;
bt_state = BT_STATE_CONNECTED;
if (bt_state == BT_STATE_PAIRING) {
// Serial.println("Pairing complete, disconnecting");
delay(2000); SerialBT.disconnect();
} else { bt_state = BT_STATE_CONNECTED; }
} else {
// Serial.println("Authentication fail");
ble_authenticated = false;
bt_state = BT_STATE_ON;
bt_update_passkey();
bt_security_setup();
}
bt_allow_pairing = false;
@ -272,16 +301,16 @@ char bt_devname[11];
}
void bt_connect_callback(BLEServer *server) {
// uint16_t conn_id = server->getConnId();
uint16_t conn_id = server->getConnId();
// Serial.printf("Connected: %d\n", conn_id);
display_unblank();
ble_authenticated = false;
bt_state = BT_STATE_CONNECTED;
if (bt_state != BT_STATE_PAIRING) { bt_state = BT_STATE_CONNECTED; }
cable_state = CABLE_STATE_DISCONNECTED;
}
void bt_disconnect_callback(BLEServer *server) {
// uint16_t conn_id = server->getConnId();
uint16_t conn_id = server->getConnId();
// Serial.printf("Disconnected: %d\n", conn_id);
display_unblank();
ble_authenticated = false;
@ -289,6 +318,7 @@ char bt_devname[11];
}
bool bt_setup_hw() {
// Serial.println("BT setup hw");
if (!bt_ready) {
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
bt_enabled = true;
@ -320,45 +350,30 @@ char bt_devname[11];
} else { return false; }
}
void bt_start() {
display_unblank();
if (bt_state == BT_STATE_OFF) {
bt_state = BT_STATE_ON;
SerialBT.begin(bt_devname);
SerialBT.setTimeout(10);
}
}
void bt_security_setup() {
// Serial.println("Executing BT security setup");
if (pairing_pin == 0) { bt_update_passkey(); }
uint32_t passkey = pairing_pin;
// Serial.printf("Passkey is %d\n", passkey);
void bt_stop() {
display_unblank();
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
SerialBT.end();
}
}
uint8_t key_size = 16;
uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
return true;
} else {
return false;
}
}
esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND;
uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE;
uint8_t oob_support = ESP_BLE_OOB_DISABLE;
void bt_enable_pairing() {
display_unblank();
if (bt_state == BT_STATE_OFF) bt_start();
esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT;
bt_security_setup();
//bt_debond_all();
//bt_update_passkey();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
}
void update_bt() {
@ -374,9 +389,12 @@ char bt_devname[11];
#endif
#elif MCU_VARIANT == MCU_NRF52
uint32_t pairing_pin = 0;
uint8_t eeprom_read(uint32_t mapped_addr);
void bt_stop() {
// Serial.println("BT Stop");
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
@ -386,16 +404,19 @@ char bt_devname[11];
void bt_flush() { if (bt_state == BT_STATE_CONNECTED) { SerialBT.flushTXD(); } }
void bt_disable_pairing() {
// Serial.println("BT Disable pairing");
bt_allow_pairing = false;
pairing_pin = 0;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_pairing_complete(uint16_t conn_handle, uint8_t auth_status) {
// Serial.println("BT pairing complete");
BLEConnection* connection = Bluefruit.Connection(conn_handle);
if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
BLEConnection* connection = Bluefruit.Connection(conn_handle);
ble_gap_conn_sec_mode_t security = connection->getSecureMode();
// Serial.println("Bonding success");
// On the NRF52 it is not possible with the Arduino library to reject
// requests from devices with no IO capabilities, which would allow
@ -412,26 +433,26 @@ char bt_devname[11];
// Requires investigation.
if (security.sm == 1 && security.lv >= 3) {
// Serial.println("Auth level success");
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
connection->disconnect();
bt_disable_pairing();
} else {
if (connection->bonded()) {
connection->removeBondKey();
}
// Serial.println("Auth level failure, debonding");
if (connection->bonded()) { connection->removeBondKey(); }
connection->disconnect();
bt_disable_pairing();
}
} else {
bt_ssp_pin = 0;
// Serial.println("Bonding failure");
connection->disconnect();
bt_disable_pairing();
}
}
bool bt_passkey_callback(uint16_t conn_handle, uint8_t const passkey[6], bool match_request) {
for (int i = 0; i < 6; i++) {
// multiply by tens however many times needed to make numbers appear in order
bt_ssp_pin += ((int)passkey[i] - 48) * pow(10, 5-i);
}
kiss_indicate_btpin();
// Serial.println("Passkey callback");
if (bt_allow_pairing) {
return true;
}
@ -439,6 +460,7 @@ char bt_devname[11];
}
void bt_connect_callback(uint16_t conn_handle) {
// Serial.println("Connect callback");
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
@ -449,12 +471,26 @@ char bt_devname[11];
}
void bt_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
// Serial.println("Disconnect callback");
if (reason != BLE_GAP_SEC_STATUS_SUCCESS) {
bt_state = BT_STATE_ON;
}
}
void bt_update_passkey() {
// Serial.println("Update passkey");
pairing_pin = random(899999)+100000;
bt_ssp_pin = pairing_pin;
}
uint32_t bt_get_passkey() {
// Serial.println("API passkey request");
if (pairing_pin == 0) { bt_update_passkey(); }
return pairing_pin;
}
bool bt_setup_hw() {
// Serial.println("Setup HW");
if (!bt_ready) {
#if HAS_EEPROM
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
@ -468,6 +504,10 @@ char bt_devname[11];
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.autoConnLed(false);
if (Bluefruit.begin()) {
uint32_t pin = bt_get_passkey();
char pin_char[6];
sprintf(pin_char,"%lu", pin);
Bluefruit.setTxPower(8); // Check bluefruit.h for supported values
Bluefruit.Security.setIOCaps(true, false, false); // display, yes; yes / no, no; keyboard, no
// This device is indeed capable of yes / no through the pairing mode
@ -477,6 +517,7 @@ char bt_devname[11];
Bluefruit.Security.setMITM(true);
Bluefruit.Security.setPairPasskeyCallback(bt_passkey_callback);
Bluefruit.Security.setSecuredCallback(bt_connect_callback);
Bluefruit.Security.setPIN(pin_char);
Bluefruit.Periph.setDisconnectCallback(bt_disconnect_callback);
Bluefruit.Security.setPairCompleteCallback(bt_pairing_complete);
Bluefruit.Periph.setConnInterval(6, 12); // 7.5 - 15 ms
@ -504,20 +545,24 @@ char bt_devname[11];
}
void bt_start() {
// Serial.println("BT Start");
if (bt_state == BT_STATE_OFF) {
Bluefruit.setName(bt_devname);
bledis.setManufacturer(BLE_MANUFACTURER);
bledis.setModel(BLE_MODEL);
// start device information service
bledis.begin();
SerialBT.bufferTXD(true); // enable buffering
SerialBT.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM); // enable encryption for BLE serial
SerialBT.begin();
blebas.begin();
// Guard to ensure SerialBT service is not duplicated through BT being power cycled
if (!SerialBT_init) {
SerialBT.bufferTXD(true); // enable buffering
SerialBT.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM); // enable encryption for BLE serial
SerialBT.begin();
SerialBT_init = true;
}
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
@ -535,6 +580,7 @@ char bt_devname[11];
}
bool bt_init() {
// Serial.println("BT init");
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
@ -545,12 +591,22 @@ char bt_devname[11];
}
void bt_enable_pairing() {
// Serial.println("BT enable pairing");
if (bt_state == BT_STATE_OFF) bt_start();
uint32_t pin = bt_get_passkey();
char pin_char[6];
sprintf(pin_char,"%lu", pin);
Bluefruit.Security.setPIN(pin_char);
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
kiss_indicate_btpin();
}
void bt_debond_all() { }
void update_bt() {
if (bt_allow_pairing && millis()-bt_pairing_started >= BT_PAIRING_TIMEOUT) {
bt_disable_pairing();

View File

@ -65,6 +65,11 @@
#define MODEL_DB 0xDB // LilyGO T-Beam Supreme, 433 MHz
#define MODEL_DC 0xDC // LilyGO T-Beam Supreme, 868 MHz
#define PRODUCT_XIAO_S3 0xEB
#define BOARD_XIAO_S3 0x3E
#define MODEL_DE 0xDE // Xiao ESP32S3 with Wio-SX1262 module, 433 MHz
#define MODEL_DD 0xDD // Xiao ESP32S3 with Wio-SX1262 module, 868 MHz
#define PRODUCT_T32_10 0xB2
#define BOARD_LORA32_V1_0 0x39
#define MODEL_BA 0xBA // LilyGO T3 v1.0, 433 MHz
@ -593,6 +598,46 @@
#endif
#endif
#elif BOARD_MODEL == BOARD_XIAO_S3
#define IS_ESP32S3 true
#define MODEM SX1262
#define DIO2_AS_RF_SWITCH true
#define HAS_BUSY true
#define HAS_TCXO true
#define HAS_DISPLAY false
#define HAS_CONSOLE true
#define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_NP false
#define HAS_SD false
#define HAS_EEPROM true
#define HAS_INPUT true
#define HAS_SLEEP true
#define PIN_WAKEUP GPIO_NUM_21
#define WAKEUP_LEVEL 0
const int pin_btn_usr1 = 21;
const int pin_cs = 41;
const int pin_reset = 42;
const int pin_sclk = 7;
const int pin_mosi = 9;
const int pin_miso = 8;
const int pin_tcxo_enable = -1;
const int pin_dio = 39;
const int pin_busy = 40;
#if HAS_NP == false
#if defined(EXTERNAL_LEDS)
const int pin_led_rx = 48;
const int pin_led_tx = 48;
#else
const int pin_led_rx = 48;
const int pin_led_tx = 48;
#endif
#endif
#else
#error An unsupported ESP32 board was selected. Cannot compile RNode firmware.
#endif

View File

@ -20,7 +20,7 @@
#define CONFIG_H
#define MAJ_VERS 0x01
#define MIN_VERS 0x51
#define MIN_VERS 0x52
#define MODE_HOST 0x11
#define MODE_TNC 0x12

View File

@ -4,9 +4,9 @@ import sys
import shutil
packages = {
"rns": "rns-0.9.0-py3-none-any.whl",
"rns": "rns-0.9.1-py3-none-any.whl",
"nomadnet": "nomadnet-0.5.7-py3-none-any.whl",
"lxmf": "lxmf-0.5.9-py3-none-any.whl",
"lxmf": "lxmf-0.6.0-py3-none-any.whl",
"rnsh": "rnsh-0.1.5-py3-none-any.whl",
}

View File

@ -85,6 +85,12 @@
#define SCL_OLED 18
#define SDA_OLED 17
#define DISP_CUSTOM_ADDR false
#elif BOARD_MODEL == BOARD_XIAO_S3
#define DISP_RST -1
#define DISP_ADDR 0x3C
#define SCL_OLED 6
#define SDA_OLED 5
#define DISP_CUSTOM_ADDR true
#else
#define DISP_RST -1
#define DISP_ADDR 0x3C
@ -278,6 +284,8 @@ bool display_init() {
#endif
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
Wire.begin(SDA_OLED, SCL_OLED);
#elif BOARD_MODEL == BOARD_XIAO_S3
Wire.begin(SDA_OLED, SCL_OLED);
#endif
#if HAS_EEPROM
@ -609,7 +617,7 @@ void draw_quality_bars(int px, int py) {
}
}
#if MODE == SX1280
#if MODEM == SX1280
#define S_RSSI_MIN -105.0
#define S_RSSI_MAX -65.0
#else
@ -655,7 +663,7 @@ void draw_waterfall(int px, int py) {
if (rssi_val > WF_RSSI_MAX) rssi_val = WF_RSSI_MAX;
int rssi_normalised = ((rssi_val - WF_RSSI_MIN)*(1.0/WF_RSSI_SPAN))*WF_PIXEL_WIDTH;
if (display_tx) {
for (uint8_t i; i < WF_TX_SIZE; i++) {
for (uint8_t i = 0; i < WF_TX_SIZE; i++) {
waterfall[waterfall_head++] = -1;
if (waterfall_head >= WATERFALL_SIZE) waterfall_head = 0;
}

View File

@ -61,6 +61,7 @@
#define CMD_DISP_RCND 0x68
#define CMD_NP_INT 0x65
#define CMD_BT_CTRL 0x46
#define CMD_BT_UNPAIR 0x70
#define CMD_BT_PIN 0x62
#define CMD_DIS_IA 0x69
@ -82,6 +83,11 @@
#define CMD_RESET 0x55
#define CMD_RESET_BYTE 0xF8
#define CMD_LOG 0x80
#define CMD_TIME 0x81
#define CMD_MUX_CHAIN 0x82
#define CMD_MUX_DSCVR 0x83
#define DETECT_REQ 0x73
#define DETECT_RESP 0x46

View File

@ -16,6 +16,9 @@
# Version 2.0.17 of the Arduino ESP core is based on ESP-IDF v4.4.7
ARDUINO_ESP_CORE_VER = 2.0.17
# Version 3.2.0 of the Arduino ESP core is based on ESP-IDF v5.4.1
# ARDUINO_ESP_CORE_VER = 3.2.0
all: release
clean:
@ -143,6 +146,9 @@ firmware-heltec_t114:
firmware-techo:
arduino-cli compile --log --fqbn adafruit:nrf52:pca10056 -e --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x44\""
firmware-xiao_s3:
arduino-cli compile --log --fqbn "esp32:esp32:XIAO_ESP32S3" -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3E\""
upload:
arduino-cli upload -p /dev/ttyUSB0 --fqbn unsignedio:avr:rnode
@ -192,11 +198,11 @@ upload-heltec32_v2:
python ./Release/esptool/esptool.py --chip esp32 --port /dev/ttyUSB1 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin
upload-heltec32_v3:
arduino-cli upload -p /dev/ttyUSB1 --fqbn esp32:esp32:heltec_wifi_lora_32_V3
arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:heltec_wifi_lora_32_V3
@sleep 1
rnodeconf /dev/ttyUSB1 --firmware-hash $$(./partition_hashes ./build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.bin)
rnodeconf /dev/ttyUSB0 --firmware-hash $$(./partition_hashes ./build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.bin)
@sleep 3
python ./Release/esptool/esptool.py --chip esp32-s3 --port /dev/ttyUSB1 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin
python ./Release/esptool/esptool.py --chip esp32-s3 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin
upload-tdeck:
arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:esp32s3
@ -255,9 +261,16 @@ upload-techo:
@sleep 6
rnodeconf /dev/ttyACM0 --firmware-hash $$(./partition_hashes from_device /dev/ttyACM0)
upload-xiao_s3:
arduino-cli upload -p /dev/ttyACM0 --fqbn esp32:esp32:XIAO_ESP32S3
@sleep 1
rnodeconf /dev/ttyACM0 --firmware-hash $$(./partition_hashes ./build/esp32.esp32.XIAO_ESP32S3/RNode_Firmware.ino.bin)
@sleep 3
python ./Release/esptool/esptool.py --chip esp32s3 --port /dev/ttyACM0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000 ./Release/console_image.bin
release: release-all
release-all: console-site spiffs-image release-tbeam release-tbeam_sx1262 release-lora32_v10 release-lora32_v20 release-lora32_v21 release-lora32_v10_extled release-lora32_v20_extled release-lora32_v21_extled release-lora32_v21_tcxo release-featheresp32 release-genericesp32 release-heltec32_v2 release-heltec32_v3 release-heltec32_v2_extled release-heltec_t114 release-techo release-rnode_ng_20 release-rnode_ng_21 release-t3s3 release-t3s3_sx127x release-t3s3_sx1280_pa release-tdeck release-tbeam_supreme release-rak4631 release-hashes
release-all: release-tbeam release-tbeam_sx1262 release-lora32_v10 release-lora32_v20 release-lora32_v21 release-lora32_v10_extled release-lora32_v20_extled release-lora32_v21_extled release-lora32_v21_tcxo release-featheresp32 release-genericesp32 release-heltec32_v2 release-heltec32_v3 release-heltec32_v2_extled release-heltec_t114 release-techo release-rnode_ng_20 release-rnode_ng_21 release-t3s3 release-t3s3_sx127x release-t3s3_sx1280_pa release-tdeck release-tbeam_supreme release-rak4631 release-xiao_s3 release-hashes
release-hashes:
python ./release_hashes.py > ./Release/release.json
@ -357,7 +370,7 @@ release-heltec32_v2: check_bt_buffers
zip --junk-paths ./Release/rnode_firmware_heltec32v2.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_heltec32v2.boot_app0 build/rnode_firmware_heltec32v2.bin build/rnode_firmware_heltec32v2.bootloader build/rnode_firmware_heltec32v2.partitions
rm -r build
release-heltec32_v3:
release-heltec32_v3: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V3 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3A\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_heltec32v3.boot_app0
cp build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.bin build/rnode_firmware_heltec32v3.bin
@ -475,3 +488,12 @@ release-techo:
arduino-cli compile --log --fqbn adafruit:nrf52:pca10056 -e --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x44\""
cp build/adafruit.nrf52.pca10056/RNode_Firmware.ino.hex build/rnode_firmware_techo.hex
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/rnode_firmware_techo.hex Release/rnode_firmware_techo.zip
release-xiao_s3:
arduino-cli compile --fqbn "esp32:esp32:XIAO_ESP32S3" -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3E\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_xiao_esp32s3.boot_app0
cp build/esp32.esp32.XIAO_ESP32S3/RNode_Firmware.ino.bin build/rnode_firmware_xiao_esp32s3.bin
cp build/esp32.esp32.XIAO_ESP32S3/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_xiao_esp32s3.bootloader
cp build/esp32.esp32.XIAO_ESP32S3/RNode_Firmware.ino.partitions.bin build/rnode_firmware_xiao_esp32s3.partitions
zip --junk-paths ./Release/rnode_firmware_xiao_esp32s3.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_xiao_esp32s3.boot_app0 build/rnode_firmware_xiao_esp32s3.bin build/rnode_firmware_xiao_esp32s3.bootloader build/rnode_firmware_xiao_esp32s3.partitions
rm -r build

View File

@ -232,6 +232,10 @@ void measure_battery() {
}
}
#if MCU_VARIANT == MCU_NRF52
if (bt_state != BT_STATE_OFF) { blebas.write(battery_percent); }
#endif
// if (bt_state == BT_STATE_CONNECTED) {
// SerialBT.printf("Bus voltage %.3fv. Unfiltered %.3fv.", battery_voltage, bat_v_samples[BAT_SAMPLES-1]);
// if (bat_voltage_dropping) { SerialBT.printf(" Voltage is dropping. Percentage %.1f%%.", battery_percent); }

View File

@ -16,7 +16,7 @@ The RNode system is primarily software, which *transforms* different kinds of av
## Latest Release
The latest release, installable through `rnodeconf`, is version `1.81`. You must have at least version `2.4.0` of `rnodeconf` installed to update the RNode Firmware to version `1.81`. Get it by updating the `rns` package to at least version `0.9.0`.
The latest release, installable through `rnodeconf`, is version `1.82`. You must have at least version `2.4.1` of `rnodeconf` installed to update the RNode Firmware to version `1.82`. Get it by updating the `rns` package to at least version `0.9.4`.
## A Self-Replicating System
@ -72,19 +72,19 @@ The RNode Firmware supports the following boards:
- LilyGO T3S3 devices with SX1276/8 LoRa chips
- LilyGO T3S3 devices with SX1262/8 LoRa chips
- LilyGO T3S3 devices with SX1280 LoRa chips
- LilyGO T-Echo devices
- Heltec LoRa32 v2 devices
- Heltec LoRa32 v3 devices
- Heltec T114 devices
- RAK4631 devices
- SeeedStudio XIAO ESP32S3 devices (with Wio-SX1262)
- Homebrew RNodes based on ATmega1284p boards
- Homebrew RNodes based on ATmega2560 boards
- Homebrew RNodes based on Adafruit Feather ESP32 boards
- Homebrew RNodes based on generic ESP32 boards
## Supported Transceiver Modules
The RNode Firmware supports all transceiver modules based on **Semtech SX1276** or **Semtech SX1278** chips, that have an **SPI interface** and expose the **DIO_0** interrupt pin from the chip.
Support for **SX1262**, **SX1268** and **SX1280** is being implemented. Please support the project with donations if you want this faster!
The RNode Firmware supports all transceiver modules based on Semtech **SX1276**, **SX1278**, **SX1262**, **SX1268** and **SX1280** chips, that have an **SPI interface** and expose the relevant **DIO** interrupt pins from the chip.
## Getting Started Fast
You can download and flash the firmware to all the supported boards using the [RNode Config Utility](https://github.com/markqvist/rnodeconfigutil). All firmware releases are now handled and installed directly through the `rnodeconf` utility, which is included in the `rns` package. It can be installed via `pip`:

View File

@ -94,14 +94,24 @@ void setup() {
#endif
// Seed the PRNG for CSMA R-value selection
# if MCU_VARIANT == MCU_ESP32
#if MCU_VARIANT == MCU_ESP32
// On ESP32, get the seed value from the
// hardware RNG
int seed_val = (int)esp_random();
unsigned long seed_val = (unsigned long)esp_random();
#elif MCU_VARIANT == MCU_NRF52
// On nRF, get the seed value from the
// hardware RNG
unsigned long seed_val = get_rng_seed();
#else
// Otherwise, get a pseudo-random seed
// value from an unconnected analog pin
int seed_val = analogRead(0);
//
// CAUTION! If you are implementing the
// firmware on a platform that does not
// have a hardware RNG, you MUST take
// care to get a seed value with enough
// entropy at each device reset!
unsigned long seed_val = analogRead(0);
#endif
randomSeed(seed_val);
@ -115,6 +125,10 @@ void setup() {
led_init();
#endif
#if MCU_VARIANT == MCU_NRF52 && HAS_NP == true
boot_seq();
#endif
#if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1
// Some boards need to wait until the hardware UART is set up before booting
// the full firmware. In the case of the RAK4631 and Heltec T114, the line below will wait
@ -179,6 +193,13 @@ void setup() {
#endif
#endif
#if BOARD_MODEL == BOARD_XIAO_S3
// Improve wakeup from sleep
delay(300);
LoRa->reset();
delay(100);
#endif
// Check installed transceiver chip and
// probe boot parameters.
if (LoRa->preInit()) {
@ -1127,6 +1148,10 @@ void serial_callback(uint8_t sbyte) {
}
}
#endif
} else if (command == CMD_BT_UNPAIR) {
#if HAS_BLE
if (sbyte == 0x01) { bt_debond_all(); }
#endif
} else if (command == CMD_DISP_INT) {
#if HAS_DISPLAY
if (sbyte == FESC) {
@ -1611,10 +1636,13 @@ void loop() {
void sleep_now() {
#if HAS_SLEEP == true
stopRadio(); // TODO: Check this on all platforms
#if PLATFORM == PLATFORM_ESP32
#if BOARD_MODEL == BOARD_T3S3
display_intensity = 0;
update_display(true);
#if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_XIAO_S3
#if HAS_DISPLAY
display_intensity = 0;
update_display(true);
#endif
#endif
#if PIN_DISP_SLEEP >= 0
pinMode(PIN_DISP_SLEEP, OUTPUT);

View File

@ -18,6 +18,7 @@
#if HAS_EEPROM
#include <EEPROM.h>
#elif PLATFORM == PLATFORM_NRF52
#include <hal/nrf_rng.h>
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
using namespace Adafruit_LittleFS_Namespace;
@ -103,6 +104,28 @@ uint8_t boot_vector = 0x00;
// TODO: Get NRF52 boot flags
#endif
#if MCU_VARIANT == MCU_NRF52
unsigned long get_rng_seed() {
nrf_rng_error_correction_enable(NRF_RNG);
nrf_rng_shorts_disable(NRF_RNG, NRF_RNG_SHORT_VALRDY_STOP_MASK);
nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_START);
while (!nrf_rng_event_check(NRF_RNG, NRF_RNG_EVENT_VALRDY));
uint8_t rb_a = nrf_rng_random_value_get(NRF_RNG);
nrf_rng_event_clear(NRF_RNG, NRF_RNG_EVENT_VALRDY);
while (!nrf_rng_event_check(NRF_RNG, NRF_RNG_EVENT_VALRDY));
uint8_t rb_b = nrf_rng_random_value_get(NRF_RNG);
nrf_rng_event_clear(NRF_RNG, NRF_RNG_EVENT_VALRDY);
while (!nrf_rng_event_check(NRF_RNG, NRF_RNG_EVENT_VALRDY));
uint8_t rb_c = nrf_rng_random_value_get(NRF_RNG);
nrf_rng_event_clear(NRF_RNG, NRF_RNG_EVENT_VALRDY);
while (!nrf_rng_event_check(NRF_RNG, NRF_RNG_EVENT_VALRDY));
uint8_t rb_d = nrf_rng_random_value_get(NRF_RNG);
nrf_rng_event_clear(NRF_RNG, NRF_RNG_EVENT_VALRDY);
nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_STOP);
return rb_a << 24 | rb_b << 16 | rb_c << 8 | rb_d;
}
#endif
#if HAS_NP == true
#include <Adafruit_NeoPixel.h>
#define NUMPIXELS 1
@ -285,6 +308,13 @@ uint8_t boot_vector = 0x00;
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
void led_id_on() { }
void led_id_off() { }
#elif BOARD_MODEL == BOARD_XIAO_S3
void led_rx_on() { digitalWrite(pin_led_rx, LED_ON); }
void led_rx_off() { digitalWrite(pin_led_rx, LED_OFF); }
void led_tx_on() { digitalWrite(pin_led_tx, LED_ON); }
void led_tx_off() { digitalWrite(pin_led_tx, LED_OFF); }
void led_id_on() { }
void led_id_off() { }
#elif BOARD_MODEL == BOARD_HUZZAH32
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
@ -342,7 +372,7 @@ void hard_reset(void) {
#elif MCU_VARIANT == MCU_ESP32
ESP.restart();
#elif MCU_VARIANT == MCU_NRF52
NVIC_SystemReset();
NVIC_SystemReset();
#endif
}
@ -1264,6 +1294,9 @@ void setTXPower() {
if (model == MODEL_DB) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_DC) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_DD) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_DE) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E4) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E3) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
@ -1467,7 +1500,7 @@ bool eeprom_product_valid() {
#if PLATFORM == PLATFORM_AVR
if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW) {
#elif PLATFORM == PLATFORM_ESP32
if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1) {
if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1 || rval == PRODUCT_XIAO_S3) {
#elif PLATFORM == PLATFORM_NRF52
if (rval == PRODUCT_RAK4631 || rval == PRODUCT_HELTEC_T114 || rval == PRODUCT_TECHO || rval == PRODUCT_HMBRW) {
#else
@ -1503,6 +1536,8 @@ bool eeprom_model_valid() {
if (model == MODEL_16 || model == MODEL_17) {
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
if (model == MODEL_DB || model == MODEL_DC) {
#elif BOARD_MODEL == BOARD_XIAO_S3
if (model == MODEL_DD || model == MODEL_DE) {
#elif BOARD_MODEL == BOARD_LORA32_V1_0
if (model == MODEL_BA || model == MODEL_BB) {
#elif BOARD_MODEL == BOARD_LORA32_V2_0

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
import sys
import re
try:
target_path = sys.argv[1]
@ -12,7 +13,7 @@ try:
for line in sf:
line_index += 1
if line.startswith("#define RX_QUEUE_SIZE"):
ents = line.split(" ")
ents = re.sub(" +", " ", line).split(" ")
try:
rxbuf_size = int(ents[2])
rx_line_index = line_index
@ -20,12 +21,12 @@ try:
print(f"Could not parse Bluetooth RX_QUEUE_SIZE: {e}")
if line.startswith("#define TX_QUEUE_SIZE"):
ents = line.split(" ")
ents = re.sub(" +", " ", line).split(" ")
try:
txbuf_size = int(ents[2])
tx_line_index = line_index
except Exception as e:
print(f"Could not parse Bluetooth RX_QUEUE_SIZE: {e}")
print(f"Could not parse Bluetooth TX_QUEUE_SIZE: {e}")
if rxbuf_size != 0 and txbuf_size != 0:
break

View File

@ -125,7 +125,7 @@ bool sx126x::preInit() {
pinMode(_ss, OUTPUT);
digitalWrite(_ss, HIGH);
#if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_TDECK
#if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_XIAO_S3
SPI.begin(pin_sclk, pin_miso, pin_mosi, pin_cs);
#elif BOARD_MODEL == BOARD_TECHO
SPI.setPins(pin_miso, pin_sclk, pin_mosi);
@ -570,7 +570,7 @@ void sx126x::sleep() { uint8_t byte = 0x00; executeOpcode(OP_SLEEP_6X, &byte, 1)
void sx126x::enableTCXO() {
#if HAS_TCXO
#if BOARD_MODEL == BOARD_RAK4631 || BOARD_MODEL == BOARD_HELTEC32_V3
#if BOARD_MODEL == BOARD_RAK4631 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_XIAO_S3
uint8_t buf[4] = {MODE_TCXO_3_3V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_TBEAM
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};

View File

@ -56,6 +56,7 @@ public:
void receive(int size = 0);
void standby();
void sleep();
void reset(void);
bool preInit();
uint8_t getTxPower();
@ -111,7 +112,6 @@ private:
void handleLowDataRate();
void optimizeModemSensitivity();
void reset(void);
void calibrate(void);
void calibrate_image(long frequency);