Merge remote-tracking branch 'upstream/dev'

This commit is contained in:
jacob.eva 2024-10-16 21:43:16 +01:00
commit ee53fb83e0
No known key found for this signature in database
GPG Key ID: 0B92E083BBCCAA1E
71 changed files with 2822 additions and 1556 deletions

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -22,8 +22,8 @@
#elif HAS_BLE == true
#include "esp_bt_main.h"
#include "esp_bt_device.h"
// TODO: Remove
#define SerialBT Serial
#include "src/ble/BLESerial.h"
BLESerial SerialBT;
#endif
#elif MCU_VARIANT == MCU_NRF52
@ -36,6 +36,7 @@
#endif
#define BT_PAIRING_TIMEOUT 35000
#define BLE_FLUSH_TIMEOUT 20
uint32_t bt_pairing_started = 0;
#define BT_DEV_ADDR_LEN 6
@ -59,6 +60,7 @@ char bt_devname[11];
}
void bt_stop() {
//display_unblank();
if (bt_state != BT_STATE_OFF) {
SerialBT.end();
bt_allow_pairing = false;
@ -67,6 +69,7 @@ char bt_devname[11];
}
void bt_start() {
//display_unblank();
if (bt_state == BT_STATE_OFF) {
SerialBT.begin(bt_devname);
bt_state = BT_STATE_ON;
@ -74,6 +77,7 @@ char bt_devname[11];
}
void bt_enable_pairing() {
//display_unblank();
if (bt_state == BT_STATE_OFF) bt_start();
bt_allow_pairing = true;
bt_pairing_started = millis();
@ -81,12 +85,14 @@ char bt_devname[11];
}
void bt_disable_pairing() {
//display_unblank();
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_pairing_complete(boolean success) {
//display_unblank();
if (success) {
bt_disable_pairing();
} else {
@ -94,7 +100,8 @@ char bt_devname[11];
}
}
void bt_connection_callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param){
void bt_connection_callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {
//display_unblank();
if(event == ESP_SPP_SRV_OPEN_EVT) {
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
@ -157,25 +164,122 @@ char bt_devname[11];
}
#elif HAS_BLE == true
void bt_stop() {
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
}
}
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() {
//display_unblank();
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_connect_callback(uint16_t conn_handle) {
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();
}
bool bt_confirm_pin_callback(uint32_t pin) {
// Serial.printf("Confirm PIN callback: %d\n", pin);
return true;
}
void bt_debond_all() {
// Serial.println("Debonding all");
int dev_num = esp_ble_get_bond_device_num();
esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
esp_ble_get_bond_device_list(&dev_num, dev_list);
for (int i = 0; i < dev_num; i++) { esp_ble_remove_bond_device(dev_list[i].bd_addr); }
free(dev_list);
}
void bt_update_passkey() {
// Serial.println("Updating passkey");
pairing_pin = random(899999)+100000;
bt_ssp_pin = pairing_pin;
}
uint32_t bt_passkey_callback() {
// Serial.println("API passkey request");
if (pairing_pin == 0) { bt_update_passkey(); }
return pairing_pin;
}
bool bt_client_authenticated() {
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");
return true;
} else {
// Serial.println("Rejecting security request");
return false;
}
}
void bt_authentication_complete_callback(esp_ble_auth_cmpl_t auth_result) {
if (auth_result.success == true) {
// Serial.println("Authentication success");
ble_authenticated = true;
bt_state = BT_STATE_CONNECTED;
} else {
// Serial.println("Authentication fail");
ble_authenticated = false;
bt_state = BT_STATE_ON;
bt_security_setup();
}
bt_allow_pairing = false;
bt_ssp_pin = 0;
}
void bt_connect_callback(BLEServer *server) {
// uint16_t conn_id = server->getConnId();
// Serial.printf("Connected: %d\n", conn_id);
//display_unblank();
ble_authenticated = false;
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
}
void bt_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
void bt_disconnect_callback(BLEServer *server) {
// uint16_t conn_id = server->getConnId();
// Serial.printf("Disconnected: %d\n", conn_id);
//display_unblank();
ble_authenticated = false;
bt_state = BT_STATE_ON;
}
@ -200,7 +304,7 @@ char bt_devname[11];
sprintf(bt_devname, "RNode %02X%02X", bt_dh[14], bt_dh[15]);
free(data);
// TODO: Implement GAP & GATT for RNode comms over BLE
bt_security_setup();
bt_ready = true;
return true;
@ -212,9 +316,20 @@ char bt_devname[11];
}
void bt_start() {
//display_unblank();
if (bt_state == BT_STATE_OFF) {
bt_state = BT_STATE_ON;
// TODO: Implement
SerialBT.begin(bt_devname);
SerialBT.setTimeout(10);
}
}
void bt_stop() {
//display_unblank();
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
SerialBT.end();
}
}
@ -229,7 +344,13 @@ char bt_devname[11];
}
void bt_enable_pairing() {
//display_unblank();
if (bt_state == BT_STATE_OFF) bt_start();
bt_security_setup();
//bt_debond_all();
//bt_update_passkey();
bt_allow_pairing = true;
bt_pairing_started = millis();
bt_state = BT_STATE_PAIRING;
@ -239,26 +360,31 @@ char bt_devname[11];
if (bt_allow_pairing && millis()-bt_pairing_started >= BT_PAIRING_TIMEOUT) {
bt_disable_pairing();
}
if (bt_state == BT_STATE_CONNECTED && millis()-SerialBT.lastFlushTime >= BLE_FLUSH_TIMEOUT) {
if (SerialBT.transmitBufferLength > 0) {
bt_flush();
}
}
}
#endif
#elif MCU_VARIANT == MCU_NRF52
uint8_t eeprom_read(uint32_t mapped_addr);
uint8_t eeprom_read(uint32_t mapped_addr);
void bt_stop() {
if (bt_state != BT_STATE_OFF) {
bt_allow_pairing = false;
bt_state = BT_STATE_OFF;
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_disable_pairing() {
bt_allow_pairing = false;
bt_ssp_pin = 0;
bt_state = BT_STATE_ON;
}
void bt_pairing_complete(uint16_t conn_handle, uint8_t auth_status) {
void bt_pairing_complete(uint16_t conn_handle, uint8_t auth_status) {
if (auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
BLEConnection* connection = Bluefruit.Connection(conn_handle);
@ -291,24 +417,23 @@ void bt_pairing_complete(uint16_t conn_handle, uint8_t auth_status) {
} else {
bt_ssp_pin = 0;
}
}
}
bool bt_passkey_callback(uint16_t conn_handle, uint8_t const passkey[6], bool match_request) {
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);
// 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();
if (bt_allow_pairing) {
return true;
return true;
}
return false;
}
}
void bt_connect_callback(uint16_t conn_handle) {
void bt_connect_callback(uint16_t conn_handle) {
bt_state = BT_STATE_CONNECTED;
cable_state = CABLE_STATE_DISCONNECTED;
BLEConnection* conn = Bluefruit.Connection(conn_handle);
conn->requestPHY(BLE_GAP_PHY_2MBPS);
conn->requestMtuExchange(512+3);
@ -321,93 +446,91 @@ void bt_disconnect_callback(uint16_t conn_handle, uint8_t reason) {
}
}
bool bt_setup_hw() {
if (!bt_ready) {
#if HAS_EEPROM
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
#else
if (eeprom_read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
#endif
bt_enabled = true;
} else {
bt_enabled = false;
}
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.autoConnLed(false);
if (Bluefruit.begin()) {
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
// being set, but I have chosen to set it thus to force the input of the
// pin on the device initiating the pairing. This prevents it from being
// paired with automatically by a hypothetical malicious device nearby
// without physical access to the RNode.
Bluefruit.Security.setMITM(true);
Bluefruit.Security.setPairPasskeyCallback(bt_passkey_callback);
Bluefruit.Security.setSecuredCallback(bt_connect_callback);
Bluefruit.Periph.setDisconnectCallback(bt_disconnect_callback);
Bluefruit.Security.setPairCompleteCallback(bt_pairing_complete);
Bluefruit.Periph.setConnInterval(6, 12); // 7.5 - 15 ms
const ble_gap_addr_t gap_addr = Bluefruit.getAddr();
char *data = (char*)malloc(BT_DEV_ADDR_LEN+1);
for (int i = 0; i < BT_DEV_ADDR_LEN; i++) {
data[i] = gap_addr.addr[i];
}
bool bt_setup_hw() {
if (!bt_ready) {
#if HAS_EEPROM
data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE));
if (EEPROM.read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
#else
data[BT_DEV_ADDR_LEN] = eeprom_read(eeprom_addr(ADDR_SIGNATURE));
if (eeprom_read(eeprom_addr(ADDR_CONF_BT)) == BT_ENABLE_BYTE) {
#endif
unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN);
memcpy(bt_dh, hash, BT_DEV_HASH_LEN);
sprintf(bt_devname, "openCom XL %02X%02X", bt_dh[14], bt_dh[15]);
free(data);
bt_enabled = true;
} else {
bt_enabled = false;
}
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.autoConnLed(false);
if (Bluefruit.begin()) {
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
// being set, but I have chosen to set it thus to force the input of the
// pin on the device initiating the pairing.
bt_ready = true;
return true;
Bluefruit.Security.setMITM(true);
Bluefruit.Security.setPairPasskeyCallback(bt_passkey_callback);
Bluefruit.Security.setSecuredCallback(bt_connect_callback);
Bluefruit.Periph.setDisconnectCallback(bt_disconnect_callback);
Bluefruit.Security.setPairCompleteCallback(bt_pairing_complete);
Bluefruit.Periph.setConnInterval(6, 12); // 7.5 - 15 ms
const ble_gap_addr_t gap_addr = Bluefruit.getAddr();
char *data = (char*)malloc(BT_DEV_ADDR_LEN+1);
for (int i = 0; i < BT_DEV_ADDR_LEN; i++) {
data[i] = gap_addr.addr[i];
}
#if HAS_EEPROM
data[BT_DEV_ADDR_LEN] = EEPROM.read(eeprom_addr(ADDR_SIGNATURE));
#else
data[BT_DEV_ADDR_LEN] = eeprom_read(eeprom_addr(ADDR_SIGNATURE));
#endif
unsigned char *hash = MD5::make_hash(data, BT_DEV_ADDR_LEN);
memcpy(bt_dh, hash, BT_DEV_HASH_LEN);
sprintf(bt_devname, "openCom XL %02X%02X", bt_dh[14], bt_dh[15]);
free(data);
bt_ready = true;
return true;
} else { return false; }
} else { return false; }
} else { return false; }
}
}
void 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();
void 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();
if (!SerialBT_init) {
if (!SerialBT_init) {
SerialBT.bufferTXD(true); // enable buffering
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;
}
SerialBT.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM); // enable encryption for BLE serial
SerialBT.begin();
SerialBT_init = true;
}
blebas.begin();
blebas.begin();
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(SerialBT);
// Include bleuart 128-bit uuid
Bluefruit.Advertising.addService(SerialBT);
// There is no room for Name in Advertising packet
// Use Scan response for Name
Bluefruit.ScanResponse.addName();
// There is no room for Name in Advertising packet
// Use Scan response for Name
Bluefruit.ScanResponse.addName();
Bluefruit.Advertising.start(0);
Bluefruit.Advertising.start(0);
bt_state = BT_STATE_ON;
}
}
bt_state = BT_STATE_ON;
}
}
bool bt_init() {
bool bt_init() {
bt_state = BT_STATE_OFF;
if (bt_setup_hw()) {
if (bt_enabled && !console_active) bt_start();
@ -415,18 +538,18 @@ bool bt_init() {
} 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();
}
}
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

369
Boards.h
View File

@ -25,23 +25,102 @@
#define MCU_ESP32 0x81
#define MCU_NRF52 0x71
// Boards
#define BOARD_RNODE 0x31
#define BOARD_HMBRW 0x32
// Products, boards and models. Grouped by manufacturer.
// Below are the original RNodes, sold by Mark Qvist.
#define PRODUCT_RNODE 0x03 // RNode devices
#define BOARD_RNODE 0x31 // Original v1.0 RNode
#define MODEL_A4 0xA4 // RNode v1.0, 433 MHz
#define MODEL_A9 0xA9 // RNode v1.0, 868 MHz
#define BOARD_RNODE_NG_20 0x40 // RNode hardware revision v2.0
#define MODEL_A3 0xA3 // RNode v2.0, 433 MHz
#define MODEL_A8 0xA8 // RNode v2.0, 868 MHz
#define BOARD_RNODE_NG_21 0x41 // RNode hardware revision v2.1
#define MODEL_A2 0xA2 // RNode v2.1, 433 MHz
#define MODEL_A7 0xA7 // RNode v2.1, 868 MHz
#define BOARD_RNODE_NG_22 0x42 // RNode hardware revision v2.2 (T3S3)
#define MODEL_A1 0xA1 // RNode v2.2, 433 MHz with SX1268
#define MODEL_A5 0xA5 // RNode v2.2, 433 MHz with SX1278
#define MODEL_A6 0xA6 // RNode v2.2, 868 MHz with SX1262
#define MODEL_AA 0xAA // RNode v2.2, 868 MHz with SX1276
#define PRODUCT_TBEAM 0xE0 // T-Beam - sold by LilyGO
#define BOARD_TBEAM 0x33
#define MODEL_E4 0xE4 // T-Beam SX1278, 433 Mhz
#define MODEL_E9 0xE9 // T-Beam SX1276, 868 Mhz
#define MODEL_E3 0xE3 // T-Beam SX1268, 433 Mhz
#define MODEL_E8 0xE8 // T-Beam SX1262, 868 Mhz
#define PRODUCT_TDECK_V1 0xD0 // T-Deck - sold by LilyGO
#define BOARD_TDECK 0x3B
#define MODEL_D4 0xD4 // LilyGO T-Deck, 433 MHz
#define MODEL_D9 0xD9 // LilyGO T-Deck, 868 MHz
#define PRODUCT_TBEAM_S_V1 0xEA // T-Beam Supreme - sold by LilyGO
#define BOARD_TBEAM_S_V1 0x3D
#define MODEL_DB 0xDB // LilyGO T-Beam Supreme, 433 MHz
#define MODEL_DC 0xDC // LilyGO T-Beam Supreme, 868 MHz
#define PRODUCT_T32_10 0xB2 // T3 v1.0 - sold by LilyGO
#define BOARD_LORA32_V1_0 0x39
#define MODEL_BA 0xBA // LilyGO T3 v1.0, 433 MHz
#define MODEL_BB 0xBB // LilyGO T3 v1.0, 868 MHz
#define PRODUCT_T32_20 0xB0 // T3 v2.0 - sold by LilyGO
#define BOARD_LORA32_V2_0 0x36
#define MODEL_B3 0xB3 // LilyGO T3 v2.0, 433 MHz
#define MODEL_B8 0xB8 // LilyGO T3 v2.0, 868 MHz
#define PRODUCT_T32_21 0xB1 // T3 v2.1 - sold by LilyGO
#define BOARD_LORA32_V2_1 0x37
#define MODEL_B4 0xB4 // LilyGO T3 v2.1, 433 MHz
#define MODEL_B9 0xB9 // LilyGO T3 v2.1, 868 MHz
#define BOARD_T3S3 0x42 // T3S3 - sold by LilyGO
#define MODEL_A1 0xA1 // T3S3 SX1262 868/915 MHz
#define MODEL_AB 0xAB // T3S3 SX1276 868/915 MHz
#define MODEL_A5 0xA5 // T3S3 SX1278 433 MHz
#define MODEL_AB 0xAB // T3S3 SX1280 2.4 GHz w/ PA
#define PRODUCT_TECHO 0x15 // LilyGO T-Echo devices
#define BOARD_TECHO 0x43
#define MODEL_16 0x16 // T-Echo 433 MHz
#define MODEL_17 0x17 // T-Echo 868/915 MHz
#define PRODUCT_H32_V2 0xC0 // LoRa32 v2 - sold by Heltec
#define BOARD_HELTEC32_V2 0x38
#define MODEL_C4 0xC4 // Heltec Lora32 v2, 433 MHz
#define MODEL_C9 0xC9 // Heltec Lora32 v2, 868 MHz
#define PRODUCT_H32_V3 0xC1 // LoRa32 v3 - sold by Heltec
#define BOARD_HELTEC32_V3 0x3A
#define MODEL_C5 0xC5 // Heltec Lora32 v3, 433 MHz
#define MODEL_CA 0xCA // Heltec Lora32 v3, 868 MHz
#define PRODUCT_RAK4631 0x10 // RAK4631 - sold by RAKWireless
#define BOARD_RAK4631 0x51
#define MODEL_11 0x11 // RAK4631, 433 MHz
#define MODEL_12 0x12 // RAK4631, 868 MHz
#define MODEL_13 0x13 // RAK4631, 433MHz with WisBlock SX1280 module (LIBSYS002)
#define MODEL_14 0x14 // RAK4631, 868/915 MHz with WisBlock SX1280 module (LIBSYS002)
#define PRODUCT_OPENCOM_XL 0x20 // openCom XL - sold by Liberated Embedded Systems
#define BOARD_OPENCOM_XL 0x52
#define MODEL_21 0x21 // openCom XL, 868/915 MHz
#define BOARD_E22_ESP32 0x44 // Custom Ebyte E22 board design for meshtastic, source:
// https://github.com/NanoVHF/Meshtastic-DIY/blob/main/Schematics/E-Byte_E22/Mesh_Ebyte_E22-XXXM30S.pdf
#define PRODUCT_HMBRW 0xF0
#define BOARD_HMBRW 0x32
#define BOARD_HUZZAH32 0x34
#define BOARD_GENERIC_ESP32 0x35
#define BOARD_LORA32_V2_0 0x36
#define BOARD_LORA32_V2_1 0x37
#define BOARD_LORA32_V1_0 0x39
#define BOARD_HELTEC32_V2 0x38
#define BOARD_HELTEC32_V3 0x3A
#define BOARD_RNODE_NG_20 0x40
#define BOARD_RNODE_NG_21 0x41
#define BOARD_T3S3 0x42
#define BOARD_TECHO 0x43
#define BOARD_GENERIC_NRF52 0x50
#define BOARD_FREENODE 0x52
#define MODEL_FE 0xFE // Homebrew board, max 17dBm output power
#define MODEL_FF 0xFF // Homebrew board, max 14dBm output power
// Displays
#define OLED 0x01
@ -131,7 +210,6 @@
#define DISPLAY OLED
#define HAS_PMU true
#define HAS_BLUETOOTH true
#define HAS_BLE true
#define HAS_CONSOLE true
#define HAS_SD false
#define HAS_EEPROM true
@ -139,10 +217,39 @@
#define I2C_SCL 22
#define PMU_IRQ 35
#define INTERFACE_COUNT 1
#define HAS_INPUT true
const int pin_btn_usr1 = 38;
const int pin_led_rx = 2;
const int pin_led_tx = 4;
const uint8_t interfaces[INTERFACE_COUNT] = {SX1262};
#if BOARD_VARIANT == MODEL_E4 || BOARD_VARIANT == MODEL_E9
const uint8_t interfaces[INTERFACE_COUNT] = {SX127X};
const bool interface_cfg[INTERFACE_COUNT][3] = {
// SX127X
{
true, // DEFAULT_SPI
false, // HAS_TCXO
false // DIO2_AS_RF_SWITCH
},
};
const int8_t interface_pins[INTERFACE_COUNT][10] = {
// SX127X
{
18, // pin_ss
-1, // pin_sclk
-1, // pin_mosi
-1, // pin_miso
-1, // pin_busy
26, // pin_dio
23, // pin_reset
-1, // pin_txen
-1, // pin_rxen
-1 // pin_tcxo_enable
}
};
#elif BOARD_VARIANT == MODEL_E3 || BOARD_VARIANT == MODEL_E8
const uint8_t interfaces[INTERFACE_COUNT] = {SX126X};
const bool interface_cfg[INTERFACE_COUNT][3] = {
// SX1262
{
@ -166,6 +273,7 @@
-1 // pin_tcxo_enable
}
};
#endif
#elif BOARD_MODEL == BOARD_HUZZAH32
#define HAS_BLUETOOTH true
@ -204,7 +312,6 @@
#define HAS_DISPLAY true
#define DISPLAY OLED
#define HAS_BLUETOOTH true
#define HAS_BLE true
#define HAS_CONSOLE true
#define HAS_EEPROM true
#define INTERFACE_COUNT 1
@ -248,7 +355,6 @@
#define HAS_DISPLAY true
#define DISPLAY OLED
#define HAS_BLUETOOTH true
#define HAS_BLE true
#define HAS_CONSOLE true
#define HAS_EEPROM true
#define INTERFACE_COUNT 1
@ -293,7 +399,6 @@
#define HAS_DISPLAY true
#define DISPLAY OLED
#define HAS_BLUETOOTH true
#define HAS_BLE true
#define HAS_PMU true
#define HAS_CONSOLE true
#define HAS_EEPROM true
@ -367,6 +472,13 @@
#define HAS_CONSOLE true
#define HAS_EEPROM true
#define INTERFACE_COUNT 1
#define HAS_INPUT true
#define HAS_SLEEP true
#define PIN_WAKEUP GPIO_NUM_0
#define WAKEUP_LEVEL 0
const int pin_btn_usr1 = 0;
#if defined(EXTERNAL_LEDS)
const int pin_led_rx = 36;
const int pin_led_tx = 37;
@ -405,7 +517,8 @@
#define HAS_DISPLAY true
#define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_CONSOLE false
#define HAS_PMU true
#define HAS_CONSOLE true
#define HAS_EEPROM true
#define HAS_INPUT true
#define HAS_SLEEP true
@ -551,7 +664,6 @@
#elif BOARD_MODEL == BOARD_T3S3
#define IS_ESP32S3 true
#define HAS_DISPLAY true
#define DISPLAY OLED
#define HAS_CONSOLE false
@ -579,6 +691,7 @@
const int SD_MOSI = 11;
const int SD_CLK = 14;
const int SD_CS = 13;
#if HAS_NP == false
#if defined(EXTERNAL_LEDS)
const int pin_led_rx = 37;
@ -599,17 +712,6 @@
true // DIO2_AS_RF_SWITCH
},
};
#elif BOARD_VARIANT == MODEL_A5 // SX1280 with PA
const uint8_t interfaces[INTERFACE_COUNT] = {SX1280};
const bool interface_cfg[INTERFACE_COUNT][3] = {
// SX1280
{
false, // DEFAULT_SPI
false, // HAS_TCXO
false // DIO2_AS_RF_SWITCH
},
};
#endif
const uint8_t interface_pins[INTERFACE_COUNT][10] = {
// SX1262
{
@ -625,13 +727,184 @@
-1 // pin_tcxo_enable
}
};
#else
#error An unsupported ESP32 board was selected. Cannot compile RNode firmware.
#endif
#elif BOARD_VARIANT == MODEL_AB // SX1280 with PA
const uint8_t interfaces[INTERFACE_COUNT] = {SX1280};
const bool interface_cfg[INTERFACE_COUNT][3] = {
// SX1280
{
false, // DEFAULT_SPI
false, // HAS_TCXO
false // DIO2_AS_RF_SWITCH
},
};
const uint8_t interface_pins[INTERFACE_COUNT][10] = {
// SX1280
{
7, // pin_ss
5, // pin_sclk
6, // pin_mosi
3, // pin_miso
36, // pin_busy
9, // pin_dio
8, // pin_reset
10, // pin_txen
21, // pin_rxen
-1 // pin_tcxo_enable
}
};
#endif
#elif BOARD_MODEL == BOARD_E22_ESP32
#define HAS_DISPLAY true
#define DISPLAY OLED
#define HAS_BLUETOOTH true
#define HAS_BLE true
#define HAS_CONSOLE true
#define HAS_SD false
#define HAS_EEPROM true
#define I2C_SDA 21
#define I2C_SCL 22
#define INTERFACE_COUNT 1
const int pin_led_rx = 2;
const int pin_led_tx = 4;
const uint8_t interfaces[INTERFACE_COUNT] = {SX1262};
const bool interface_cfg[INTERFACE_COUNT][3] = {
// SX1262
{
true, // DEFAULT_SPI
true, // HAS_TCXO
true // DIO2_AS_RF_SWITCH
},
};
const int8_t interface_pins[INTERFACE_COUNT][10] = {
// SX1262
{
18, // pin_ss
5, // pin_sclk
27, // pin_mosi
19, // pin_miso
32, // pin_busy
33, // pin_dio
23, // pin_reset
-1, // pin_txen
14, // pin_rxen
-1 // pin_tcxo_enable
}
};
#elif BOARD_MODEL == BOARD_TDECK
#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 false
#define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_PMU 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_0
#define WAKEUP_LEVEL 0
const int pin_poweron = 10;
const int pin_btn_usr1 = 0;
const int pin_cs = 9;
const int pin_reset = 17;
const int pin_sclk = 40;
const int pin_mosi = 41;
const int pin_miso = 38;
const int pin_tcxo_enable = -1;
const int pin_dio = 45;
const int pin_busy = 13;
const int SD_MISO = 38;
const int SD_MOSI = 41;
const int SD_CLK = 40;
const int SD_CS = 39;
const int DISPLAY_DC = 11;
const int DISPLAY_CS = 12;
const int DISPLAY_MISO = 38;
const int DISPLAY_MOSI = 41;
const int DISPLAY_CLK = 40;
const int DISPLAY_BL_PIN = 42;
#if HAS_NP == false
#if defined(EXTERNAL_LEDS)
const int pin_led_rx = 43;
const int pin_led_tx = 43;
#else
const int pin_led_rx = 43;
const int pin_led_tx = 43;
#endif
#endif
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
#define IS_ESP32S3 true
#define MODEM SX1262
#define DIO2_AS_RF_SWITCH true
#define HAS_BUSY true
#define HAS_TCXO true
#define HAS_DISPLAY true
#define HAS_CONSOLE true
#define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_PMU true
#define HAS_NP false
#define HAS_SD false
#define HAS_EEPROM true
#define HAS_INPUT true
#define HAS_SLEEP false
#define PMU_IRQ 40
#define I2C_SCL 41
#define I2C_SDA 42
const int pin_btn_usr1 = 0;
const int pin_cs = 10;
const int pin_reset = 5;
const int pin_sclk = 12;
const int pin_mosi = 11;
const int pin_miso = 13;
const int pin_tcxo_enable = -1;
const int pin_dio = 1;
const int pin_busy = 4;
const int SD_MISO = 37;
const int SD_MOSI = 35;
const int SD_CLK = 36;
const int SD_CS = 47;
const int IMU_CS = 34;
#if HAS_NP == false
#if defined(EXTERNAL_LEDS)
const int pin_led_rx = 43;
const int pin_led_tx = 43;
#else
const int pin_led_rx = 43;
const int pin_led_tx = 43;
#endif
#endif
#endif
#elif MCU_VARIANT == MCU_NRF52
#if BOARD_MODEL == BOARD_TECHO
#define VALIDATE_FIRMWARE false
#define HAS_INPUT true
//#define GPS_BAUD_RATE 115200
//#define PIN_GPS_TX 41
//#define PIN_GPS_RX 40
@ -639,17 +912,18 @@
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
//#define HAS_EEPROM true
//#define HAS_SD true
//#define HAS_DISPLAY true
#define HAS_DISPLAY true
#define DISPLAY EINK_BW
#define DISPLAY_MODEL GxEPD2_154_D67
//#define HAS_CONSOLE true
//#define HAS_TXCO true
//#define DISPLAY EINK_BW
//#define HAS_BLE true
//#define HAS_PMU true
#define CONFIG_UART_BUFFER_SIZE 40000
#define CONFIG_QUEUE_0_SIZE 6144
#define CONFIG_QUEUE_MAX_LENGTH 200
#define BLE_MANUFACTURER "LilyGO"
#define BLE_MODEL "T-Echo"
//#define BLE_MANUFACTURER "LilyGO"
//#define BLE_MODEL "T-Echo"
#define INTERFACE_COUNT 1
//#define I2C_SDA 26
//#define I2C_SCL 27
@ -686,10 +960,17 @@
const int pin_disp_reset = 2;
const int pin_disp_busy = 3;
const int pin_disp_en = 43;
const int pin_disp_sck = 31;
const int pin_disp_mosi = 29;
const int pin_disp_miso = -1;
#define HAS_BACKLIGHT true
const int pin_btn_usr1 = 42;
const int pin_backlight = 43;
const int pin_led_rx = LED_BLUE;
const int pin_led_tx = LED_RED;
#elif BOARD_MODEL == BOARD_FREENODE
#elif BOARD_MODEL == BOARD_OPENCOM_XL
#define HAS_EEPROM false
#define HAS_DISPLAY true
#define DISPLAY EINK_BW
@ -699,16 +980,14 @@
#define HAS_PMU true
#define HAS_NP false
#define HAS_SD false
#define CONFIG_UART_BUFFER_SIZE 40000
#define CONFIG_QUEUE_0_SIZE 6144
#define CONFIG_QUEUE_1_SIZE 20000
#define CONFIG_QUEUE_MAX_LENGTH 200
#define EEPROM_SIZE 296
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
#define BLE_MANUFACTURER "RAK Wireless"
#define BLE_MODEL "RAK4640"
#define HAS_BUZZER true
#define HAS_BUZZER false
#define PIN_BUZZER WB_IO2
// todo, I would much rather these be in Buzzer.h
@ -718,14 +997,15 @@
#define TX_HI_TONE 550
#define MAX_BUZZER_DELAY 100
#define HAS_BUZZER_CTRL true
#define HAS_BUZZER_CTRL false
#define HAS_INPUT true
#define HAS_INPUT false
#define PIN_BUTTON WB_SW1
#define INTERFACE_COUNT 2
#define CONFIG_QUEUE_1_SIZE 40000
#define CONFIG_UART_BUFFER_SIZE 40000 // \todo, does it have to be this big?
// first interface in list is the primary
const uint8_t interfaces[INTERFACE_COUNT] = {SX126X, SX128X};
@ -778,6 +1058,7 @@
const int pin_disp_busy = WB_IO4;
const int pin_disp_en = WB_IO2;
const int pin_btn_usr1 = 9;
const int pin_led_rx = LED_BLUE;
const int pin_led_tx = LED_GREEN;
#else

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -20,7 +20,7 @@
#define CONFIG_H
#define MAJ_VERS 0x01
#define MIN_VERS 0x4a
#define MIN_VERS 0x4b
#define MODE_HOST 0x11
#define MODE_TNC 0x12
@ -65,7 +65,6 @@
// packet RSSI register
const int rssi_offset = 157;
// Default LoRa settings
const int lora_rx_turnaround_ms = 66;
const int lora_post_tx_yield_slots = 6;
@ -78,10 +77,10 @@
bool pmu_ready = false;
bool promisc = false;
bool implicit = false;
bool memory_low = false;
uint8_t implicit_l = 0;
volatile bool packet_ready = false;
volatile uint8_t packet_interface = 0xFF;
uint8_t packet_interface = 0xFF;
uint8_t op_mode = MODE_HOST;
uint8_t model = 0x00;
@ -90,7 +89,7 @@
int last_rssi = -292;
uint8_t last_rssi_raw = 0x00;
uint8_t last_snr_raw = 0x80;
uint8_t seq = 0xFF;
uint8_t seq[INTERFACE_COUNT];
uint16_t read_len = 0;
bool serial_in_frame = false;
@ -115,9 +114,10 @@
unsigned long last_rx = 0;
// Power management
#define BATTERY_STATE_UNKNOWN 0x00
#define BATTERY_STATE_DISCHARGING 0x01
#define BATTERY_STATE_CHARGING 0x02
#define BATTERY_STATE_CHARGED 0x03
#define BATTERY_STATE_CHARGING 0x02
#define BATTERY_STATE_CHARGED 0x03
bool battery_installed = false;
bool battery_indeterminate = false;
bool external_power = false;
@ -127,6 +127,7 @@
uint8_t battery_state = 0x00;
uint8_t display_intensity = 0xFF;
uint8_t display_addr = 0xFF;
bool display_blanking_enabled = false;
bool display_diagnostics = true;
bool device_init_done = false;
bool eeprom_ok = false;
@ -134,9 +135,9 @@
// Boot flags
#define START_FROM_BOOTLOADER 0x01
#define START_FROM_POWERON 0x02
#define START_FROM_BROWNOUT 0x03
#define START_FROM_JTAG 0x04
#define START_FROM_POWERON 0x02
#define START_FROM_BROWNOUT 0x03
#define START_FROM_JTAG 0x04
// Subinterfaces
// select interface 0 by default

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by

View File

@ -21,7 +21,7 @@ pages-debug:
sourcepack:
@echo Packing firmware sources...
zip --junk-paths -r build/pkg/rnode_firmware.zip ../arduino-cli.yaml ../Bluetooth.h ../Boards.h ../Config.h ../Console.h ../Device.h ../Display.h ../Framing.h ../Graphics.h ../Input.h ../LICENSE ../Makefile ../MD5.cpp ../MD5.h ../Modem.h ../partition_hashes ../Power.h ../README.md ../release_hashes.py ../RNode_Firmware_CE.ino ../ROM.h ../sx126x.cpp ../sx126x.h ../sx127x.cpp ../sx127x.h ../sx128x.cpp ../sx128x.h ../Utilities.h
zip --junk-paths -r build/pkg/rnode_firmware.zip ../arduino-cli.yaml ../src/ble/BLESerial.cpp ../src/ble/BLESerial.h ../Bluetooth.h ../Boards.h ../Config.h ../Console.h ../Device.h ../Display.h ../Framing.h ../Graphics.h .../Input.h ../Interfaces.h ../LICENSE ../Makefile ../src/misc/FIFOBuffer.c ../src/misc/FIFOBuffer.h ../src/misc/MD5.cpp ../src/misc/MD5.h ../partition_hashes ../Power.h ../README.md ../release_hashes.py ../RNode_Firmware_CE.ino ../ROM.h ../Radio.cpp ../Radio.hpp ../Utilities.h ../esp32_btbufs.py
data:
@echo Including assets...

View File

@ -4,9 +4,9 @@ import sys
import shutil
packages = {
"rns": "rns-0.7.5-py3-none-any.whl",
"nomadnet": "nomadnet-0.4.9-py3-none-any.whl",
"lxmf": "lxmf-0.4.3-py3-none-any.whl",
"rns": "rns-0.8.2-py3-none-any.whl",
"nomadnet": "nomadnet-0.5.4-py3-none-any.whl",
"lxmf": "lxmf-0.5.5-py3-none-any.whl",
"rnsh": "rnsh-0.1.4-py3-none-any.whl",
}
@ -174,26 +174,34 @@ mf.write(help_redirect)
mf.close()
def optimise_manual(path):
pm = 110
pm = 60
scale_imgs = [
("_images/board_rnodev2.png", pm),
("_images/board_rnode.png", pm),
("_images/board_heltec32.png", pm),
("_images/board_heltec32v20.png", pm),
("_images/board_heltec32v30.png", pm),
("_images/board_t3v21.png", pm),
("_images/board_t3v20.png", pm),
("_images/sideband_devices.webp", pm),
("_images/board_t3v10.png", pm),
("_images/board_t3s3.png", pm),
("_images/board_tbeam.png", pm),
("_images/board_tdeck.png", pm),
("_images/board_rak4631.png", pm),
("_images/board_tbeam_supreme.png", pm),
("_images/sideband_devices.webp", pm),
("_images/nomadnet_3.png", pm),
("_images/meshchat_1.webp", pm),
("_images/radio_is5ac.png", pm),
("_images/radio_rblhg5.png", pm),
("_static/rns_logo_512.png", 256),
("../images/bg_h_1.webp", pm),
]
import subprocess
import shlex
for i,s in scale_imgs:
fp = path+"/"+i
resize = "convert "+fp+" -resize "+str(s)+" "+fp
resize = "convert "+fp+" -quality 25 -resize "+str(s)+" "+fp
print(resize)
subprocess.call(shlex.split(resize), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
@ -205,6 +213,7 @@ def optimise_manual(path):
"_static/scripts/furo.js.map",
"_static/jquery-3.6.0.js",
"_static/jquery.js",
"static/underscore-1.13.1.js",
"_static/_sphinx_javascript_frameworks_compat.js",
"_static/scripts/furo.js.LICENSE.txt",
"_static/styles/furo-extensions.css.map",

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -296,7 +296,8 @@ bool device_init() {
}
#else
// Skip hash comparison and checking BT
return true;
device_init_done = true;
return device_init_done;
#endif
}
#endif

1134
Display.h

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -53,6 +53,8 @@
#define CMD_FB_READL 0x44
#define CMD_DISP_INT 0x45
#define CMD_DISP_ADDR 0x63
#define CMD_DISP_BLNK 0x64
#define CMD_NP_INT 0x65
#define CMD_BT_CTRL 0x46
#define CMD_BT_PIN 0x62
@ -81,7 +83,7 @@
#define CMD_INT1_DATA 0x10
#define CMD_INT2_DATA 0x20
#define CMD_INT3_DATA 0x70
#define CMD_INT4_DATA 0x80
#define CMD_INT4_DATA 0x75
#define CMD_INT5_DATA 0x90
#define CMD_INT6_DATA 0xA0
#define CMD_INT7_DATA 0xB0
@ -93,8 +95,8 @@
#define CMD_SEL_INT0 0x1E
#define CMD_SEL_INT1 0x1F
#define CMD_SEL_INT2 0x2F
#define CMD_SEL_INT3 0x7F
#define CMD_SEL_INT4 0x8F
#define CMD_SEL_INT3 0x74
#define CMD_SEL_INT4 0x7F
#define CMD_SEL_INT5 0x9F
#define CMD_SEL_INT6 0xAF
#define CMD_SEL_INT7 0xBF
@ -119,6 +121,8 @@
#define ERROR_TXFAILED 0x02
#define ERROR_EEPROM_LOCKED 0x03
#define ERROR_QUEUE_FULL 0x04
#define ERROR_MEMORY_LOW 0x05
#define ERROR_MODEM_TIMEOUT 0x06
// Serial framing variables
size_t frame_len;

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -13,402 +13,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#if DISP_H == UNSCALED_MAX
// use 64px wide graphics
const unsigned char bm_cable [] PROGMEM = {
0x00, 0x00, 0x00, 0x1c, 0x00, 0x38, 0x07, 0xfc, 0x08, 0x38, 0x10, 0x1c, 0x10, 0x00, 0x08, 0x00,
0x07, 0xc0, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x07, 0xc0, 0x08, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x80, 0x04, 0x43, 0x08, 0x46,
0xf1, 0x8f, 0x02, 0x16, 0x02, 0x23, 0x01, 0x20, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_bt [] PROGMEM = {
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x01, 0x40,
0x01, 0x80, 0x01, 0x40, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x01, 0x40,
0x29, 0x94, 0x01, 0x40, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x11, 0x48,
0x29, 0x94, 0x11, 0x48, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00
};
const unsigned char bm_rf [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xc4,
0x4a, 0xaa, 0x4a, 0xce, 0x6e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x08, 0x10, 0x13, 0xc8, 0x04, 0x20, 0x01, 0x80, 0x00, 0x00, 0x4e, 0xc4,
0x4a, 0xaa, 0x4a, 0xce, 0x6e, 0xaa, 0x00, 0x00, 0x01, 0x80, 0x04, 0x20, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x4e,
0x31, 0x48, 0x61, 0xca, 0x74, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x08, 0x10, 0x13, 0xc8, 0x04, 0x20, 0x01, 0x80, 0x00, 0x00, 0x71, 0x4e,
0x31, 0x48, 0x61, 0xca, 0x74, 0x4e, 0x00, 0x00, 0x01, 0x80, 0x04, 0x20, 0x03, 0xc0, 0x00, 0x00
};
const unsigned char bm_boot [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x38, 0x66, 0x67, 0x1c, 0x3f, 0xff, 0xff, 0xfc, 0x99, 0xe6, 0x66, 0x4c, 0xff, 0xff,
0xff, 0xfc, 0x98, 0x70, 0xe6, 0x7c, 0x3f, 0xff, 0xff, 0xfc, 0x99, 0xf0, 0xe6, 0x4c, 0xff, 0xff,
0xff, 0xfc, 0x38, 0x79, 0xe7, 0x1c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0c, 0x38, 0xe1, 0xc3, 0x33, 0x38, 0x7f, 0xfe, 0x7e, 0x72, 0x64, 0xe7, 0x31, 0x33, 0xff,
0xff, 0x1e, 0x70, 0x61, 0xe7, 0x30, 0x32, 0x7f, 0xff, 0xce, 0x72, 0x61, 0xe7, 0x32, 0x32, 0x7f,
0xfe, 0x1e, 0x72, 0x64, 0xe7, 0x33, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_no_radio [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc7, 0x0e, 0x71, 0xfc, 0xce, 0x38, 0x7f,
0xc9, 0x93, 0x26, 0x64, 0xfc, 0x4c, 0x9c, 0xff, 0xc3, 0x83, 0x26, 0x64, 0xfc, 0x0c, 0x9c, 0xff,
0xc3, 0x93, 0x26, 0x64, 0xfc, 0x8c, 0x9c, 0xff, 0xc9, 0x93, 0x0e, 0x71, 0xfc, 0xce, 0x3c, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x8e, 0x4c, 0xcc, 0x3f, 0xff, 0xfc, 0xff,
0xcf, 0x26, 0x4c, 0x4c, 0x9f, 0xff, 0xfb, 0x7f, 0xc3, 0x26, 0x4c, 0x0c, 0x9f, 0xff, 0xfb, 0x7f,
0xcf, 0x26, 0x4c, 0x8c, 0x9f, 0xff, 0xf7, 0xbf, 0xcf, 0x8f, 0x1c, 0xcc, 0x3f, 0xff, 0xf4, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfb,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_hwfail [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xe3, 0x87, 0x0e, 0x73, 0x8e, 0x1c, 0x3f,
0xe4, 0xc9, 0x93, 0x26, 0x53, 0x26, 0x4c, 0xff, 0xe0, 0xc1, 0x87, 0x26, 0x53, 0x06, 0x1c, 0x3f,
0xe4, 0xc9, 0x87, 0x26, 0x03, 0x26, 0x1c, 0xff, 0xe4, 0xc9, 0x93, 0x0f, 0x27, 0x26, 0x4c, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe1, 0xc7, 0x33, 0xc9, 0x87, 0x0f, 0xf9, 0xff, 0xe7, 0x93, 0x33, 0xc9, 0x93, 0x3f, 0xf6, 0xff,
0xe1, 0x83, 0x33, 0xc9, 0x87, 0x0f, 0xf6, 0xff, 0xe7, 0x93, 0x33, 0xc9, 0x87, 0x3f, 0xef, 0x7f,
0xe7, 0x93, 0x30, 0xe3, 0x93, 0x0f, 0xe9, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_console [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x1f, 0xcf, 0xff, 0xff, 0xf3, 0xf8, 0xff,
0xfe, 0x3f, 0x9f, 0xff, 0xff, 0xf9, 0xfc, 0x7f, 0xfc, 0x7f, 0x99, 0xe6, 0x61, 0x99, 0xfe, 0x3f,
0xf8, 0xe7, 0x99, 0x26, 0x67, 0x99, 0xe7, 0x1f, 0xf9, 0xc7, 0x99, 0x26, 0x61, 0x99, 0xe3, 0x9f,
0xf1, 0x8f, 0x98, 0x06, 0x67, 0x99, 0xf1, 0x8f, 0xf3, 0x9f, 0x9c, 0xce, 0x67, 0x99, 0xf9, 0xcf,
0xf3, 0x99, 0x9f, 0xff, 0xff, 0xf9, 0x99, 0xcf, 0xf3, 0x99, 0x9f, 0xff, 0xff, 0xf9, 0x99, 0xcf,
0xf3, 0x9f, 0x9f, 0xe3, 0x83, 0xf9, 0xf9, 0xcf, 0xf1, 0x8f, 0x9f, 0xc9, 0x93, 0xf9, 0xf1, 0x8f,
0xf9, 0xc7, 0x9f, 0xc1, 0x83, 0xf9, 0xe3, 0x9f, 0xf8, 0xe7, 0x9f, 0xc9, 0x9f, 0xf9, 0xe7, 0x1f,
0xfc, 0x7f, 0x9f, 0xc9, 0x9f, 0xf9, 0xfe, 0x3f, 0xfe, 0x3f, 0x9f, 0xff, 0xff, 0xf9, 0xfc, 0x7f,
0xff, 0x1f, 0xcf, 0xff, 0xff, 0xf3, 0xf8, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f,
0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f, 0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x78, 0x1e, 0x07, 0x81, 0xe0, 0x78, 0x1f,
0xef, 0xbb, 0xee, 0xfb, 0xbe, 0xef, 0xbb, 0xef, 0xe8, 0xda, 0xb6, 0x9d, 0xb3, 0x6d, 0xda, 0x37,
0xef, 0xda, 0xf6, 0xb5, 0xad, 0x6c, 0xdb, 0xf7, 0xe8, 0x5a, 0x36, 0x95, 0xad, 0x6c, 0xda, 0x97,
0xef, 0xdb, 0xf6, 0x85, 0xb3, 0x6c, 0xda, 0x97, 0xea, 0x5a, 0x36, 0xb5, 0xb3, 0x6c, 0xdb, 0xf7,
0xef, 0xda, 0xf6, 0xa5, 0xad, 0x6f, 0xda, 0x57, 0xe8, 0x5a, 0xb6, 0x85, 0xad, 0x6c, 0xda, 0x57,
0xef, 0xdb, 0xf6, 0xfd, 0xbf, 0x6f, 0xdb, 0xf7, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x07,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x42, 0x7c, 0x60, 0xf0, 0x78, 0x3c, 0x7f, 0xfe, 0x4a, 0x7c, 0x64, 0xf2, 0x79, 0x3c, 0x7f,
0xfe, 0x43, 0xfe, 0x64, 0xf2, 0x79, 0x3e, 0x7f, 0xfe, 0x4e, 0x7e, 0x64, 0x92, 0x49, 0x26, 0x7f,
0xfe, 0x4e, 0x7e, 0x60, 0x90, 0x48, 0x26, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_pairing [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0xe3, 0x98, 0x73, 0x33, 0x87, 0xff, 0xff, 0xf2, 0xc9, 0x99, 0x33, 0x13, 0x3f, 0xff,
0xff, 0xf0, 0xc1, 0x98, 0x73, 0x03, 0x27, 0xff, 0xff, 0xf3, 0xc9, 0x98, 0x73, 0x23, 0x27, 0xff,
0xff, 0xf3, 0xc9, 0x99, 0x33, 0x33, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_fw_update [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x98, 0x70, 0xf1, 0xc3, 0x33, 0x38, 0x7f, 0xfc, 0x99, 0x32, 0x64, 0xe7, 0x31, 0x33, 0xff,
0xfc, 0x98, 0x72, 0x60, 0xe7, 0x30, 0x32, 0x7f, 0xfc, 0x99, 0xf2, 0x64, 0xe7, 0x32, 0x32, 0x7f,
0xfe, 0x39, 0xf0, 0xe4, 0xe7, 0x33, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x66, 0x1c, 0xe6, 0x73, 0x8e, 0x1c, 0x3f, 0xf9, 0xe6, 0x4c, 0x46, 0x53, 0x26, 0x4c, 0xff,
0xf8, 0x66, 0x1c, 0x06, 0x53, 0x06, 0x1c, 0x3f, 0xf9, 0xe6, 0x1c, 0xa6, 0x03, 0x26, 0x1c, 0xff,
0xf9, 0xe6, 0x4c, 0xe7, 0x27, 0x26, 0x4c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_version [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x99, 0x86, 0x1e, 0x19, 0xc7, 0x33, 0xff, 0xff, 0x99, 0x9e, 0x4c, 0xf9, 0x93, 0x13, 0xff,
0xff, 0xc3, 0x86, 0x1e, 0x39, 0x93, 0x03, 0xff, 0xff, 0xc3, 0x9e, 0x1f, 0x99, 0x93, 0x23, 0xff,
0xff, 0xe7, 0x86, 0x4c, 0x39, 0xc7, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_updating [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0x71, 0x7f, 0xff,
0xff, 0xff, 0x7f, 0xf5, 0xff, 0x75, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0x71, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0xd4, 0x7f, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x57, 0xd5, 0x7f, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x17, 0xd4, 0x7f, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x44, 0x71, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x57, 0x55, 0x75, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x47, 0x44, 0x71, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0x51, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x44, 0x51, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x54, 0x45, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x14, 0x54, 0x45, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0x60, 0x00, 0x00, 0x03, 0x7f, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x07, 0x7f, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x5c, 0x00, 0x00, 0x1c, 0x7f, 0xff,
0xff, 0xff, 0x56, 0x00, 0x00, 0x35, 0x7f, 0xff, 0xff, 0xff, 0x57, 0x00, 0x00, 0x74, 0x7f, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0xc0, 0x01, 0xd1, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x60, 0x03, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x44, 0x70, 0x07, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x5c, 0x1d, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x56, 0x35, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x14, 0x57, 0xe5, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static unsigned char bm_def[] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x61, 0x10, 0x8c, 0x23, 0xc4, 0x3f, 0xff,
0xb5, 0xa7, 0xb7, 0xb5, 0xed, 0xed, 0xbf, 0xff, 0xb5, 0xb9, 0xb4, 0xb4, 0x6d, 0xed, 0xbf, 0xff,
0x85, 0xa1, 0x10, 0xb4, 0x21, 0x44, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe7, 0x1c, 0xfe, 0x7f, 0x8f, 0xf0, 0x00,
0x1f, 0xf7, 0x9d, 0xff, 0x7f, 0x9f, 0xf0, 0x00, 0x1c, 0x77, 0xfd, 0xc7, 0x73, 0xdc, 0x00, 0x00,
0x1f, 0xe7, 0xfd, 0xc7, 0x71, 0xdf, 0x00, 0x00, 0x1f, 0xe7, 0x7d, 0xc7, 0x71, 0xdf, 0x00, 0x00,
0x1c, 0x77, 0x3d, 0xc7, 0x73, 0xdc, 0x00, 0x00, 0x1c, 0x77, 0x1d, 0xff, 0x7f, 0x9f, 0xf0, 0x00,
0x1c, 0x77, 0x1c, 0xfe, 0x7f, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x62, 0x24, 0x49, 0x22, 0x4e, 0x44,
0x00, 0x24, 0x93, 0x66, 0xc9, 0x32, 0x44, 0x28, 0x00, 0x20, 0x92, 0xa5, 0x49, 0x2a, 0x44, 0x10,
0x00, 0x24, 0x92, 0x24, 0x49, 0x26, 0x44, 0x10, 0x00, 0x18, 0x62, 0x24, 0x46, 0x22, 0x44, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x9c, 0x44, 0x88, 0xc7, 0x1c, 0x00, 0x00, 0x10, 0x92, 0x6c, 0xa9, 0x24, 0x90,
0x00, 0x00, 0x1c, 0x9c, 0x54, 0xa9, 0xe7, 0x1c, 0x00, 0x00, 0x10, 0x94, 0x44, 0xa9, 0x25, 0x10,
0x00, 0x00, 0x10, 0x92, 0x44, 0x51, 0x24, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_def_lc [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x61, 0x10, 0x8c, 0x23, 0xc4, 0x3f, 0xff,
0xb5, 0xa7, 0xb7, 0xb5, 0xed, 0xed, 0xbf, 0xff, 0xb5, 0xb9, 0xb4, 0xb4, 0x6d, 0xed, 0xbf, 0xff,
0x85, 0xa1, 0x10, 0xb4, 0x21, 0x44, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe7, 0x1c, 0xfe, 0x7f, 0x8f, 0xf0, 0x00,
0x1f, 0xf7, 0x9d, 0xff, 0x7f, 0x9f, 0xf0, 0x00, 0x1c, 0x77, 0xfd, 0xc7, 0x73, 0xdc, 0x00, 0x00,
0x1f, 0xe7, 0xfd, 0xc7, 0x71, 0xdf, 0x00, 0x00, 0x1f, 0xe7, 0x7d, 0xc7, 0x71, 0xdf, 0x00, 0x00,
0x1c, 0x77, 0x3d, 0xc7, 0x73, 0xdc, 0x00, 0x00, 0x1c, 0x77, 0x1d, 0xff, 0x7f, 0x9f, 0xf0, 0x00,
0x1c, 0x77, 0x1c, 0xfe, 0x7f, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x39, 0x10, 0x61, 0x88, 0x91, 0x1c,
0x02, 0x49, 0x21, 0x90, 0x92, 0x4d, 0x9b, 0x20, 0x02, 0x4e, 0x39, 0x50, 0x82, 0x4a, 0x95, 0x18,
0x02, 0x48, 0x21, 0x30, 0x92, 0x48, 0x91, 0x04, 0x01, 0x88, 0x39, 0x10, 0x61, 0x88, 0x91, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xc8, 0x8e, 0x73, 0x91, 0x1c, 0x00, 0x00, 0x02, 0x05, 0x10, 0x22, 0x1b, 0x20,
0x00, 0x00, 0x01, 0x82, 0x0c, 0x23, 0x95, 0x18, 0x00, 0x00, 0x00, 0x42, 0x02, 0x22, 0x11, 0x04,
0x00, 0x00, 0x03, 0x82, 0x1c, 0x23, 0x91, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_hwok [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf2, 0x71, 0xc3, 0x87, 0x39, 0xc7, 0x0e, 0x1f, 0xf2, 0x64, 0xc9, 0x93, 0x29, 0x93, 0x26, 0x7f,
0xf0, 0x60, 0xc3, 0x93, 0x29, 0x83, 0x0e, 0x1f, 0xf2, 0x64, 0xc3, 0x93, 0x01, 0x93, 0x0e, 0x7f,
0xf2, 0x64, 0xc9, 0x87, 0x93, 0x93, 0x26, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x33, 0x30, 0xff, 0x8e, 0x4f, 0xff,
0xff, 0xf3, 0x13, 0x39, 0xff, 0x26, 0x1f, 0xff, 0xff, 0xf3, 0x03, 0x39, 0xff, 0x26, 0x3f, 0xff,
0xff, 0xf3, 0x23, 0x39, 0xff, 0x26, 0x1f, 0xff, 0xff, 0xf3, 0x33, 0x39, 0xff, 0x8e, 0x4f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc3, 0x0e, 0x67, 0xf8, 0x70, 0xe3, 0x87, 0x33, 0xe7, 0x27, 0x0f, 0xf9, 0x33, 0xc9, 0x93, 0x87,
0xe7, 0x0f, 0x9f, 0xf8, 0x70, 0xc1, 0x93, 0xcf, 0xe7, 0x0f, 0x0f, 0xf8, 0x73, 0xc9, 0x93, 0xcf,
0xe7, 0x26, 0x67, 0xf9, 0x30, 0xc9, 0x87, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_console_active [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x8e, 0x67, 0x0e, 0x39, 0xe1, 0xff,
0xff, 0x93, 0x26, 0x26, 0x7c, 0x99, 0xe7, 0xff, 0xff, 0x9f, 0x26, 0x07, 0x1c, 0x99, 0xe1, 0xff,
0xff, 0x93, 0x26, 0x47, 0xcc, 0x99, 0xe7, 0xff, 0xff, 0xc7, 0x8e, 0x66, 0x1e, 0x38, 0x61, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x70, 0xcc, 0xcc, 0x3f, 0xff,
0xff, 0xfc, 0x99, 0x39, 0xcc, 0xcc, 0xff, 0xff, 0xff, 0xfc, 0x19, 0xf9, 0xce, 0x1c, 0x3f, 0xff,
0xff, 0xfc, 0x99, 0x39, 0xce, 0x1c, 0xff, 0xff, 0xff, 0xfc, 0x9c, 0x79, 0xcf, 0x3c, 0x3f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_checks [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0x0c, 0x99, 0xc7, 0x0f,
0xe6, 0x00, 0x7f, 0x93, 0x3c, 0x99, 0x93, 0x3f, 0xe6, 0x00, 0x7f, 0x93, 0x0e, 0x39, 0x9f, 0x0f,
0xff, 0xff, 0xff, 0x93, 0x3e, 0x39, 0x93, 0x3f, 0xff, 0xff, 0xff, 0x87, 0x0f, 0x79, 0xc7, 0x0f,
0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x39, 0x30, 0xe3, 0x93, 0x87,
0xe6, 0x00, 0x7c, 0x99, 0x33, 0xc9, 0x87, 0x3f, 0xe6, 0x00, 0x7c, 0xf8, 0x30, 0xcf, 0x8f, 0x8f,
0xff, 0xff, 0xfc, 0x99, 0x33, 0xc9, 0x87, 0xe7, 0xff, 0xff, 0xfe, 0x39, 0x30, 0xe3, 0x93, 0x0f,
0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9c, 0x3c, 0x78, 0x70, 0xc3, 0x0f,
0xe6, 0x0d, 0x3c, 0x99, 0x33, 0xe7, 0xcf, 0x27, 0xe6, 0x04, 0x7c, 0x38, 0x38, 0xf1, 0xc3, 0x27,
0xff, 0xfe, 0xfc, 0xf9, 0x3e, 0x7c, 0xcf, 0x27, 0xff, 0xff, 0xfc, 0xf9, 0x30, 0xe1, 0xc3, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_frame [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x40, 0x02, 0x0f, 0xff, 0xfc,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x1e, 0x40, 0x02, 0x78, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x3f, 0xff, 0xf2, 0x40, 0x02, 0x4f, 0xff, 0xfc,
0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x00, 0x00, 0x3f, 0xff, 0xf2, 0x40, 0x02, 0x4f, 0xff, 0xfc,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x1e, 0x40, 0x02, 0x78, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x3f, 0xff, 0xf0, 0x40, 0x02, 0x0f, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x1c,
0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xaa, 0x8a, 0xaa, 0x80
};
const unsigned char bm_online [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x1c, 0x66, 0x61, 0x8c, 0x24, 0x90, 0x87,
0xe6, 0x49, 0x22, 0x4f, 0x24, 0xe4, 0x93, 0x93, 0xe6, 0x18, 0x20, 0x63, 0x3c, 0x26, 0x30, 0x87,
0xe6, 0x19, 0x24, 0x79, 0x24, 0xe6, 0x33, 0x87, 0xe6, 0x49, 0x26, 0x43, 0x8c, 0x27, 0x70, 0x93,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xe6, 0x73, 0xe7, 0x33, 0x87, 0xff,
0xff, 0xe4, 0xe2, 0x73, 0xe7, 0x13, 0x9f, 0xff, 0xff, 0xe4, 0xe0, 0x73, 0xe7, 0x03, 0x87, 0xff,
0xff, 0xe4, 0xe4, 0x73, 0xe7, 0x23, 0x9f, 0xff, 0xff, 0xf1, 0xe6, 0x70, 0xe7, 0x33, 0x87, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_fw_corrupt [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x30, 0xe7, 0x33, 0x9c, 0x70, 0xe1, 0xff,
0xcf, 0x32, 0x62, 0x32, 0x99, 0x32, 0x67, 0xff, 0xc3, 0x30, 0xe0, 0x32, 0x98, 0x30, 0xe1, 0xff,
0xcf, 0x30, 0xe5, 0x30, 0x19, 0x30, 0xe7, 0xff, 0xcf, 0x32, 0x67, 0x39, 0x39, 0x32, 0x61, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xc7, 0x0e, 0x1c, 0x98, 0x70, 0xfc, 0xff,
0xc9, 0x93, 0x26, 0x4c, 0x99, 0x39, 0xfb, 0x7f, 0xcf, 0x93, 0x0e, 0x1c, 0x98, 0x79, 0xfb, 0x7f,
0xc9, 0x93, 0x0e, 0x1c, 0x99, 0xf9, 0xf7, 0xbf, 0xe3, 0xc7, 0x26, 0x4e, 0x39, 0xf9, 0xf4, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfb,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_plug [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x7f, 0x80, 0x55, 0xfc, 0x00, 0xaa, 0xfc, 0x00, 0x00,
0x7f, 0x80, 0x00, 0x1c, 0x00
};
const unsigned char bm_hg_low [] PROGMEM = {
0xf8, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0xf8, 0xf8
};
const unsigned char bm_hg_high [] PROGMEM = {
0xf8, 0x88, 0xf8, 0x70, 0x20, 0x70, 0xf8, 0xf8, 0xf8
};
const unsigned char bm_n_uh [] PROGMEM = {
0x07, 0x27, 0x27, 0x27, 0x07, 0x8f, 0x8f, 0xcf, 0xcf, 0xcf, 0x07, 0xe7, 0x07, 0x3f, 0x07, 0x07,
0xe7, 0xc7, 0xe7, 0x07, 0x27, 0x27, 0x07, 0xe7, 0xe7, 0x07, 0x3f, 0x07, 0xe7, 0x07, 0x07, 0x3f,
0x07, 0x27, 0x07, 0x07, 0xc7, 0xcf, 0x9f, 0x1f, 0x07, 0x27, 0x07, 0x27, 0x07, 0x07, 0x27, 0x07,
0xe7, 0xe7
};
const unsigned char bm_dot_sqr [] PROGMEM = {
0xaa, 0xd5, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00,
0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00,
0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0xaa, 0xd5, 0x40
};
#elif DISP_H == 122
#if DISP_H == 122
// use 122px wide graphics
const unsigned char bm_bt [] PROGMEM = {
@ -1710,6 +1315,401 @@ const unsigned char bm_dot_sqr [] PROGMEM = {
0xee, 0xdd, 0xdd, 0xc0
};
#else
// use 64px wide graphics
const unsigned char bm_cable [] PROGMEM = {
0x00, 0x00, 0x00, 0x1c, 0x00, 0x38, 0x07, 0xfc, 0x08, 0x38, 0x10, 0x1c, 0x10, 0x00, 0x08, 0x00,
0x07, 0xc0, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x07, 0xc0, 0x08, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x80, 0x04, 0x43, 0x08, 0x46,
0xf1, 0x8f, 0x02, 0x16, 0x02, 0x23, 0x01, 0x20, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_bt [] PROGMEM = {
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x01, 0x40,
0x01, 0x80, 0x01, 0x40, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x01, 0x40,
0x29, 0x94, 0x01, 0x40, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x20, 0x11, 0x48,
0x29, 0x94, 0x11, 0x48, 0x03, 0x20, 0x05, 0x10, 0x09, 0x20, 0x01, 0x40, 0x01, 0x80, 0x01, 0x00
};
const unsigned char bm_rf [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xc4,
0x4a, 0xaa, 0x4a, 0xce, 0x6e, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x08, 0x10, 0x13, 0xc8, 0x04, 0x20, 0x01, 0x80, 0x00, 0x00, 0x4e, 0xc4,
0x4a, 0xaa, 0x4a, 0xce, 0x6e, 0xaa, 0x00, 0x00, 0x01, 0x80, 0x04, 0x20, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x4e,
0x31, 0x48, 0x61, 0xca, 0x74, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xe0, 0x08, 0x10, 0x13, 0xc8, 0x04, 0x20, 0x01, 0x80, 0x00, 0x00, 0x71, 0x4e,
0x31, 0x48, 0x61, 0xca, 0x74, 0x4e, 0x00, 0x00, 0x01, 0x80, 0x04, 0x20, 0x03, 0xc0, 0x00, 0x00
};
const unsigned char bm_boot [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x38, 0x66, 0x67, 0x1c, 0x3f, 0xff, 0xff, 0xfc, 0x99, 0xe6, 0x66, 0x4c, 0xff, 0xff,
0xff, 0xfc, 0x98, 0x70, 0xe6, 0x7c, 0x3f, 0xff, 0xff, 0xfc, 0x99, 0xf0, 0xe6, 0x4c, 0xff, 0xff,
0xff, 0xfc, 0x38, 0x79, 0xe7, 0x1c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x0c, 0x38, 0xe1, 0xc3, 0x33, 0x38, 0x7f, 0xfe, 0x7e, 0x72, 0x64, 0xe7, 0x31, 0x33, 0xff,
0xff, 0x1e, 0x70, 0x61, 0xe7, 0x30, 0x32, 0x7f, 0xff, 0xce, 0x72, 0x61, 0xe7, 0x32, 0x32, 0x7f,
0xfe, 0x1e, 0x72, 0x64, 0xe7, 0x33, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_no_radio [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc7, 0x0e, 0x71, 0xfc, 0xce, 0x38, 0x7f,
0xc9, 0x93, 0x26, 0x64, 0xfc, 0x4c, 0x9c, 0xff, 0xc3, 0x83, 0x26, 0x64, 0xfc, 0x0c, 0x9c, 0xff,
0xc3, 0x93, 0x26, 0x64, 0xfc, 0x8c, 0x9c, 0xff, 0xc9, 0x93, 0x0e, 0x71, 0xfc, 0xce, 0x3c, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x8e, 0x4c, 0xcc, 0x3f, 0xff, 0xfc, 0xff,
0xcf, 0x26, 0x4c, 0x4c, 0x9f, 0xff, 0xfb, 0x7f, 0xc3, 0x26, 0x4c, 0x0c, 0x9f, 0xff, 0xfb, 0x7f,
0xcf, 0x26, 0x4c, 0x8c, 0x9f, 0xff, 0xf7, 0xbf, 0xcf, 0x8f, 0x1c, 0xcc, 0x3f, 0xff, 0xf4, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfb,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_hwfail [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xe3, 0x87, 0x0e, 0x73, 0x8e, 0x1c, 0x3f,
0xe4, 0xc9, 0x93, 0x26, 0x53, 0x26, 0x4c, 0xff, 0xe0, 0xc1, 0x87, 0x26, 0x53, 0x06, 0x1c, 0x3f,
0xe4, 0xc9, 0x87, 0x26, 0x03, 0x26, 0x1c, 0xff, 0xe4, 0xc9, 0x93, 0x0f, 0x27, 0x26, 0x4c, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe1, 0xc7, 0x33, 0xc9, 0x87, 0x0f, 0xf9, 0xff, 0xe7, 0x93, 0x33, 0xc9, 0x93, 0x3f, 0xf6, 0xff,
0xe1, 0x83, 0x33, 0xc9, 0x87, 0x0f, 0xf6, 0xff, 0xe7, 0x93, 0x33, 0xc9, 0x87, 0x3f, 0xef, 0x7f,
0xe7, 0x93, 0x30, 0xe3, 0x93, 0x0f, 0xe9, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_console [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x1f, 0xcf, 0xff, 0xff, 0xf3, 0xf8, 0xff,
0xfe, 0x3f, 0x9f, 0xff, 0xff, 0xf9, 0xfc, 0x7f, 0xfc, 0x7f, 0x99, 0xe6, 0x61, 0x99, 0xfe, 0x3f,
0xf8, 0xe7, 0x99, 0x26, 0x67, 0x99, 0xe7, 0x1f, 0xf9, 0xc7, 0x99, 0x26, 0x61, 0x99, 0xe3, 0x9f,
0xf1, 0x8f, 0x98, 0x06, 0x67, 0x99, 0xf1, 0x8f, 0xf3, 0x9f, 0x9c, 0xce, 0x67, 0x99, 0xf9, 0xcf,
0xf3, 0x99, 0x9f, 0xff, 0xff, 0xf9, 0x99, 0xcf, 0xf3, 0x99, 0x9f, 0xff, 0xff, 0xf9, 0x99, 0xcf,
0xf3, 0x9f, 0x9f, 0xe3, 0x83, 0xf9, 0xf9, 0xcf, 0xf1, 0x8f, 0x9f, 0xc9, 0x93, 0xf9, 0xf1, 0x8f,
0xf9, 0xc7, 0x9f, 0xc1, 0x83, 0xf9, 0xe3, 0x9f, 0xf8, 0xe7, 0x9f, 0xc9, 0x9f, 0xf9, 0xe7, 0x1f,
0xfc, 0x7f, 0x9f, 0xc9, 0x9f, 0xf9, 0xfe, 0x3f, 0xfe, 0x3f, 0x9f, 0xff, 0xff, 0xf9, 0xfc, 0x7f,
0xff, 0x1f, 0xcf, 0xff, 0xff, 0xf3, 0xf8, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f,
0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f, 0xfd, 0xff, 0x7f, 0xdf, 0xf7, 0xfd, 0xff, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x78, 0x1e, 0x07, 0x81, 0xe0, 0x78, 0x1f,
0xef, 0xbb, 0xee, 0xfb, 0xbe, 0xef, 0xbb, 0xef, 0xe8, 0xda, 0xb6, 0x9d, 0xb3, 0x6d, 0xda, 0x37,
0xef, 0xda, 0xf6, 0xb5, 0xad, 0x6c, 0xdb, 0xf7, 0xe8, 0x5a, 0x36, 0x95, 0xad, 0x6c, 0xda, 0x97,
0xef, 0xdb, 0xf6, 0x85, 0xb3, 0x6c, 0xda, 0x97, 0xea, 0x5a, 0x36, 0xb5, 0xb3, 0x6c, 0xdb, 0xf7,
0xef, 0xda, 0xf6, 0xa5, 0xad, 0x6f, 0xda, 0x57, 0xe8, 0x5a, 0xb6, 0x85, 0xad, 0x6c, 0xda, 0x57,
0xef, 0xdb, 0xf6, 0xfd, 0xbf, 0x6f, 0xdb, 0xf7, 0xe0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x07,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x42, 0x7c, 0x60, 0xf0, 0x78, 0x3c, 0x7f, 0xfe, 0x4a, 0x7c, 0x64, 0xf2, 0x79, 0x3c, 0x7f,
0xfe, 0x43, 0xfe, 0x64, 0xf2, 0x79, 0x3e, 0x7f, 0xfe, 0x4e, 0x7e, 0x64, 0x92, 0x49, 0x26, 0x7f,
0xfe, 0x4e, 0x7e, 0x60, 0x90, 0x48, 0x26, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_pairing [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0xe3, 0x98, 0x73, 0x33, 0x87, 0xff, 0xff, 0xf2, 0xc9, 0x99, 0x33, 0x13, 0x3f, 0xff,
0xff, 0xf0, 0xc1, 0x98, 0x73, 0x03, 0x27, 0xff, 0xff, 0xf3, 0xc9, 0x98, 0x73, 0x23, 0x27, 0xff,
0xff, 0xf3, 0xc9, 0x99, 0x33, 0x33, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_fw_update [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x98, 0x70, 0xf1, 0xc3, 0x33, 0x38, 0x7f, 0xfc, 0x99, 0x32, 0x64, 0xe7, 0x31, 0x33, 0xff,
0xfc, 0x98, 0x72, 0x60, 0xe7, 0x30, 0x32, 0x7f, 0xfc, 0x99, 0xf2, 0x64, 0xe7, 0x32, 0x32, 0x7f,
0xfe, 0x39, 0xf0, 0xe4, 0xe7, 0x33, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x66, 0x1c, 0xe6, 0x73, 0x8e, 0x1c, 0x3f, 0xf9, 0xe6, 0x4c, 0x46, 0x53, 0x26, 0x4c, 0xff,
0xf8, 0x66, 0x1c, 0x06, 0x53, 0x06, 0x1c, 0x3f, 0xf9, 0xe6, 0x1c, 0xa6, 0x03, 0x26, 0x1c, 0xff,
0xf9, 0xe6, 0x4c, 0xe7, 0x27, 0x26, 0x4c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_version [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x99, 0x86, 0x1e, 0x19, 0xc7, 0x33, 0xff, 0xff, 0x99, 0x9e, 0x4c, 0xf9, 0x93, 0x13, 0xff,
0xff, 0xc3, 0x86, 0x1e, 0x39, 0x93, 0x03, 0xff, 0xff, 0xc3, 0x9e, 0x1f, 0x99, 0x93, 0x23, 0xff,
0xff, 0xe7, 0x86, 0x4c, 0x39, 0xc7, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_updating [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0x71, 0x7f, 0xff,
0xff, 0xff, 0x7f, 0xf5, 0xff, 0x75, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xf1, 0xff, 0x71, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x17, 0xd4, 0x7f, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x57, 0xd5, 0x7f, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x17, 0xd4, 0x7f, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x44, 0x71, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x57, 0x55, 0x75, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x47, 0x44, 0x71, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0x51, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x44, 0x51, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x54, 0x45, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x14, 0x54, 0x45, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0x60, 0x00, 0x00, 0x03, 0x7f, 0xff, 0xff, 0xff, 0x30, 0x00, 0x00, 0x07, 0x7f, 0xff,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x5c, 0x00, 0x00, 0x1c, 0x7f, 0xff,
0xff, 0xff, 0x56, 0x00, 0x00, 0x35, 0x7f, 0xff, 0xff, 0xff, 0x57, 0x00, 0x00, 0x74, 0x7f, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0xc0, 0x01, 0xd1, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x60, 0x03, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x44, 0x70, 0x07, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x5c, 0x1d, 0x44, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x56, 0x35, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x14, 0x57, 0xe5, 0x44, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0x55, 0x55, 0x55, 0x55, 0x7f, 0xff, 0xff, 0xff, 0x45, 0x44, 0x51, 0x51, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static unsigned char bm_def[] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x61, 0x10, 0x8c, 0x23, 0xc4, 0x3f, 0xff,
0xb5, 0xa7, 0xb7, 0xb5, 0xed, 0xed, 0xbf, 0xff, 0xb5, 0xb9, 0xb4, 0xb4, 0x6d, 0xed, 0xbf, 0xff,
0x85, 0xa1, 0x10, 0xb4, 0x21, 0x44, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe7, 0x1c, 0xfe, 0x7f, 0x8f, 0xf0, 0x00,
0x1f, 0xf7, 0x9d, 0xff, 0x7f, 0x9f, 0xf0, 0x00, 0x1c, 0x77, 0xfd, 0xc7, 0x73, 0xdc, 0x00, 0x00,
0x1f, 0xe7, 0xfd, 0xc7, 0x71, 0xdf, 0x00, 0x00, 0x1f, 0xe7, 0x7d, 0xc7, 0x71, 0xdf, 0x00, 0x00,
0x1c, 0x77, 0x3d, 0xc7, 0x73, 0xdc, 0x00, 0x00, 0x1c, 0x77, 0x1d, 0xff, 0x7f, 0x9f, 0xf0, 0x00,
0x1c, 0x77, 0x1c, 0xfe, 0x7f, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x62, 0x24, 0x49, 0x22, 0x4e, 0x44,
0x00, 0x24, 0x93, 0x66, 0xc9, 0x32, 0x44, 0x28, 0x00, 0x20, 0x92, 0xa5, 0x49, 0x2a, 0x44, 0x10,
0x00, 0x24, 0x92, 0x24, 0x49, 0x26, 0x44, 0x10, 0x00, 0x18, 0x62, 0x24, 0x46, 0x22, 0x44, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x9c, 0x44, 0x88, 0xc7, 0x1c, 0x00, 0x00, 0x10, 0x92, 0x6c, 0xa9, 0x24, 0x90,
0x00, 0x00, 0x1c, 0x9c, 0x54, 0xa9, 0xe7, 0x1c, 0x00, 0x00, 0x10, 0x94, 0x44, 0xa9, 0x25, 0x10,
0x00, 0x00, 0x10, 0x92, 0x44, 0x51, 0x24, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_def_lc [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x61, 0x10, 0x8c, 0x23, 0xc4, 0x3f, 0xff,
0xb5, 0xa7, 0xb7, 0xb5, 0xed, 0xed, 0xbf, 0xff, 0xb5, 0xb9, 0xb4, 0xb4, 0x6d, 0xed, 0xbf, 0xff,
0x85, 0xa1, 0x10, 0xb4, 0x21, 0x44, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe7, 0x1c, 0xfe, 0x7f, 0x8f, 0xf0, 0x00,
0x1f, 0xf7, 0x9d, 0xff, 0x7f, 0x9f, 0xf0, 0x00, 0x1c, 0x77, 0xfd, 0xc7, 0x73, 0xdc, 0x00, 0x00,
0x1f, 0xe7, 0xfd, 0xc7, 0x71, 0xdf, 0x00, 0x00, 0x1f, 0xe7, 0x7d, 0xc7, 0x71, 0xdf, 0x00, 0x00,
0x1c, 0x77, 0x3d, 0xc7, 0x73, 0xdc, 0x00, 0x00, 0x1c, 0x77, 0x1d, 0xff, 0x7f, 0x9f, 0xf0, 0x00,
0x1c, 0x77, 0x1c, 0xfe, 0x7f, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
0x2a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x8e, 0x39, 0x10, 0x61, 0x88, 0x91, 0x1c,
0x02, 0x49, 0x21, 0x90, 0x92, 0x4d, 0x9b, 0x20, 0x02, 0x4e, 0x39, 0x50, 0x82, 0x4a, 0x95, 0x18,
0x02, 0x48, 0x21, 0x30, 0x92, 0x48, 0x91, 0x04, 0x01, 0x88, 0x39, 0x10, 0x61, 0x88, 0x91, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xc8, 0x8e, 0x73, 0x91, 0x1c, 0x00, 0x00, 0x02, 0x05, 0x10, 0x22, 0x1b, 0x20,
0x00, 0x00, 0x01, 0x82, 0x0c, 0x23, 0x95, 0x18, 0x00, 0x00, 0x00, 0x42, 0x02, 0x22, 0x11, 0x04,
0x00, 0x00, 0x03, 0x82, 0x1c, 0x23, 0x91, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char bm_hwok [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf2, 0x71, 0xc3, 0x87, 0x39, 0xc7, 0x0e, 0x1f, 0xf2, 0x64, 0xc9, 0x93, 0x29, 0x93, 0x26, 0x7f,
0xf0, 0x60, 0xc3, 0x93, 0x29, 0x83, 0x0e, 0x1f, 0xf2, 0x64, 0xc3, 0x93, 0x01, 0x93, 0x0e, 0x7f,
0xf2, 0x64, 0xc9, 0x87, 0x93, 0x93, 0x26, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x33, 0x30, 0xff, 0x8e, 0x4f, 0xff,
0xff, 0xf3, 0x13, 0x39, 0xff, 0x26, 0x1f, 0xff, 0xff, 0xf3, 0x03, 0x39, 0xff, 0x26, 0x3f, 0xff,
0xff, 0xf3, 0x23, 0x39, 0xff, 0x26, 0x1f, 0xff, 0xff, 0xf3, 0x33, 0x39, 0xff, 0x8e, 0x4f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc3, 0x0e, 0x67, 0xf8, 0x70, 0xe3, 0x87, 0x33, 0xe7, 0x27, 0x0f, 0xf9, 0x33, 0xc9, 0x93, 0x87,
0xe7, 0x0f, 0x9f, 0xf8, 0x70, 0xc1, 0x93, 0xcf, 0xe7, 0x0f, 0x0f, 0xf8, 0x73, 0xc9, 0x93, 0xcf,
0xe7, 0x26, 0x67, 0xf9, 0x30, 0xc9, 0x87, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_console_active [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x8e, 0x67, 0x0e, 0x39, 0xe1, 0xff,
0xff, 0x93, 0x26, 0x26, 0x7c, 0x99, 0xe7, 0xff, 0xff, 0x9f, 0x26, 0x07, 0x1c, 0x99, 0xe1, 0xff,
0xff, 0x93, 0x26, 0x47, 0xcc, 0x99, 0xe7, 0xff, 0xff, 0xc7, 0x8e, 0x66, 0x1e, 0x38, 0x61, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3c, 0x70, 0xcc, 0xcc, 0x3f, 0xff,
0xff, 0xfc, 0x99, 0x39, 0xcc, 0xcc, 0xff, 0xff, 0xff, 0xfc, 0x19, 0xf9, 0xce, 0x1c, 0x3f, 0xff,
0xff, 0xfc, 0x99, 0x39, 0xce, 0x1c, 0xff, 0xff, 0xff, 0xfc, 0x9c, 0x79, 0xcf, 0x3c, 0x3f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_checks [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0x0c, 0x99, 0xc7, 0x0f,
0xe6, 0x00, 0x7f, 0x93, 0x3c, 0x99, 0x93, 0x3f, 0xe6, 0x00, 0x7f, 0x93, 0x0e, 0x39, 0x9f, 0x0f,
0xff, 0xff, 0xff, 0x93, 0x3e, 0x39, 0x93, 0x3f, 0xff, 0xff, 0xff, 0x87, 0x0f, 0x79, 0xc7, 0x0f,
0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x39, 0x30, 0xe3, 0x93, 0x87,
0xe6, 0x00, 0x7c, 0x99, 0x33, 0xc9, 0x87, 0x3f, 0xe6, 0x00, 0x7c, 0xf8, 0x30, 0xcf, 0x8f, 0x8f,
0xff, 0xff, 0xfc, 0x99, 0x33, 0xc9, 0x87, 0xe7, 0xff, 0xff, 0xfe, 0x39, 0x30, 0xe3, 0x93, 0x0f,
0xe6, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x00, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9c, 0x3c, 0x78, 0x70, 0xc3, 0x0f,
0xe6, 0x0d, 0x3c, 0x99, 0x33, 0xe7, 0xcf, 0x27, 0xe6, 0x04, 0x7c, 0x38, 0x38, 0xf1, 0xc3, 0x27,
0xff, 0xfe, 0xfc, 0xf9, 0x3e, 0x7c, 0xcf, 0x27, 0xff, 0xff, 0xfc, 0xf9, 0x30, 0xe1, 0xc3, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_frame [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x40, 0x02, 0x0f, 0xff, 0xfc,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x1e, 0x40, 0x02, 0x78, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x3f, 0xff, 0xf2, 0x40, 0x02, 0x4f, 0xff, 0xfc,
0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x02, 0x40, 0x02, 0x40, 0x00, 0x00, 0x3f, 0xff, 0xf2, 0x40, 0x02, 0x4f, 0xff, 0xfc,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04, 0x20, 0x00, 0x12, 0x40, 0x02, 0x48, 0x00, 0x04,
0x20, 0x00, 0x1e, 0x40, 0x02, 0x78, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04,
0x20, 0x00, 0x10, 0x40, 0x02, 0x08, 0x00, 0x04, 0x3f, 0xff, 0xf0, 0x40, 0x02, 0x0f, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x1c,
0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xaa, 0x8a, 0xaa, 0x80
};
const unsigned char bm_online [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x1c, 0x66, 0x61, 0x8c, 0x24, 0x90, 0x87,
0xe6, 0x49, 0x22, 0x4f, 0x24, 0xe4, 0x93, 0x93, 0xe6, 0x18, 0x20, 0x63, 0x3c, 0x26, 0x30, 0x87,
0xe6, 0x19, 0x24, 0x79, 0x24, 0xe6, 0x33, 0x87, 0xe6, 0x49, 0x26, 0x43, 0x8c, 0x27, 0x70, 0x93,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xe6, 0x73, 0xe7, 0x33, 0x87, 0xff,
0xff, 0xe4, 0xe2, 0x73, 0xe7, 0x13, 0x9f, 0xff, 0xff, 0xe4, 0xe0, 0x73, 0xe7, 0x03, 0x87, 0xff,
0xff, 0xe4, 0xe4, 0x73, 0xe7, 0x23, 0x9f, 0xff, 0xff, 0xf1, 0xe6, 0x70, 0xe7, 0x33, 0x87, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_fw_corrupt [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x30, 0xe7, 0x33, 0x9c, 0x70, 0xe1, 0xff,
0xcf, 0x32, 0x62, 0x32, 0x99, 0x32, 0x67, 0xff, 0xc3, 0x30, 0xe0, 0x32, 0x98, 0x30, 0xe1, 0xff,
0xcf, 0x30, 0xe5, 0x30, 0x19, 0x30, 0xe7, 0xff, 0xcf, 0x32, 0x67, 0x39, 0x39, 0x32, 0x61, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xc7, 0x0e, 0x1c, 0x98, 0x70, 0xfc, 0xff,
0xc9, 0x93, 0x26, 0x4c, 0x99, 0x39, 0xfb, 0x7f, 0xcf, 0x93, 0x0e, 0x1c, 0x98, 0x79, 0xfb, 0x7f,
0xc9, 0x93, 0x0e, 0x1c, 0x99, 0xf9, 0xf7, 0xbf, 0xe3, 0xc7, 0x26, 0x4e, 0x39, 0xf9, 0xf4, 0xbf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec, 0xdf,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xef,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xf7,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfb,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
const unsigned char bm_plug [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x7f, 0x80, 0x55, 0xfc, 0x00, 0xaa, 0xfc, 0x00, 0x00,
0x7f, 0x80, 0x00, 0x1c, 0x00
};
const unsigned char bm_hg_low [] PROGMEM = {
0xf8, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0xf8, 0xf8
};
const unsigned char bm_hg_high [] PROGMEM = {
0xf8, 0x88, 0xf8, 0x70, 0x20, 0x70, 0xf8, 0xf8, 0xf8
};
const unsigned char bm_n_uh [] PROGMEM = {
0x07, 0x27, 0x27, 0x27, 0x07, 0x8f, 0x8f, 0xcf, 0xcf, 0xcf, 0x07, 0xe7, 0x07, 0x3f, 0x07, 0x07,
0xe7, 0xc7, 0xe7, 0x07, 0x27, 0x27, 0x07, 0xe7, 0xe7, 0x07, 0x3f, 0x07, 0xe7, 0x07, 0x07, 0x3f,
0x07, 0x27, 0x07, 0x07, 0xc7, 0xcf, 0x9f, 0x1f, 0x07, 0x27, 0x07, 0x27, 0x07, 0x07, 0x27, 0x07,
0xe7, 0xe7
};
const unsigned char bm_dot_sqr [] PROGMEM = {
0xaa, 0xd5, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00,
0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00,
0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0xaa, 0xd5, 0x40
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Graphics/Bitmaps/frame.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
Graphics/Bitmaps/plug.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

BIN
Graphics/Design/Text.xcf Normal file

Binary file not shown.

BIN
Graphics/Design/banners.kra Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Graphics/Design/cs.kra Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Graphics/Design/frame.kra Normal file

Binary file not shown.

BIN
Graphics/Design/icons.kra Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Graphics/Design/plug.kra Normal file

Binary file not shown.

BIN
Graphics/Design/r_icon.kra Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

327
Makefile
View File

@ -1,4 +1,4 @@
# Copyright (C) 2023, Mark Qvist
# Copyright (C) 2024, Mark Qvist
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -13,36 +13,47 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
ESP_IDF_VER = 2.0.17
# Version 2.0.17 of the Arduino ESP core is based on ESP-IDF v4.4.7
ARDUINO_ESP_CORE_VER = 2.0.17
V ?= 0
VFLAG =
ifeq "$(V)" "1"
VFLAG =-v
endif
COMMON_BUILD_FLAGS = $(VFLAG) -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152"
COMMON_ESP_UPLOAD_FlAGS = $(VFLAG) --chip esp32 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB 0x210000
all: release
clean:
-rm -r ./build
-rm ./Release/rnode_firmware*
-rm -rf ./build
-rm -f ./Release/rnode_firmware*
prep: prep-esp32 prep-nrf prep-samd
prep: prep-esp32 prep-nrf
prep-index:
arduino-cli core update-index --config-file arduino-cli.yaml
prep-esp32:
arduino-cli core update-index --config-file arduino-cli.yaml
arduino-cli core install esp32:esp32@2.0.17 --config-file arduino-cli.yaml
arduino-cli core install esp32:esp32@$(ARDUINO_ESP_CORE_VER) --config-file arduino-cli.yaml
arduino-cli lib install "Adafruit SSD1306"
arduino-cli lib install "Adafruit SH110X"
arduino-cli lib install "Adafruit ST7735 and ST7789 Library"
arduino-cli lib install "Adafruit NeoPixel"
arduino-cli lib install "XPowersLib"
arduino-cli lib install "Crypto"
arduino-cli lib install "Adafruit NeoPixel"
pip install pyserial rns --upgrade --user --break-system-packages # This looks scary, but it's actually just telling pip to install packages as a user instead of trying to install them systemwide, which bypasses the "externally managed environment" error.
prep-samd:
arduino-cli core update-index --config-file arduino-cli.yaml
arduino-cli core install adafruit:samd --config-file arduino-cli.yaml
prep-nrf:
arduino-cli core update-index --config-file arduino-cli.yaml
arduino-cli core install adafruit:nrf52 --config-file arduino-cli.yaml
arduino-cli core install rakwireless:nrf52 --config-file arduino-cli.yaml
arduino-cli lib install "Crypto"
arduino-cli lib install "Adafruit GFX Library"
arduino-cli lib install "GxEPD2"
pip install pyserial rns --upgrade --user --break-system-packages
pip install pyserial rns --upgrade --user --break-system-packages # This looks scary, but it's actually just telling pip to install packages as a user instead of trying to install them systemwide, which bypasses the "externally managed environment" error.
pip install adafruit-nrfutil --upgrade --user --break-system-packages # This looks scary, but it's actually just telling pip to install packages as a user instead of trying to install them systemwide, which bypasses the "externally managed environment" error.
console-site:
@ -55,137 +66,161 @@ spiffs-image:
upload-spiffs:
@echo Deploying SPIFFS image...
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyACM0) $(COMMON_UPLOAD_FLAGS) ./Release/console_image.bin
firmware-tbeam:
arduino-cli compile --fqbn esp32:esp32:t-beam -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\""
firmware: $(shell grep ^firmware- Makefile | cut -d: -f1)
firmware-tbeam_sx126x:
arduino-cli compile --fqbn esp32:esp32:t-beam -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DMODEM=0x03\""
check_bt_buffers:
@./esp32_btbufs.py ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/libraries/BluetoothSerial/src/BluetoothSerial.cpp
firmware-tbeam: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:t-beam $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DBOARD_VARIANT=0xE4\""
firmware-tbeam_sx1262: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:t-beam $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DBOARD_VARIANT=0xE8\""
firmware-techo: firmware-techo4 firmware-techo9
firmware-techo4:
arduino-cli compile --fqbn adafruit:nrf52:pca10056 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x43\" \"-DBOARD_VARIANT=0x16\""
arduino-cli compile --fqbn adafruit:nrf52:pca10056 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x43\" \"-DBOARD_VARIANT=0x16\""
firmware-techo9:
arduino-cli compile --fqbn adafruit:nrf52:pca10056 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x43\" \"-DBOARD_VARIANT=0x17\""
arduino-cli compile --fqbn adafruit:nrf52:pca10056 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x43\" \"-DBOARD_VARIANT=0x17\""
firmware-t3s3_sx1262:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_VARIANT=0xA1\""
firmware-t3s3:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_VARIANT=0xAB\""
firmware-t3s3_sx126x:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_VARIANT=0xA1\""
firmware-t3s3_sx1280_pa:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_VARIANT=0xA5\""
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_VARIANT=0xAB\""
firmware-lora32_v10:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\""
firmware-e22_esp32:
arduino-cli compile --fqbn esp32:esp32:esp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x44\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v10_extled:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v10: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\""
firmware-lora32_v20:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v10_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v21:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\""
firmware-lora32_v20: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v21_extled:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DEXTERNAL_LEDS=true\""
firmware-lora32_v21: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\""
firmware-lora32_v21_tcxo:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DENABLE_TCXO=true\""
firmware-lora32_v21_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DEXTERNAL_LEDS=true\""
firmware-heltec32_v2:
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\""
firmware-lora32_v21_tcxo: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DENABLE_TCXO=true\""
firmware-heltec32_v2_extled:
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\" \"-DEXTERNAL_LEDS=true\""
firmware-heltec32_v2: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\""
firmware-heltec32_v2_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\" \"-DEXTERNAL_LEDS=true\""
firmware-heltec32_v3:
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\""
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V3 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3A\""
firmware-rnode_ng_20:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x40\""
firmware-rnode_ng_20: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x40\""
firmware-rnode_ng_21:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x41\""
firmware-rnode_ng_21: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x41\""
firmware-featheresp32:
arduino-cli compile --fqbn esp32:esp32:featheresp32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x34\""
firmware-featheresp32: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:featheresp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x34\""
firmware-genericesp32:
arduino-cli compile --fqbn esp32:esp32:esp32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x35\""
firmware-genericesp32: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:esp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x35\""
firmware-rak4631:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x12\""
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x12\""
firmware-rak4631_sx1280:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x14\""
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x14\""
firmware-freenode:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x52\" \"-DBOARD_VARIANT=0x21\""
firmware-opencom-xl:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x52\" \"-DBOARD_VARIANT=0x21\""
upload-tbeam:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:t-beam
@sleep 1
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.t-beam/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyACM0) $(COMMON_ESP_UPLOAD_FLAGS) ./Release/console_image.bin
upload-techo:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn adafruit:nrf52:pca10056
unzip -o build/adafruit.nrf52.pca10056/RNode_Firmware_CE.ino.zip -d build/adafruit.nrf52.pca10056
#rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/adafruit.nrf52.pca10056/RNode_Firmware_CE.ino.bin | grep -o '^\S*')
../Reticulum/RNS/Utilities/rnodeconf.py $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/adafruit.nrf52.pca10056/RNode_Firmware_CE.ino.bin | grep -o '^\S*')
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/adafruit.nrf52.pca10056/RNode_Firmware_CE.ino.bin | grep -o '^\S*')
upload-lora32_v10:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:ttgo-lora32
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-lora32_v20:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:ttgo-lora32
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-lora32_v21:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:ttgo-lora32
@sleep 1
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyACM0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-heltec32_v2:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:heltec_wifi_lora_32_V2
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-heltec32_v3:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:heltec_wifi_lora_32_V3
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.heltec_wifi_lora_32_V3/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32-s3 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) --chip esp32-s3 --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 $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:esp32s3
@sleep 1
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.esp32s3/RNode_Firmware_CE.ino.bin)
@sleep 3
python ./Release/esptool/esptool.py --chip esp32-s3 --port $(or $(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
upload-tbeam_supreme:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:esp32s3
@sleep 1
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.esp32s3/RNode_Firmware_CE.ino.bin)
@sleep 3
python ./Release/esptool/esptool.py --chip esp32-s3 --port $(or $(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
upload-rnode_ng_20:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:ttgo-lora32
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-rnode_ng_21:
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:ttgo-lora32
@sleep 1
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyACM0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
upload-t3s3:
@echo
@ -193,7 +228,7 @@ upload-t3s3:
@read
arduino-cli upload -p $(or $(port), /dev/ttyACM0) --fqbn esp32:esp32:esp32s3
@sleep 2
python3 ./Release/esptool/esptool.py --chip esp32s3 --port $(or $(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
python ./Release/esptool/esptool.py --chip esp32s3 --port $(or $(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
@echo
@echo Press the RESET button on the board now, and hit enter
@read
@ -205,9 +240,9 @@ upload-featheresp32:
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.featheresp32/opencom_xl_firmware.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --chip esp32 --port $(or $(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
python ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_UPLOAD_FLAGS) ./Release/console_image.bin
upload-freenode:
upload-opencom-xl:
arduino-cli upload -p /dev/ttyACM0 --fqbn rakwireless:nrf52:WisCoreRAK4631Board
unzip -o build/rakwireless.nrf52.WisCoreRAK4631Board/opencom_xl_firmware.ino.zip -d build/rakwireless.nrf52.WisCoreRAK4631Board
rnodeconf $(or $(port), /dev/ttyACM0) --firmware-hash $$(sha256sum ./build/rakwireless.nrf52.WisCoreRAK4631Board/opencom_xl_firmware.ino.bin | grep -o '^\S*')
@ -218,15 +253,20 @@ upload-freenode:
@sleep 3
python3 rnodeconf.py /dev/ttyACM0 --set-firmware-length $$(ls -l ./build/rakwireless.nrf52.WisCoreRAK4631Board/opencom_xl_firmware.ino.bin | awk '{print $$5}')
release: release-all
upload-e22_esp32:
arduino-cli upload -p $(or $(port), /dev/ttyUSB0) --fqbn esp32:esp32:esp32
@sleep 1
rnodeconf $(or $(port), /dev/ttyUSB0) --firmware-hash $$(./partition_hashes ./build/esp32.esp32.esp32/RNode_Firmware_CE.ino.bin)
@sleep 3
python3 ./Release/esptool/esptool.py --port $(or $(port), /dev/ttyUSB0) $(COMMON_ESP_UPLOAD_FlAGS) ./Release/console_image.bin
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-rnode_ng_20 release-rnode_ng_21 release-t3s3 release-hashes
release: console-site spiffs-image $(shell grep ^release- Makefile | cut -d: -f1)
release-hashes:
python3 ./release_hashes.py > ./Release/release.json
release-tbeam:
arduino-cli compile --fqbn esp32:esp32:t-beam -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\""
release-tbeam: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:t-beam $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DBOARD_VARIANT=0xE4\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_tbeam.boot_app0
cp build/esp32.esp32.t-beam/opencom_xl_firmware.ino.bin build/rnode_firmware_tbeam.bin
cp build/esp32.esp32.t-beam/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_tbeam.bootloader
@ -234,8 +274,8 @@ release-tbeam:
zip --junk-paths ./Release/rnode_firmware_tbeam.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_tbeam.boot_app0 build/rnode_firmware_tbeam.bin build/rnode_firmware_tbeam.bootloader build/rnode_firmware_tbeam.partitions
rm -r build
release-tbeam_sx1262:
arduino-cli compile --fqbn esp32:esp32:t-beam -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DMODEM=0x03\""
release-tbeam_sx1262: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:t-beam $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x33\" \"-DBOARD_MODEL=E8\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_tbeam_sx1262.boot_app0
cp build/esp32.esp32.t-beam/opencom_xl_firmware.ino.bin build/rnode_firmware_tbeam_sx1262.bin
cp build/esp32.esp32.t-beam/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_tbeam_sx1262.bootloader
@ -243,8 +283,8 @@ release-tbeam_sx1262:
zip --junk-paths ./Release/rnode_firmware_tbeam_sx1262.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_tbeam_sx1262.boot_app0 build/rnode_firmware_tbeam_sx1262.bin build/rnode_firmware_tbeam_sx1262.bootloader build/rnode_firmware_tbeam_sx1262.partitions
rm -r build
release-lora32_v10:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\""
release-lora32_v10: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v10.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v10.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v10.bootloader
@ -252,8 +292,8 @@ release-lora32_v10:
zip --junk-paths ./Release/rnode_firmware_lora32v10.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v10.boot_app0 build/rnode_firmware_lora32v10.bin build/rnode_firmware_lora32v10.bootloader build/rnode_firmware_lora32v10.partitions
rm -r build
release-lora32_v20:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\""
release-lora32_v20: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v20.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v20.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v20.bootloader
@ -261,8 +301,8 @@ release-lora32_v20:
zip --junk-paths ./Release/rnode_firmware_lora32v20.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v20.boot_app0 build/rnode_firmware_lora32v20.bin build/rnode_firmware_lora32v20.bootloader build/rnode_firmware_lora32v20.partitions
rm -r build
release-lora32_v21:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\""
release-lora32_v21: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v21.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v21.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v21.bootloader
@ -270,8 +310,8 @@ release-lora32_v21:
zip --junk-paths ./Release/rnode_firmware_lora32v21.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v21.boot_app0 build/rnode_firmware_lora32v21.bin build/rnode_firmware_lora32v21.bootloader build/rnode_firmware_lora32v21.partitions
rm -r build
release-lora32_v10_extled:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\" \"-DEXTERNAL_LEDS=true\""
release-lora32_v10_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x39\" \"-DEXTERNAL_LEDS=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v10.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v10.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v10.bootloader
@ -279,8 +319,8 @@ release-lora32_v10_extled:
zip --junk-paths ./Release/rnode_firmware_lora32v10.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v10.boot_app0 build/rnode_firmware_lora32v10.bin build/rnode_firmware_lora32v10.bootloader build/rnode_firmware_lora32v10.partitions
rm -r build
release-lora32_v20_extled:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\" \"-DEXTERNAL_LEDS=true\""
release-lora32_v20_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x36\" \"-DEXTERNAL_LEDS=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v20.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v20.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v20.bootloader
@ -288,8 +328,8 @@ release-lora32_v20_extled:
zip --junk-paths ./Release/rnode_firmware_lora32v20_extled.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v20.boot_app0 build/rnode_firmware_lora32v20.bin build/rnode_firmware_lora32v20.bootloader build/rnode_firmware_lora32v20.partitions
rm -r build
release-lora32_v21_extled:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DEXTERNAL_LEDS=true\""
release-lora32_v21_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DEXTERNAL_LEDS=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v21.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v21.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v21.bootloader
@ -297,8 +337,8 @@ release-lora32_v21_extled:
zip --junk-paths ./Release/rnode_firmware_lora32v21_extled.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v21.boot_app0 build/rnode_firmware_lora32v21.bin build/rnode_firmware_lora32v21.bootloader build/rnode_firmware_lora32v21.partitions
rm -r build
release-lora32_v21_tcxo:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DENABLE_TCXO=true\""
release-lora32_v21_tcxo: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x37\" \"-DENABLE_TCXO=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_lora32v21_tcxo.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_lora32v21_tcxo.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_lora32v21_tcxo.bootloader
@ -306,53 +346,51 @@ release-lora32_v21_tcxo:
zip --junk-paths ./Release/rnode_firmware_lora32v21_tcxo.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_lora32v21_tcxo.boot_app0 build/rnode_firmware_lora32v21_tcxo.bin build/rnode_firmware_lora32v21_tcxo.bootloader build/rnode_firmware_lora32v21_tcxo.partitions
rm -r build
release-heltec32_v2:
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\""
release-heltec32_v2: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_heltec32v2.boot_app0
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.bin build/rnode_firmware_heltec32v2.bin
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_heltec32v2.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.partitions.bin build/rnode_firmware_heltec32v2.partitions
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
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware_CE.ino.bin build/rnode_firmware_heltec32v2.bin
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware_CE.ino.bootloader.bin build/rnode_firmware_heltec32v2.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware_CE.ino.partitions.bin build/rnode_firmware_heltec32v2.partitions
release-heltec32_v3:
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/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_heltec32v3.boot_app0
cp build/esp32.esp32.heltec_wifi_lora_32_V3/opencom_xl_firmware.ino.bin build/rnode_firmware_heltec32v3.bin
cp build/esp32.esp32.heltec_wifi_lora_32_V3/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_heltec32v3.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V3/opencom_xl_firmware.ino.partitions.bin build/rnode_firmware_heltec32v3.partitions
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V3 $(COMMON_BUILD_FLAGS) --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
cp build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_heltec32v3.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V3/RNode_Firmware.ino.partitions.bin build/rnode_firmware_heltec32v3.partitions
zip --junk-paths ./Release/rnode_firmware_heltec32v3.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_heltec32v3.boot_app0 build/rnode_firmware_heltec32v3.bin build/rnode_firmware_heltec32v3.bootloader build/rnode_firmware_heltec32v3.partitions
rm -r build
release-heltec32_v2_extled:
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\" \"-DEXTERNAL_LEDS=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_heltec32v2.boot_app0
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.bin build/rnode_firmware_heltec32v2.bin
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_heltec32v2.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V2/opencom_xl_firmware.ino.partitions.bin build/rnode_firmware_heltec32v2.partitions
release-heltec32_v2_extled: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:heltec_wifi_lora_32_V2 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x38\" \"-DEXTERNAL_LEDS=true\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_heltec32v2.boot_app0
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware.ino.bin build/rnode_firmware_heltec32v2.bin
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_heltec32v2.bootloader
cp build/esp32.esp32.heltec_wifi_lora_32_V2/RNode_Firmware.ino.partitions.bin build/rnode_firmware_heltec32v2.partitions
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-rnode_ng_20:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x40\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_ng20.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_ng20.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_ng20.bootloader
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.partitions.bin build/rnode_firmware_ng20.partitions
release-rnode_ng_20: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x40\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_ng20.boot_app0
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.bin build/rnode_firmware_ng20.bin
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_ng20.bootloader
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.partitions.bin build/rnode_firmware_ng20.partitions
zip --junk-paths ./Release/rnode_firmware_ng20.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_ng20.boot_app0 build/rnode_firmware_ng20.bin build/rnode_firmware_ng20.bootloader build/rnode_firmware_ng20.partitions
rm -r build
release-rnode_ng_21:
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x41\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_ng21.boot_app0
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bin build/rnode_firmware_ng21.bin
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_ng21.bootloader
cp build/esp32.esp32.ttgo-lora32/opencom_xl_firmware.ino.partitions.bin build/rnode_firmware_ng21.partitions
release-rnode_ng_21: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:ttgo-lora32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x41\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_ng21.boot_app0
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.bin build/rnode_firmware_ng21.bin
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_ng21.bootloader
cp build/esp32.esp32.ttgo-lora32/RNode_Firmware.ino.partitions.bin build/rnode_firmware_ng21.partitions
zip --junk-paths ./Release/rnode_firmware_ng21.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_ng21.boot_app0 build/rnode_firmware_ng21.bin build/rnode_firmware_ng21.bootloader build/rnode_firmware_ng21.partitions
rm -r build
release-t3s3:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\""
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_MODEL=0xAB\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_t3s3.boot_app0
cp build/esp32.esp32.esp32s3/opencom_xl_firmware.ino.bin build/rnode_firmware_t3s3.bin
cp build/esp32.esp32.esp32s3/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_t3s3.bootloader
@ -360,8 +398,45 @@ release-t3s3:
zip --junk-paths ./Release/rnode_firmware_t3s3.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_t3s3.boot_app0 build/rnode_firmware_t3s3.bin build/rnode_firmware_t3s3.bootloader build/rnode_firmware_t3s3.partitions
rm -r build
release-featheresp32:
arduino-cli compile --fqbn esp32:esp32:featheresp32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x34\""
release-e22_esp32:
arduino-cli compile --fqbn esp32:esp32:esp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x44\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_esp32_e22.boot_app0
cp build/esp32.esp32.esp32/RNode_Firmware_CE.ino.bin build/rnode_firmware_esp32_e22.bin
cp build/esp32.esp32.esp32/RNode_Firmware_CE.ino.bootloader.bin build/rnode_firmware_esp32_e22.bootloader
cp build/esp32.esp32.esp32/RNode_Firmware_CE.ino.partitions.bin build/rnode_firmware_esp32_e22.partitions
zip --junk-paths ./Release/rnode_firmware_esp32_e22.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_esp32_e22.boot_app0 build/rnode_firmware_esp32_e22.bin build/rnode_firmware_esp32_e22.bootloader build/rnode_firmware_esp32_e22.partitions
rm -r build
release-t3s3_sx126x:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x42\" \"-DBOARD_MODEL=0xA1\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_t3s3_sx126x.boot_app0
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bin build/rnode_firmware_t3s3_sx126x.bin
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_t3s3_sx126x.bootloader
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.partitions.bin build/rnode_firmware_t3s3_sx126x.partitions
zip --junk-paths ./Release/rnode_firmware_t3s3_sx126x.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_t3s3_sx126x.boot_app0 build/rnode_firmware_t3s3_sx126x.bin build/rnode_firmware_t3s3_sx126x.bootloader build/rnode_firmware_t3s3_sx126x.partitions
rm -r build
release-tdeck:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3B\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_tdeck.boot_app0
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bin build/rnode_firmware_tdeck.bin
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_tdeck.bootloader
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.partitions.bin build/rnode_firmware_tdeck.partitions
zip --junk-paths ./Release/rnode_firmware_tdeck.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_tdeck.boot_app0 build/rnode_firmware_tdeck.bin build/rnode_firmware_tdeck.bootloader build/rnode_firmware_tdeck.partitions
rm -r build
release-tbeam_supreme:
arduino-cli compile --fqbn "esp32:esp32:esp32s3:CDCOnBoot=cdc" $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x3D\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ARDUINO_ESP_CORE_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_tbeam_supreme.boot_app0
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bin build/rnode_firmware_tbeam_supreme.bin
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.bootloader.bin build/rnode_firmware_tbeam_supreme.bootloader
cp build/esp32.esp32.esp32s3/RNode_Firmware.ino.partitions.bin build/rnode_firmware_tbeam_supreme.partitions
zip --junk-paths ./Release/rnode_firmware_tbeam_supreme.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_tbeam_supreme.boot_app0 build/rnode_firmware_tbeam_supreme.bin build/rnode_firmware_tbeam_supreme.bootloader build/rnode_firmware_tbeam_supreme.partitions
rm -r build
release-featheresp32: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:featheresp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x34\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_featheresp32.boot_app0
cp build/esp32.esp32.featheresp32/opencom_xl_firmware.ino.bin build/rnode_firmware_featheresp32.bin
cp build/esp32.esp32.featheresp32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_featheresp32.bootloader
@ -369,8 +444,8 @@ release-featheresp32:
zip --junk-paths ./Release/rnode_firmware_featheresp32.zip ./Release/esptool/esptool.py ./Release/console_image.bin build/rnode_firmware_featheresp32.boot_app0 build/rnode_firmware_featheresp32.bin build/rnode_firmware_featheresp32.bootloader build/rnode_firmware_featheresp32.partitions
rm -r build
release-genericesp32:
arduino-cli compile --fqbn esp32:esp32:esp32 -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x35\""
release-genericesp32: check_bt_buffers
arduino-cli compile --fqbn esp32:esp32:esp32 $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x35\""
cp ~/.arduino15/packages/esp32/hardware/esp32/$(ESP_IDF_VER)/tools/partitions/boot_app0.bin build/rnode_firmware_esp32_generic.boot_app0
cp build/esp32.esp32.esp32/opencom_xl_firmware.ino.bin build/rnode_firmware_esp32_generic.bin
cp build/esp32.esp32.esp32/opencom_xl_firmware.ino.bootloader.bin build/rnode_firmware_esp32_generic.bootloader
@ -384,12 +459,16 @@ release-freenode:
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/opencom_xl_firmware.hex Release/rnode_firmware_opencom_xl.zip
release-rak4631:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x12\""
cp build/rakwireless.nrf52.WisCoreRAK4631Board/opencom_xl_firmware.ino.hex build/rnode_firmware_rak4631.hex
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x12\""
cp build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.hex build/rnode_firmware_rak4631.hex
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/rnode_firmware_rak4631.hex Release/rnode_firmware_rak4631.zip
release-rak4631_sx1280:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board -e --build-property "build.partitions=no_ota" --build-property "upload.maximum_size=2097152" --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x14\""
cp build/rakwireless.nrf52.WisCoreRAK4631Board/opencom_xl_firmware.ino.hex build/rnode_firmware_rak4631_sx1280.hex
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x51\" \"-DBOARD_VARIANT=0x14\""
cp build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.hex build/rnode_firmware_rak4631_sx1280.hex
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/rnode_firmware_rak4631_sx1280.hex Release/rnode_firmware_rak4631_sx1280.zip
release-opencom-xl:
arduino-cli compile --fqbn rakwireless:nrf52:WisCoreRAK4631Board $(COMMON_BUILD_FLAGS) --build-property "compiler.cpp.extra_flags=\"-DBOARD_MODEL=0x52\" \"-DBOARD_VARIANT=0x21\""
cp build/rakwireless.nrf52.WisCoreRAK4631Board/RNode_Firmware_CE.ino.hex build/rnode_firmware_opencom_xl.hex
adafruit-nrfutil dfu genpkg --dev-type 0x0052 --application build/rnode_firmware_opencom_xl.hex Release/rnode_firmware_opencom_xl.zip

250
Power.h
View File

@ -1,9 +1,28 @@
#if BOARD_MODEL == BOARD_TBEAM
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#if BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_TBEAM_S_V1
#include <XPowersLib.h>
XPowersLibInterface* PMU = NULL;
#ifndef PMU_WIRE_PORT
#define PMU_WIRE_PORT Wire
#if BOARD_MODEL == BOARD_TBEAM_S_V1
#define PMU_WIRE_PORT Wire1
#else
#define PMU_WIRE_PORT Wire
#endif
#endif
#define BAT_V_MIN 3.15
@ -28,8 +47,6 @@
pmuInterrupt = true;
}
#elif BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1
#define BAT_C_SAMPLES 7
#define BAT_D_SAMPLES 2
#define BAT_V_MIN 3.15
#define BAT_V_MAX 4.3
#define BAT_V_CHG 4.48
@ -44,26 +61,61 @@
int bat_charged_samples = 0;
bool bat_voltage_dropping = false;
float bat_delay_v = 0;
#elif BOARD_MODEL == BOARD_FREENODE
#include "nrfx_power.h"
#define BAT_C_SAMPLES 7
#define BAT_D_SAMPLES 2
#define BAT_V_MIN 2.75
#define BAT_V_MAX 4.2
#define BAT_V_FLOAT 4.22
#define BAT_SAMPLES 5
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12 - bit ADC resolution = 3000mV / 4096
#define VBAT_DIVIDER_COMP (1.73) // Compensation factor for the VBAT divider
#define VBAT_MV_PER_LSB_FIN (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
#define PIN_VBAT WB_A0
float bat_p_samples[BAT_SAMPLES];
float bat_v_samples[BAT_SAMPLES];
uint8_t bat_samples_count = 0;
int bat_discharging_samples = 0;
int bat_charging_samples = 0;
int bat_charged_samples = 0;
bool bat_voltage_dropping = false;
float bat_delay_v = 0;
float bat_state_change_v = 0;
#elif BOARD_MODEL == BOARD_OPENCOM_XL
#include "nrfx_power.h"
#define BAT_C_SAMPLES 7
#define BAT_D_SAMPLES 2
#define BAT_V_MIN 2.75
#define BAT_V_MAX 4.2
#define BAT_V_FLOAT 4.22
#define BAT_SAMPLES 5
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12 - bit ADC resolution = 3000mV / 4096
#define VBAT_DIVIDER_COMP (1.73) // Compensation factor for the VBAT divider
#define VBAT_MV_PER_LSB_FIN (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
#define PIN_VBAT WB_A0
float bat_p_samples[BAT_SAMPLES];
float bat_v_samples[BAT_SAMPLES];
uint8_t bat_samples_count = 0;
int bat_discharging_samples = 0;
int bat_charging_samples = 0;
int bat_charged_samples = 0;
bool bat_voltage_dropping = false;
float bat_delay_v = 0;
#elif BOARD_MODEL == BOARD_TDECK
#define BAT_V_MIN 3.15
#define BAT_V_MAX 4.3
#define BAT_V_CHG 4.48
#define BAT_V_FLOAT 4.33
#define BAT_SAMPLES 5
const uint8_t pin_vbat = 4;
float bat_p_samples[BAT_SAMPLES];
float bat_v_samples[BAT_SAMPLES];
uint8_t bat_samples_count = 0;
int bat_discharging_samples = 0;
int bat_charging_samples = 0;
int bat_charged_samples = 0;
bool bat_voltage_dropping = false;
float bat_delay_v = 0;
float bat_state_change_v = 0;
#elif BOARD_MODEL == BOARD_HELTEC32_V3
#define BAT_V_MIN 3.15
#define BAT_V_MAX 4.3
#define BAT_V_CHG 4.48
#define BAT_V_FLOAT 4.33
#define BAT_SAMPLES 7
const uint8_t pin_vbat = 1;
const uint8_t pin_ctrl = 37;
float bat_p_samples[BAT_SAMPLES];
float bat_v_samples[BAT_SAMPLES];
uint8_t bat_samples_count = 0;
int bat_discharging_samples = 0;
int bat_charging_samples = 0;
int bat_charged_samples = 0;
bool bat_voltage_dropping = false;
float bat_delay_v = 0;
float bat_state_change_v = 0;
>>>>>>> upstream/dev
#endif
uint32_t last_pmu_update = 0;
@ -74,10 +126,17 @@ uint8_t pmu_rc = 0;
void kiss_indicate_battery();
void measure_battery() {
#if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1
#if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_TDECK
battery_installed = true;
battery_indeterminate = true;
bat_v_samples[bat_samples_count%BAT_SAMPLES] = (float)(analogRead(pin_vbat)) / 4095*2*3.3*1.1;
#if BOARD_MODEL == BOARD_HELTEC32_V3
float battery_measurement = (float)(analogRead(pin_vbat)) * 0.0041;
#else
float battery_measurement = (float)(analogRead(pin_vbat)) / 4095.0*2.0*3.3*1.1;
#endif
bat_v_samples[bat_samples_count%BAT_SAMPLES] = battery_measurement;
bat_p_samples[bat_samples_count%BAT_SAMPLES] = ((battery_voltage-BAT_V_MIN) / (BAT_V_MAX-BAT_V_MIN))*100.0;
bat_samples_count++;
@ -100,41 +159,60 @@ void measure_battery() {
battery_voltage = battery_voltage/BAT_SAMPLES;
if (bat_delay_v == 0) bat_delay_v = battery_voltage;
if (bat_state_change_v == 0) bat_state_change_v = battery_voltage;
if (battery_percent > 100.0) battery_percent = 100.0;
if (battery_percent < 0.0) battery_percent = 0.0;
if (bat_samples_count%BAT_SAMPLES == 0) {
float bat_delay_diff = bat_state_change_v-battery_voltage;
if (bat_delay_diff < 0) { bat_delay_diff *= -1; }
if (battery_voltage < bat_delay_v && battery_voltage < BAT_V_FLOAT) {
bat_voltage_dropping = true;
if (bat_voltage_dropping == false) {
if (bat_delay_diff > 0.008) {
bat_voltage_dropping = true;
bat_state_change_v = battery_voltage;
// SerialBT.printf("STATE CHANGE to DISCHARGE at delta=%.3fv. State change v is now %.3fv.\n", bat_delay_diff, bat_state_change_v);
}
}
} else {
bat_voltage_dropping = false;
if (bat_voltage_dropping == true) {
if (bat_delay_diff > 0.01) {
bat_voltage_dropping = false;
bat_state_change_v = battery_voltage;
// SerialBT.printf("STATE CHANGE to CHARGE at delta=%.3fv. State change v is now %.3fv.\n", bat_delay_diff, bat_state_change_v);
}
}
}
bat_samples_count = 0;
bat_delay_v = battery_voltage;
}
if (bat_voltage_dropping && battery_voltage < BAT_V_FLOAT) {
battery_state = BATTERY_STATE_DISCHARGING;
} else {
#if BOARD_MODEL == BOARD_RNODE_NG_21
if (battery_percent < 100.0) {
battery_state = BATTERY_STATE_CHARGING;
#else
battery_state = BATTERY_STATE_DISCHARGING;
#endif
} else {
battery_state = BATTERY_STATE_CHARGED;
}
}
// 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%%.\n", battery_percent);
// SerialBT.printf(" Voltage is dropping. Percentage %.1f%%.", battery_percent);
// } else {
// SerialBT.print(" Voltage is not dropping.\n");
// SerialBT.printf(" Voltage is not dropping. Percentage %.1f%%.", battery_percent);
// }
// if (battery_state == BATTERY_STATE_DISCHARGING) { SerialBT.printf(" Battery discharging. delay_v %.3fv", bat_delay_v); }
// if (battery_state == BATTERY_STATE_CHARGING) { SerialBT.printf(" Battery charging. delay_v %.3fv", bat_delay_v); }
// if (battery_state == BATTERY_STATE_CHARGED) { SerialBT.print(" Battery is charged."); }
// SerialBT.print("\n");
// }
}
#elif BOARD_MODEL == BOARD_TBEAM
#elif BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_TBEAM_S_V1
if (PMU) {
float discharge_current = 0;
float charge_current = 0;
@ -172,7 +250,7 @@ void measure_battery() {
}
}
} else {
battery_state = BATTERY_STATE_DISCHARGING;
battery_state = BATTERY_STATE_UNKNOWN;
battery_percent = 0.0;
battery_voltage = 0.0;
}
@ -214,7 +292,7 @@ void measure_battery() {
battery_ready = false;
}
#elif BOARD_MODEL == BOARD_FREENODE
#elif BOARD_MODEL == BOARD_OPENCOM_XL
battery_installed = true;
battery_indeterminate = false;
@ -301,31 +379,29 @@ void update_pmu() {
}
bool init_pmu() {
#if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1
#if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TDECK
pinMode(pin_vbat, INPUT);
return true;
#elif BOARD_MODEL == BOARD_HELTEC32_V3
pinMode(pin_ctrl,OUTPUT);
digitalWrite(pin_ctrl, LOW);
return true;
#elif BOARD_MODEL == BOARD_TBEAM
Wire.begin(I2C_SDA, I2C_SCL);
if (!PMU) {
PMU = new XPowersAXP2101(PMU_WIRE_PORT);
if (!PMU->init()) {
Serial.println("Warning: Failed to find AXP2101 power management");
delete PMU;
PMU = NULL;
} else {
Serial.println("AXP2101 PMU init succeeded, using AXP2101 PMU");
}
}
if (!PMU) {
PMU = new XPowersAXP192(PMU_WIRE_PORT);
if (!PMU->init()) {
Serial.println("Warning: Failed to find AXP192 power management");
delete PMU;
PMU = NULL;
} else {
Serial.println("AXP192 PMU init succeeded, using AXP192 PMU");
}
}
@ -431,7 +507,7 @@ bool init_pmu() {
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
return true;
#elif BOARD_MODEL == BOARD_FREENODE
#elif BOARD_MODEL == BOARD_OPENCOM_XL
// board doesn't have PMU but we can measure batt voltage
// prep ADC for reading battery level
@ -445,6 +521,86 @@ bool init_pmu() {
// Get a single ADC sample and throw it away
float raw = analogRead(PIN_VBAT);
return true;
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
Wire1.begin(I2C_SDA, I2C_SCL);
if (!PMU) {
PMU = new XPowersAXP2101(PMU_WIRE_PORT);
if (!PMU->init()) {
delete PMU;
PMU = NULL;
}
}
if (!PMU) {
return false;
}
/**
* gnss module power channel
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during
* initialization
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
// lora radio power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
// m.2 interface
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
/**
* ALDO2 cannot be turned off.
* It is a necessary condition for sensor communication.
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
// sdcard power channle
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4);
// not use channel
PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited
PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited
PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
PMU->disablePowerOutput(XPOWERS_VBACKUP);
// Configure charging
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
// TODO: Reset
PMU->setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
// Set the time of pressing the button to turn off
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
PMU->setPowerKeyPressOnTime(XPOWERS_POWERON_128MS);
// disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
PMU->clearIrqStatus();
// It is necessary to disable the detection function of the TS pin on the board
// without the battery temperature detection function, otherwise it will cause abnormal charging
PMU->disableTSPinMeasure();
PMU->enableVbusVoltageMeasure();
PMU->enableBattVoltageMeasure();
return true;
#else
return false;

View File

@ -24,7 +24,6 @@ The latest release, installable through `rnodeconf`, is version `1.73`. This rel
- Fix TNC EEPROM settings not being saved - courtesy of @attermann
- Fix ESP32 linker errors - BSP version is now fixed at 2.0.17, using the older crosstool-ng linker from previous versions (2021r1)
You must have at least version `2.1.3` of `rnodeconf` installed to update the RNode Firmware to version `1.73`. Get it by updating the `rns` package to at least version `0.6.4`.
## Supported products and boards

101
ROM.h
View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -14,79 +14,40 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef ROM_H
#define ROM_H
#define ROM_H
#define CHECKSUMMED_SIZE 0x0B
#define CHECKSUMMED_SIZE 0x0B
// ROM address map ///////////////
#define ADDR_PRODUCT 0x00
#define ADDR_MODEL 0x01
#define ADDR_HW_REV 0x02
#define ADDR_SERIAL 0x03
#define ADDR_MADE 0x07
#define ADDR_CHKSUM 0x0B
#define ADDR_SIGNATURE 0x1B
#define ADDR_INFO_LOCK 0x9B
#define PRODUCT_RNODE 0x03
#define PRODUCT_HMBRW 0xF0
#define PRODUCT_TBEAM 0xE0
#define PRODUCT_T32_10 0xB2
#define PRODUCT_T32_20 0xB0
#define PRODUCT_T32_21 0xB1
#define PRODUCT_H32_V2 0xC0
#define PRODUCT_H32_V3 0xC1
#define PRODUCT_RAK4631 0x10
#define PRODUCT_FREENODE 0x20
#define MODEL_11 0x11
#define MODEL_12 0x12
#define MODEL_13 0x13 // RAK4631 LF with WisBlock SX1280 module (LIBSYS002)
#define MODEL_14 0x14 // RAK4631 HF with WisBlock SX1280 module (LIBSYS002)
#define PRODUCT_TECHO 0x15
#define MODEL_16 0x16 // T-Echo 433
#define MODEL_17 0x17 // T-Echo 915
#define MODEL_21 0x21 // European band, 868MHz
#define MODEL_A1 0xA1
#define MODEL_A5 0xA5 // T3S3 SX1280 PA
#define MODEL_A6 0xA6
#define MODEL_A4 0xA4
#define MODEL_A9 0xA9
#define MODEL_A3 0xA3
#define MODEL_A8 0xA8
#define MODEL_A2 0xA2
#define MODEL_A7 0xA7
#define MODEL_B3 0xB3
#define MODEL_B8 0xB8
#define MODEL_B4 0xB4
#define MODEL_B9 0xB9
#define MODEL_BA 0xBA
#define MODEL_BB 0xBB
#define MODEL_C4 0xC4
#define MODEL_C9 0xC9
#define MODEL_C5 0xC5
#define MODEL_CA 0xCA
#define MODEL_E4 0xE4
#define MODEL_E9 0xE9
#define MODEL_E3 0xE3
#define MODEL_E8 0xE8
#define MODEL_FE 0xFE
#define MODEL_FF 0xFF
#define ADDR_CONF_SF 0x9C
#define ADDR_CONF_CR 0x9D
#define ADDR_CONF_TXP 0x9E
#define ADDR_CONF_BW 0x9F
#define ADDR_CONF_FREQ 0xA3
#define ADDR_CONF_OK 0xA7
#define ADDR_PRODUCT 0x00
#define ADDR_MODEL 0x01
#define ADDR_HW_REV 0x02
#define ADDR_SERIAL 0x03
#define ADDR_MADE 0x07
#define ADDR_CHKSUM 0x0B
#define ADDR_SIGNATURE 0x1B
#define ADDR_INFO_LOCK 0x9B
#define ADDR_CONF_BT 0xB0
#define ADDR_CONF_DSET 0xB1
#define ADDR_CONF_DINT 0xB2
#define ADDR_CONF_DADR 0xB3
#define ADDR_CONF_DBLK 0xB4
#define ADDR_CONF_PSET 0xB5
#define ADDR_CONF_PINT 0xB6
#define ADDR_CONF_BSET 0xB7
#define ADDR_CONF_SF 0x9C
#define ADDR_CONF_CR 0x9D
#define ADDR_CONF_TXP 0x9E
#define ADDR_CONF_BW 0x9F
#define ADDR_CONF_FREQ 0xA3
#define ADDR_CONF_OK 0xA7
#define INFO_LOCK_BYTE 0x73
#define CONF_OK_BYTE 0x73
#define BT_ENABLE_BYTE 0x73
#define ADDR_CONF_BT 0xB0
#define ADDR_CONF_DSET 0xB1
#define ADDR_CONF_DINT 0xB2
#define ADDR_CONF_DADR 0xB3
#define INFO_LOCK_BYTE 0x73
#define CONF_OK_BYTE 0x73
#define BT_ENABLE_BYTE 0x73
#define EEPROM_RESERVED 200
#define EEPROM_RESERVED 200
//////////////////////////////////
#endif

119
Radio.cpp
View File

@ -119,7 +119,7 @@ sx126x::sx126x(uint8_t index, SPIClass* spi, bool tcxo, bool dio2_as_rf_switch,
RadioInterface(index),
_spiSettings(8E6, MSBFIRST, SPI_MODE0), _spiModem(spi), _ss(ss),
_sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0),
_busy(busy), _rxen(rxen), _frequency(0), _txp(0), _sf(0x07), _bw(0x04),
_busy(busy), _rxen(rxen), _frequency(0), _sf(0x07), _bw(0x04),
_cr(0x01), _ldro(0x00), _packetIndex(0), _implicitHeaderMode(0),
_payloadLength(255), _crcMode(1), _fifo_tx_addr_ptr(0),
_fifo_rx_addr_ptr(0), _preinit_done(false), _tcxo(tcxo),
@ -129,7 +129,7 @@ sx126x::sx126x(uint8_t index, SPIClass* spi, bool tcxo, bool dio2_as_rf_switch,
setTimeout(0);
// TODO, figure out why this has to be done. Using the index to reference the
// interface_obj list causes a crash otherwise
_index = getIndex();
//_index = getIndex();
}
bool sx126x::preInit() {
@ -488,34 +488,34 @@ int sx126x::beginPacket(int implicitHeader)
int sx126x::endPacket()
{
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
// put in single TX mode
uint8_t timeout[3] = {0};
executeOpcode(OP_TX_6X, timeout, 3);
// put in single TX mode
uint8_t timeout[3] = {0};
executeOpcode(OP_TX_6X, timeout, 3);
uint8_t buf[2];
uint8_t buf[2];
buf[0] = 0x00;
buf[1] = 0x00;
buf[0] = 0x00;
buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
// wait for TX done
while ((buf[1] & IRQ_TX_DONE_MASK_6X) == 0) {
// wait for TX done
while ((buf[1] & IRQ_TX_DONE_MASK_6X) == 0) {
buf[0] = 0x00;
buf[1] = 0x00;
executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
yield();
}
}
// clear IRQ's
// clear IRQ's
uint8_t mask[2];
mask[0] = 0x00;
mask[1] = IRQ_TX_DONE_MASK_6X;
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, mask, 2);
return 1;
uint8_t mask[2];
mask[0] = 0x00;
mask[1] = IRQ_TX_DONE_MASK_6X;
executeOpcode(OP_CLEAR_IRQ_STATUS_6X, mask, 2);
return 1;
}
uint8_t sx126x::modemStatus() {
@ -561,7 +561,7 @@ uint8_t sx126x::packetRssiRaw() {
return buf[2];
}
int ISR_VECT sx126x::packetRssi() {
int ISR_VECT sx126x::packetRssi(uint8_t pkt_snr_raw) {
// may need more calculations here
uint8_t buf[3] = {0};
executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
@ -740,7 +740,7 @@ void sx126x::sleep()
void sx126x::enableTCXO() {
if (_tcxo) {
#if BOARD_MODEL == BOARD_FREENODE || BOARD_MODEL == BOARD_HELTEC32_V3
#if BOARD_MODEL == BOARD_OPENCOM_XL || BOARD_MODEL == BOARD_HELTEC32_V3
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};
@ -748,6 +748,10 @@ void sx126x::enableTCXO() {
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_T3S3
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_TDECK
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#else
uint8_t buf[4] = {0};
#endif
@ -789,7 +793,7 @@ void sx126x::setTxPower(int level, int outputPin) {
executeOpcode(OP_TX_PARAMS_6X, tx_buf, 2);
}
uint8_t sx126x::getTxPower() {
int8_t sx126x::getTxPower() {
return _txp;
}
@ -995,7 +999,9 @@ void sx126x::updateBitrate() {
_lora_symbol_time_ms = (1.0/_lora_symbol_rate)*1000.0;
_bitrate = (uint32_t)(_sf * ( (4.0/(float)(_cr+4)) / ((float)(pow(2, _sf))/((float)getSignalBandwidth()/1000.0)) ) * 1000.0);
_lora_us_per_byte = 1000000.0/((float)_bitrate/8.0);
//_csma_slot_ms = _lora_symbol_time_ms*10;
_csma_slot_ms = _lora_symbol_time_ms*12;
if (_csma_slot_ms > CSMA_SLOT_MAX_MS) { _csma_slot_ms = CSMA_SLOT_MAX_MS; }
if (_csma_slot_ms < CSMA_SLOT_MIN_MS) { _csma_slot_ms = CSMA_SLOT_MIN_MS; }
float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
@ -1092,7 +1098,7 @@ sx127x::sx127x(uint8_t index, SPIClass* spi, int ss, int sclk, int mosi, int mis
setTimeout(0);
// TODO, figure out why this has to be done. Using the index to reference the
// interface_obj list causes a crash otherwise
_index = getIndex();
//_index = getIndex();
}
void sx127x::setSPIFrequency(uint32_t frequency) { _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); }
@ -1246,23 +1252,27 @@ uint8_t sx127x::packetRssiRaw() {
return pkt_rssi_value;
}
int ISR_VECT sx127x::packetRssi() {
int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE_7X) - RSSI_OFFSET;
int pkt_snr = packetSnr();
if (_frequency < 820E6) pkt_rssi -= 7;
if (pkt_snr < 0) {
pkt_rssi += pkt_snr;
} else {
// Slope correction is (16/15)*pkt_rssi,
// this estimation looses one floating point
// operation, and should be precise enough.
pkt_rssi = (int)(1.066 * pkt_rssi);
}
return pkt_rssi;
int ISR_VECT sx127x::packetRssi(uint8_t pkt_snr_raw) {
int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE_7X) - RSSI_OFFSET;
int pkt_snr;
if (pkt_snr_raw == 0xFF) {
pkt_snr = packetSnr();
} else {
pkt_snr = ((int8_t)pkt_snr_raw)*0.25;
}
if (_frequency < 820E6) pkt_rssi -= 7;
if (pkt_snr < 0) {
pkt_rssi += pkt_snr;
} else {
// Slope correction is (16/15)*pkt_rssi,
// this estimation looses one floating point
// operation, and should be precise enough.
pkt_rssi = (int)(1.066 * pkt_rssi);
}
return pkt_rssi;
}
uint8_t ISR_VECT sx127x::packetSnrRaw() {
return readRegister(REG_PKT_SNR_VALUE_7X);
}
@ -1374,9 +1384,10 @@ void sx127x::setTxPower(int level, int outputPin) {
writeRegister(REG_PA_DAC_7X, 0x84);
writeRegister(REG_PA_CONFIG_7X, PA_BOOST_7X | (level - 2));
}
_txp = level;
}
uint8_t sx127x::getTxPower() { byte txp = readRegister(REG_PA_CONFIG_7X); return txp; }
int8_t sx127x::getTxPower() { return _txp; }
void sx127x::setFrequency(uint32_t frequency) {
_frequency = frequency;
@ -1531,7 +1542,9 @@ void sx127x::updateBitrate() {
_lora_symbol_time_ms = (1.0/_lora_symbol_rate)*1000.0;
_bitrate = (uint32_t)(_sf * ( (4.0/(float)(_cr+4)) / ((float)(pow(2, _sf))/((float)getSignalBandwidth()/1000.0)) ) * 1000.0);
_lora_us_per_byte = 1000000.0/((float)_bitrate/8.0);
//_csma_slot_ms = _lora_symbol_time_ms*10;
_csma_slot_ms = _lora_symbol_time_ms*12;
if (_csma_slot_ms > CSMA_SLOT_MAX_MS) { _csma_slot_ms = CSMA_SLOT_MAX_MS; }
if (_csma_slot_ms < CSMA_SLOT_MIN_MS) { _csma_slot_ms = CSMA_SLOT_MIN_MS; }
float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
@ -1605,7 +1618,7 @@ sx128x::sx128x(uint8_t index, SPIClass* spi, bool tcxo, int ss, int sclk, int mo
_spiSettings(8E6, MSBFIRST, SPI_MODE0),
_spiModem(spi),
_ss(ss), _sclk(sclk), _mosi(mosi), _miso(miso), _reset(reset), _dio0(dio0),
_busy(busy), _rxen(rxen), _txen(txen), _frequency(0), _txp(0), _sf(0x05),
_busy(busy), _rxen(rxen), _txen(txen), _frequency(0), _sf(0x05),
_bw(0x34), _cr(0x01), _packetIndex(0), _implicitHeaderMode(0),
_payloadLength(255), _crcMode(0), _fifo_tx_addr_ptr(0), _fifo_rx_addr_ptr(0),
_rxPacketLength(0), _preinit_done(false),
@ -1615,7 +1628,7 @@ sx128x::sx128x(uint8_t index, SPIClass* spi, bool tcxo, int ss, int sclk, int mo
setTimeout(0);
// TODO, figure out why this has to be done. Using the index to reference the
// interface_obj list causes a crash otherwise
_index = getIndex();
//_index = getIndex();
}
bool sx128x::preInit() {
@ -2028,7 +2041,7 @@ uint8_t sx128x::packetRssiRaw() {
return buf[0];
}
int ISR_VECT sx128x::packetRssi() {
int ISR_VECT sx128x::packetRssi(uint8_t pkt_snr_raw) {
// may need more calculations here
uint8_t buf[5] = {0};
executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
@ -2333,7 +2346,7 @@ void sx128x::setTxPower(int level, int outputPin) {
executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2);
#elif BOARD_VARIANT == MODEL_A5
#elif BOARD_VARIANT == MODEL_AB
// T3S3 SX1280 PA
if (level > 20) {
level = 20;
@ -2414,7 +2427,7 @@ void sx128x::setTxPower(int level, int outputPin) {
break;
}
tx_buf[0] = reg_value + 18;
tx_buf[0] = reg_value;
tx_buf[1] = 0xE0; // ramping time - 20 microseconds
#else
// For SX1280 boards with no specific PA requirements
@ -2432,7 +2445,7 @@ void sx128x::setTxPower(int level, int outputPin) {
executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2);
}
uint8_t sx128x::getTxPower() {
int8_t sx128x::getTxPower() {
return _txp;
}
@ -2625,14 +2638,16 @@ void sx128x::updateBitrate() {
_lora_symbol_time_ms = (1.0/_lora_symbol_rate)*1000.0;
_bitrate = (uint32_t)(_sf * ( (4.0/(float)(_cr+4)) / ((float)(pow(2, _sf))/((float)getSignalBandwidth()/1000.0)) ) * 1000.0);
_lora_us_per_byte = 1000000.0/((float)_bitrate/8.0);
_csma_slot_ms = 10;
_csma_slot_ms = _lora_symbol_time_ms*12;
if (_csma_slot_ms > CSMA_SLOT_MAX_MS) { _csma_slot_ms = CSMA_SLOT_MAX_MS; }
if (_csma_slot_ms < CSMA_SLOT_MIN_MS) { _csma_slot_ms = CSMA_SLOT_MIN_MS; }
float target_preamble_symbols;
//if (_bitrate <= LORA_FAST_BITRATE_THRESHOLD) {
if (_bitrate <= LORA_FAST_BITRATE_THRESHOLD) {
target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
//} else {
/*target_preamble_symbols = (LORA_PREAMBLE_FAST_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
}*/
} else {
target_preamble_symbols = (LORA_PREAMBLE_FAST_TARGET_MS/_lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
}
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
} else {

View File

@ -1,7 +1,7 @@
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license.
// Modifications and additions copyright 2023 by Mark Qvist & Jacob Eva
// Modifications and additions copyright 2024 by Mark Qvist & Jacob Eva
// Obviously still under the MIT license.
#ifndef RADIO_H
@ -34,15 +34,17 @@
#define LORA_PREAMBLE_SYMBOLS_HW 4
#define LORA_PREAMBLE_SYMBOLS_MIN 18
#define LORA_PREAMBLE_TARGET_MS 15
#define LORA_PREAMBLE_FAST_TARGET_MS 1
#define LORA_PREAMBLE_FAST_TARGET_MS 4
#define LORA_FAST_BITRATE_THRESHOLD 40000
#define CSMA_SLOT_MAX_MS 100
#define CSMA_SLOT_MIN_MS 24
#define RSSI_OFFSET 157
#define PHY_HEADER_LORA_SYMBOLS 8
#define _e 2.71828183
#define _S 10.0
#define _S 12.5
// Status flags
const uint8_t SIG_DETECT = 0x01;
@ -75,17 +77,17 @@ public:
_stat_signal_detected(false), _stat_signal_synced(false),_stat_rx_ongoing(false), _last_dcd(0),
_dcd_count(0), _dcd(false), _dcd_led(false),
_dcd_waiting(false), _dcd_wait_until(0), _dcd_sample(0),
_post_tx_yield_timeout(0), _csma_slot_ms(50), _csma_p_min(0.1),
_csma_p_max(0.8), _preambleLength(6), _lora_symbol_time_ms(0.0),
_post_tx_yield_timeout(0), _csma_slot_ms(50), _csma_p(85), _csma_p_min(0.15),
_csma_p_max(0.333), _csma_b_speed(0.15), _preambleLength(6), _lora_symbol_time_ms(0.0),
_lora_symbol_rate(0.0), _lora_us_per_byte(0.0), _bitrate(0),
_packet{0}, _onReceive(NULL) {};
_packet{0}, _onReceive(NULL), _txp(0) {};
virtual int begin() = 0;
virtual void end() = 0;
virtual int beginPacket(int implicitHeader = false) = 0;
virtual int endPacket() = 0;
virtual int packetRssi() = 0;
virtual int packetRssi(uint8_t pkt_snr_raw = 0xFF) = 0;
virtual int currentRssi() = 0;
virtual uint8_t packetRssiRaw() = 0;
virtual uint8_t currentRssiRaw() = 0;
@ -110,7 +112,7 @@ public:
virtual void sleep() = 0;
virtual bool preInit() = 0;
virtual uint8_t getTxPower() = 0;
virtual int8_t getTxPower() = 0;
virtual void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN) = 0;
virtual uint32_t getFrequency() = 0;
virtual void setFrequency(uint32_t frequency) = 0;
@ -288,8 +290,8 @@ public:
float getLongtermChannelUtil() { return _longterm_channel_util; };
float CSMASlope(float u) { return (pow(_e,_S*u-_S/2.0))/(pow(_e,_S*u-_S/2.0)+1.0); };
void updateCSMAp() {
_csma_p = (uint8_t)((1.0-(_csma_p_min+(_csma_p_max-_csma_p_min)*CSMASlope(_airtime)))*255.0);
};
_csma_p = (uint8_t)((1.0-(_csma_p_min+(_csma_p_max-_csma_p_min)*CSMASlope(_airtime+_csma_b_speed)))*255.0);
}
uint8_t getCSMAp() { return _csma_p; };
void setCSMASlotMS(int slot_size) { _csma_slot_ms = slot_size; };
int getCSMASlotMS() { return _csma_slot_ms; };
@ -301,6 +303,7 @@ protected:
virtual void implicitHeaderMode() = 0;
uint8_t _index;
int8_t _txp;
bool _radio_locked;
bool _radio_online;
float _st_airtime_limit;
@ -330,6 +333,7 @@ protected:
int _csma_slot_ms;
float _csma_p_min;
float _csma_p_max;
float _csma_b_speed;
long _preambleLength;
float _lora_symbol_time_ms;
float _lora_symbol_rate;
@ -350,7 +354,7 @@ public:
int beginPacket(int implicitHeader = false);
int endPacket();
int packetRssi();
int packetRssi(uint8_t pkt_snr_raw = 0xFF);
int currentRssi();
uint8_t packetRssiRaw();
uint8_t currentRssiRaw();
@ -375,7 +379,7 @@ public:
void sleep();
bool preInit();
uint8_t getTxPower();
int8_t getTxPower();
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
uint32_t getFrequency();
void setFrequency(uint32_t frequency);
@ -443,7 +447,6 @@ private:
int _rxen;
int _busy;
uint32_t _frequency;
int _txp;
uint8_t _sf;
uint8_t _bw;
uint8_t _cr;
@ -455,7 +458,6 @@ private:
int _fifo_tx_addr_ptr;
int _fifo_rx_addr_ptr;
bool _preinit_done;
uint8_t _index;
bool _tcxo;
bool _dio2_as_rf_switch;
};
@ -470,7 +472,7 @@ public:
int beginPacket(int implicitHeader = false);
int endPacket();
int packetRssi();
int packetRssi(uint8_t pkt_snr_raw = 0xFF);
int currentRssi();
uint8_t packetRssiRaw();
uint8_t currentRssiRaw();
@ -495,7 +497,7 @@ public:
void sleep();
bool preInit();
uint8_t getTxPower();
int8_t getTxPower();
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
uint32_t getFrequency();
void setFrequency(uint32_t frequency);
@ -549,7 +551,6 @@ private:
int _packetIndex;
int _implicitHeaderMode;
bool _preinit_done;
uint8_t _index;
uint8_t _sf;
uint8_t _cr;
};
@ -564,7 +565,7 @@ public:
int beginPacket(int implicitHeader = false);
int endPacket();
int packetRssi();
int packetRssi(uint8_t pkt_snr_raw = 0xFF);
int currentRssi();
uint8_t packetRssiRaw();
uint8_t currentRssiRaw();
@ -589,7 +590,7 @@ public:
void sleep();
bool preInit();
uint8_t getTxPower();
int8_t getTxPower();
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
uint32_t getFrequency();
void setFrequency(uint32_t frequency);
@ -657,7 +658,6 @@ private:
int _busy;
int _modem;
uint32_t _frequency;
int _txp;
uint8_t _sf;
uint8_t _bw;
uint8_t _cr;
@ -669,7 +669,6 @@ private:
int _fifo_rx_addr_ptr;
bool _preinit_done;
int _rxPacketLength;
uint8_t _index;
bool _tcxo;
};
#endif

Binary file not shown.

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -37,7 +37,7 @@
#include "ROM.h"
#include "Framing.h"
#include "MD5.h"
#include "src/misc/MD5.h"
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
uint8_t eeprom_read(uint32_t mapped_addr);
@ -45,6 +45,9 @@ uint8_t eeprom_read(uint32_t mapped_addr);
#if HAS_DISPLAY == true
#include "Display.h"
#else
void display_unblank() {}
bool display_blanked = false;
#endif
#if HAS_BLUETOOTH == true || HAS_BLE == true
@ -71,11 +74,11 @@ uint8_t eeprom_read(uint32_t mapped_addr);
#if BOARD_MODEL == BOARD_HELTEC32_V3
//https://github.com/espressif/esp-idf/issues/8855
#include "hal/wdt_hal.h"
#elif BOARD_MODEL == BOARD_T3S3
#include "hal/wdt_hal.h"
#else BOARD_MODEL != BOARD_T3S3
#include "soc/rtc_wdt.h"
#endif
#elif BOARD_MODEL == BOARD_T3S3
#include "hal/wdt_hal.h"
#else
#include "hal/wdt_hal.h"
#endif
#define ISR_VECT IRAM_ATTR
#else
#define ISR_VECT
@ -98,7 +101,20 @@ uint8_t boot_vector = 0x00;
uint8_t npr = 0;
uint8_t npg = 0;
uint8_t npb = 0;
float npi = NP_M;
bool pixels_started = false;
void led_set_intensity(uint8_t intensity) {
npi = (float)intensity/255.0;
}
void led_init() {
if (EEPROM.read(eeprom_addr(ADDR_CONF_PSET)) == CONF_OK_BYTE) {
uint8_t int_val = EEPROM.read(eeprom_addr(ADDR_CONF_PINT));
led_set_intensity(int_val);
}
}
void npset(uint8_t r, uint8_t g, uint8_t b) {
if (pixels_started != true) {
pixels.begin();
@ -107,7 +123,7 @@ uint8_t boot_vector = 0x00;
if (r != npr || g != npg || b != npb) {
npr = r; npg = g; npb = b;
pixels.setPixelColor(0, pixels.Color(npr*NP_M, npg*NP_M, npb*NP_M));
pixels.setPixelColor(0, pixels.Color(npr*npi, npg*npi, npb*npi));
pixels.show();
}
}
@ -148,11 +164,26 @@ uint8_t boot_vector = 0x00;
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
void led_tx_on() { digitalWrite(pin_led_tx, HIGH); }
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
#elif BOARD_MODEL == BOARD_E22_ESP32
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
void led_tx_on() { digitalWrite(pin_led_tx, HIGH); }
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
#elif BOARD_MODEL == BOARD_TBEAM
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
void led_tx_on() { digitalWrite(pin_led_tx, LOW); }
void led_tx_off() { digitalWrite(pin_led_tx, HIGH); }
#elif BOARD_MODEL == BOARD_TDECK
void led_rx_on() { }
void led_rx_off() { }
void led_tx_on() { }
void led_tx_off() { }
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
void led_rx_on() { }
void led_rx_off() { }
void led_tx_on() { }
void led_tx_off() { }
#elif BOARD_MODEL == BOARD_LORA32_V1_0
#if defined(EXTERNAL_LEDS)
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
@ -211,11 +242,11 @@ uint8_t boot_vector = 0x00;
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
#endif
#elif MCU_VARIANT == MCU_NRF52
#if BOARD_MODEL == BOARD_FREENODE
void led_rx_on() { analogWrite(pin_led_rx, 1); }
void led_rx_off() { analogWrite(pin_led_rx, 0); }
void led_tx_on() { analogWrite(pin_led_tx, 1); }
void led_tx_off() { analogWrite(pin_led_tx, 0); }
#if BOARD_MODEL == BOARD_OPENCOM_XL
void led_rx_on() { digitalWrite(pin_led_rx, 1); }
void led_rx_off() { digitalWrite(pin_led_rx, 0); }
void led_tx_on() { digitalWrite(pin_led_tx, 1); }
void led_tx_off() { digitalWrite(pin_led_tx, 0); }
#endif
#if BOARD_MODEL == BOARD_RAK4631
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
@ -383,8 +414,8 @@ unsigned long led_standby_ticks = 0;
#if MCU_VARIANT == MCU_ESP32
#if HAS_NP == true
int led_standby_lng = 100;
int led_standby_cut = 200;
int led_standby_lng = 200;
int led_standby_cut = 100;
int led_standby_min = 0;
int led_standby_max = 375+led_standby_lng;
int led_notready_min = 0;
@ -448,7 +479,7 @@ int8_t led_standby_direction = 0;
} else {
led_standby_intensity = led_standby_ti;
}
npset(0x00, 0x00, led_standby_intensity);
npset(led_standby_intensity/3, led_standby_intensity/3, led_standby_intensity/3);
}
}
@ -595,18 +626,17 @@ void serial_write(uint8_t byte) {
Serial.write(byte);
} else {
SerialBT.write(byte);
#if MCU_VARIANT == MCU_NRF52 && HAS_BLE
// This ensures that the TX buffer is flushed after a frame is queued in serial.
// serial_in_frame is used to ensure that the flush only happens at the end of the frame
if (serial_in_frame && byte == FEND) {
SerialBT.flushTXD();
serial_in_frame = false;
}
else if (!serial_in_frame && byte == FEND) {
serial_in_frame = true;
}
#endif
#if MCU_VARIANT == MCU_NRF52 && HAS_BLE
// This ensures that the TX buffer is flushed after a frame is queued in serial.
// serial_in_frame is used to ensure that the flush only happens at the end of the frame
if (serial_in_frame && byte == FEND) {
SerialBT.flushTXD();
serial_in_frame = false;
}
else if (!serial_in_frame && byte == FEND) {
serial_in_frame = true;
}
#endif
}
#else
Serial.write(byte);
@ -1029,6 +1059,8 @@ void setTXPower(RadioInterface* radio, int txp) {
if (model == MODEL_A7) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_A8) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_A9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_AA) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_AB) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_B3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_B4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
@ -1038,6 +1070,15 @@ void setTXPower(RadioInterface* radio, int txp) {
if (model == MODEL_C4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_C9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_C5) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_CA) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_D4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_D9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_DB) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_DC) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E4) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E9) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
if (model == MODEL_E3) radio->setTxPower(txp, PA_OUTPUT_PA_BOOST_PIN);
@ -1223,11 +1264,11 @@ void promisc_disable() {
#endif
bool eeprom_info_locked() {
#if HAS_EEPROM
uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK));
#elif MCU_VARIANT == MCU_NRF52
uint8_t lock_byte = eeprom_read(eeprom_addr(ADDR_INFO_LOCK));
#endif
#if HAS_EEPROM
uint8_t lock_byte = EEPROM.read(eeprom_addr(ADDR_INFO_LOCK));
#elif MCU_VARIANT == MCU_NRF52
uint8_t lock_byte = eeprom_read(eeprom_addr(ADDR_INFO_LOCK));
#endif
if (lock_byte == INFO_LOCK_BYTE) {
return true;
} else {
@ -1304,15 +1345,15 @@ void eeprom_update(int mapped_addr, uint8_t byte) {
written_bytes++;
if (((mapped_addr - eeprom_addr(0)) == ADDR_INFO_LOCK) || (mapped_addr - eeprom_addr(0)) == ADDR_CONF_OK) {
// have to do a flush because we're only writing 1 byte and it syncs after 4
eeprom_flush();
// have to do a flush because we're only writing 1 byte and it syncs after 4
eeprom_flush();
}
if (written_bytes >= 4) {
eeprom_file.close();
eeprom_file.open(EEPROM_FILE, FILE_O_WRITE);
written_bytes = 0;
}
if (written_bytes >= 4) {
eeprom_file.close();
eeprom_file.open(EEPROM_FILE, FILE_O_WRITE);
written_bytes = 0;
}
#endif
}
@ -1344,16 +1385,16 @@ bool eeprom_lock_set() {
}
bool eeprom_product_valid() {
#if HAS_EEPROM
uint8_t rval = EEPROM.read(eeprom_addr(ADDR_PRODUCT));
#elif MCU_VARIANT == MCU_NRF52
uint8_t rval = eeprom_read(eeprom_addr(ADDR_PRODUCT));
#endif
#if HAS_EEPROM
uint8_t rval = EEPROM.read(eeprom_addr(ADDR_PRODUCT));
#elif MCU_VARIANT == MCU_NRF52
uint8_t rval = eeprom_read(eeprom_addr(ADDR_PRODUCT));
#endif
#if 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) {
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) {
#elif PLATFORM == PLATFORM_NRF52
if (rval == PRODUCT_TECHO || rval == PRODUCT_RAK4631 || rval == PRODUCT_HMBRW || rval == PRODUCT_FREENODE) {
if (rval == PRODUCT_TECHO || rval == PRODUCT_RAK4631 || rval == PRODUCT_HMBRW || rval == PRODUCT_OPENCOM_XL) {
#else
if (false) {
#endif
@ -1375,14 +1416,18 @@ bool eeprom_model_valid() {
if (model == MODEL_A3 || model == MODEL_A8) {
#elif BOARD_MODEL == BOARD_RNODE_NG_21
if (model == MODEL_A2 || model == MODEL_A7) {
#elif BOARD_MODEL == BOARD_RNODE_NG_22
if (model == MODEL_A1 || model == MODEL_A6 || model == MODEL_A5 || model == MODEL_AA) {
#elif BOARD_MODEL == BOARD_T3S3
if (model == MODEL_A1 || model == MODEL_A5 || model == MODEL_A6) {
#elif BOARD_MODEL == BOARD_HMBRW
if (model == MODEL_FF || model == MODEL_FE) {
#elif BOARD_MODEL == BOARD_TBEAM
if (model == MODEL_E4 || model == MODEL_E9 || model == MODEL_E3 || model == MODEL_E8) {
#elif BOARD_MODEL == BOARD_TECHO
if (model == MODEL_16 || model == MODEL_17) {
#elif BOARD_MODEL == BOARD_TDECK
if (model == MODEL_D4 || model == MODEL_D9) {
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
if (model == MODEL_DB || model == MODEL_DC) {
#elif BOARD_MODEL == BOARD_LORA32_V1_0
if (model == MODEL_BA || model == MODEL_BB) {
#elif BOARD_MODEL == BOARD_LORA32_V2_0
@ -1393,10 +1438,12 @@ bool eeprom_model_valid() {
if (model == MODEL_C4 || model == MODEL_C9) {
#elif BOARD_MODEL == BOARD_HELTEC32_V3
if (model == MODEL_C5 || model == MODEL_CA) {
#elif BOARD_MODEL == BOARD_FREENODE
#elif BOARD_MODEL == BOARD_OPENCOM_XL
if (model == MODEL_21) {
#elif BOARD_MODEL == BOARD_HUZZAH32
if (model == MODEL_FF) {
#elif BOARD_MODEL == BOARD_HMBRW
if (model == MODEL_FF || model == MODEL_FE) {
#elif BOARD_MODEL == BOARD_GENERIC_ESP32
if (model == MODEL_FF || model == MODEL_FE) {
#else
@ -1454,16 +1501,16 @@ bool eeprom_checksum_valid() {
void bt_conf_save(bool is_enabled) {
if (is_enabled) {
eeprom_update(eeprom_addr(ADDR_CONF_BT), BT_ENABLE_BYTE);
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
// have to do a flush because we're only writing 1 byte and it syncs after 8
eeprom_flush();
#endif
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
// have to do a flush because we're only writing 1 byte and it syncs after 8
eeprom_flush();
#endif
} else {
eeprom_update(eeprom_addr(ADDR_CONF_BT), 0x00);
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
// have to do a flush because we're only writing 1 byte and it syncs after 8
eeprom_flush();
#endif
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
// have to do a flush because we're only writing 1 byte and it syncs after 8
eeprom_flush();
#endif
}
}
@ -1475,6 +1522,25 @@ void da_conf_save(uint8_t dadr) {
eeprom_update(eeprom_addr(ADDR_CONF_DADR), dadr);
}
void db_conf_save(uint8_t val) {
#if HAS_DISPLAY
if (val == 0x00) {
display_blanking_enabled = false;
} else {
display_blanking_enabled = true;
//display_blanking_timeout = val*1000;
}
eeprom_update(eeprom_addr(ADDR_CONF_BSET), CONF_OK_BYTE);
eeprom_update(eeprom_addr(ADDR_CONF_DBLK), val);
#endif
}
void np_int_conf_save(uint8_t p_int) {
eeprom_update(eeprom_addr(ADDR_CONF_PSET), CONF_OK_BYTE);
eeprom_update(eeprom_addr(ADDR_CONF_PINT), p_int);
}
bool eeprom_have_conf() {
#if HAS_EEPROM
if (EEPROM.read(eeprom_addr(ADDR_CONF_OK)) == CONF_OK_BYTE) {

View File

@ -3,4 +3,3 @@ board_manager:
- https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
- https://liberatedsystems.co.uk/rnode-firmware-ce/esp-custom-package.json
- https://raw.githubusercontent.com/RAKwireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless_index.json
- http://unsigned.io/arduino/package_unsignedio_UnsignedBoards_index.json

47
esp32_btbufs.py Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
import sys
try:
target_path = sys.argv[1]
rxbuf_size = 0; rxbuf_minsize = 6144
txbuf_size = 0; txbuf_minsize = 384
line_index = 0
rx_line_index = 0
tx_line_index = 0
with open(target_path) as sf:
for line in sf:
line_index += 1
if line.startswith("#define RX_QUEUE_SIZE"):
ents = line.split(" ")
try:
rxbuf_size = int(ents[2])
rx_line_index = line_index
except Exception as e:
print(f"Could not parse Bluetooth RX_QUEUE_SIZE: {e}")
if line.startswith("#define TX_QUEUE_SIZE"):
ents = 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}")
if rxbuf_size != 0 and txbuf_size != 0:
break
if rxbuf_size < rxbuf_minsize:
print(f"Error: The configured ESP32 Bluetooth RX buffer size is too small, please set it to at least {rxbuf_minsize} and try compiling again.")
print(f"The buffer configuration can be modified in line {rx_line_index} of: {target_path}")
exit(1)
if txbuf_size < txbuf_minsize:
print(f"Error: The configured ESP32 Bluetooth TX buffer size is too small, please set it to at least {txbuf_minsize} and try compiling again.")
print(f"The buffer configuration can be modified in line {tx_line_index} of: {target_path}")
exit(1)
exit(0)
except Exception as e:
print(f"Could not determine ESP32 Bluetooth buffer configuration: {e}")
print("Please fix this error and try again")

View File

@ -1,4 +1,4 @@
// Copyright (C) 2023, Mark Qvist
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -19,7 +19,7 @@
#if MCU_VARIANT == MCU_NRF52
#define INTERFACE_SPI
#if BOARD_MODEL == BOARD_FREENODE
#if BOARD_MODEL == BOARD_OPENCOM_XL
// Required because on RAK4631, non-default SPI pins must be initialised when class is declared.
SPIClass interface_spi[1] = {
// SX1262
@ -74,6 +74,16 @@ volatile bool serial_buffering = false;
#include "Console.h"
#endif
#define MODEM_QUEUE_SIZE 4*INTERFACE_COUNT
typedef struct {
size_t len;
int rssi;
int snr_raw;
uint8_t interface;
uint8_t data[];
} modem_packet_t;
static xQueueHandle modem_packet_queue = NULL;
char sbuf[128];
uint8_t *packet_queue[INTERFACE_COUNT];
@ -83,6 +93,18 @@ void setup() {
boot_seq();
EEPROM.begin(EEPROM_SIZE);
Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE);
#if BOARD_MODEL == BOARD_TDECK
pinMode(pin_poweron, OUTPUT);
digitalWrite(pin_poweron, HIGH);
pinMode(SD_CS, OUTPUT);
pinMode(DISPLAY_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
digitalWrite(DISPLAY_CS, HIGH);
pinMode(DISPLAY_BL_PIN, OUTPUT);
#endif
#endif
#if MCU_VARIANT == MCU_NRF52
@ -109,9 +131,13 @@ void setup() {
Serial.begin(serial_baudrate);
#if BOARD_MODEL != BOARD_FREENODE && BOARD_MODEL != BOARD_RNODE_NG_22
#if HAS_NP
led_init();
#endif
#if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_RNODE_NG_22 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_OPENCOM_XL
// Some boards need to wait until the hardware UART is set up before booting
// the full firmware. In the case of the RAK4631, the line below will wait
// the full firmware. In the case of the RAK4631/TECHO, the line below will wait
// until a serial connection is actually established with a master. Thus, it
// is disabled on this platform.
while (!Serial);
@ -145,6 +171,10 @@ void setup() {
memset(packet_starts_buf, 0, sizeof(packet_starts_buf));
memset(packet_lengths_buf, 0, sizeof(packet_starts_buf));
memset(seq, 0xFF, sizeof(seq));
modem_packet_queue = xQueueCreate(MODEM_QUEUE_SIZE, sizeof(modem_packet_t*));
for (int i = 0; i < INTERFACE_COUNT; i++) {
fifo16_init(&packet_starts[i], packet_starts_buf, CONFIG_QUEUE_MAX_LENGTH+1);
fifo16_init(&packet_lengths[i], packet_lengths_buf, CONFIG_QUEUE_MAX_LENGTH+1);
@ -155,6 +185,8 @@ void setup() {
fifo_init(&packet_rdy_interfaces, packet_rdy_interfaces_buf, MAX_INTERFACES);
// add call to init_channel_stats here? \todo
// Create and configure interface objects
for (uint8_t i = 0; i < INTERFACE_COUNT; i++) {
switch (interfaces[i]) {
@ -324,34 +356,76 @@ inline void kiss_write_packet(int index) {
uint8_t cmd_byte = getInterfaceCommandByte(index);
serial_write(FEND);
// Add index of interface the packet came from
serial_write(cmd_byte);
for (uint16_t i = 0; i < read_len; i++) {
#if MCU_VARIANT == MCU_NRF52
portENTER_CRITICAL();
uint8_t byte = pbuf[i];
portEXIT_CRITICAL();
uint8_t byte = pbuf[i];
portEXIT_CRITICAL();
#else
uint8_t byte = pbuf[i];
#endif
if (byte == FEND) { serial_write(FESC); byte = TFEND; }
if (byte == FESC) { serial_write(FESC); byte = TFESC; }
serial_write(byte);
}
serial_write(FEND);
read_len = 0;
packet_ready = false;
#if MCU_VARIANT == MCU_ESP32 && HAS_BLE
bt_flush();
#endif
}
inline void getPacketData(RadioInterface* radio, uint16_t len) {
BaseType_t mask = taskENTER_CRITICAL_FROM_ISR();
while (len-- && read_len < MTU) {
pbuf[read_len++] = radio->read();
}
taskEXIT_CRITICAL_FROM_ISR(mask);
#if MCU_VARIANT != MCU_NRF52
while (len-- && read_len < MTU) {
pbuf[read_len++] = radio->read();
}
#else
BaseType_t int_mask = taskENTER_CRITICAL_FROM_ISR();
while (len-- && read_len < MTU) {
pbuf[read_len++] = radio->read();
}
taskEXIT_CRITICAL_FROM_ISR(int_mask);
#endif
}
void receive_callback(uint8_t index, int packet_size) {
selected_radio = interface_obj[index];
inline bool queue_packet(RadioInterface* radio, uint8_t index) {
// Allocate packet struct, but abort if there
// is not enough memory available.
modem_packet_t *modem_packet = (modem_packet_t*)malloc(sizeof(modem_packet_t) + read_len);
if(!modem_packet) { memory_low = true; return false; }
// Get packet RSSI and SNR
modem_packet->snr_raw = radio->packetSnrRaw();
// Pass raw SNR to get RSSI as SX127X driver requires it for calculations
modem_packet->rssi = radio->packetRssi(modem_packet->snr_raw);
modem_packet->interface = index;
// Send packet to event queue, but free the
// allocated memory again if the queue is
// unable to receive the packet.
modem_packet->len = read_len;
memcpy(modem_packet->data, pbuf, read_len);
if (!modem_packet_queue || xQueueSendFromISR(modem_packet_queue, &modem_packet, NULL) != pdPASS) {
free(modem_packet);
return false;
}
return true;
}
void ISR_VECT receive_callback(uint8_t index, int packet_size) {
selected_radio = interface_obj[index];
bool ready = false;
BaseType_t int_mask;
if (!promisc) {
// The standard operating mode allows large
// packets with a payload up to 500 bytes,
@ -362,37 +436,41 @@ void receive_callback(uint8_t index, int packet_size) {
uint8_t header = selected_radio->read(); packet_size--;
uint8_t sequence = packetSequence(header);
if (isSplitPacket(header) && seq == SEQ_UNSET) {
if (isSplitPacket(header) && seq[index] == SEQ_UNSET) {
// This is the first part of a split
// packet, so we set the seq variable
// and add the data to the buffer
BaseType_t mask = taskENTER_CRITICAL_FROM_ISR();
read_len = 0;
seq = sequence;
taskEXIT_CRITICAL_FROM_ISR(mask);
#if MCU_VARIANT == MCU_NRF52
int_mask = taskENTER_CRITICAL_FROM_ISR(); read_len = 0; taskEXIT_CRITICAL_FROM_ISR(int_mask);
#else
read_len = 0;
#endif
seq[index] = sequence;
getPacketData(selected_radio, packet_size);
} else if (isSplitPacket(header) && seq == sequence) {
} else if (isSplitPacket(header) && seq[index] == sequence) {
// This is the second part of a split
// packet, so we add it to the buffer
// and set the ready flag.
getPacketData(selected_radio, packet_size);
seq = SEQ_UNSET;
packet_interface = index;
packet_ready = true;
seq[index] = SEQ_UNSET;
ready = true;
} else if (isSplitPacket(header) && seq != sequence) {
} else if (isSplitPacket(header) && seq[index] != sequence) {
// This split packet does not carry the
// same sequence id, so we must assume
// that we are seeing the first part of
// a new split packet.
BaseType_t mask = taskENTER_CRITICAL_FROM_ISR();
read_len = 0;
seq = sequence;
taskEXIT_CRITICAL_FROM_ISR(mask);
#if MCU_VARIANT == MCU_NRF52
int_mask = taskENTER_CRITICAL_FROM_ISR(); read_len = 0; taskEXIT_CRITICAL_FROM_ISR(int_mask);
#else
read_len = 0;
#endif
seq[index] = sequence;
getPacketData(selected_radio, packet_size);
@ -401,31 +479,33 @@ void receive_callback(uint8_t index, int packet_size) {
// just read it and set the ready
// flag to true.
if (seq != SEQ_UNSET) {
if (seq[index] != SEQ_UNSET) {
// If we already had part of a split
// packet in the buffer, we clear it.
BaseType_t mask = taskENTER_CRITICAL_FROM_ISR();
read_len = 0;
seq = SEQ_UNSET;
taskEXIT_CRITICAL_FROM_ISR(mask);
#if MCU_VARIANT == MCU_NRF52
int_mask = taskENTER_CRITICAL_FROM_ISR(); read_len = 0; taskEXIT_CRITICAL_FROM_ISR(int_mask);
#else
read_len = 0;
#endif
seq[index] = SEQ_UNSET;
}
getPacketData(selected_radio, packet_size);
packet_interface = index;
packet_ready = true;
ready = true;
}
} else {
// In promiscuous mode, raw packets are
// output directly to the host
BaseType_t mask = taskENTER_CRITICAL_FROM_ISR();
read_len = 0;
taskEXIT_CRITICAL_FROM_ISR(mask);
getPacketData(selected_radio, packet_size);
packet_interface = index;
packet_ready = true;
ready = true;
}
if (ready) {
queue_packet(selected_radio, index);
}
last_rx = millis();
@ -536,6 +616,9 @@ void flushQueue(RadioInterface* radio) {
queued_bytes[index] = 0;
selected_radio->updateAirtime();
queue_flushing = false;
#if HAS_DISPLAY
display_tx = true;
#endif
}
void transmit(RadioInterface* radio, uint16_t size) {
@ -557,7 +640,9 @@ void transmit(RadioInterface* radio, uint16_t size) {
written++;
if (written == 255) {
// Only start a new packet if this is a split packet and it has
// exceeded the length of a single packet
if (written == 255 && header & 0x0F) {
radio->endPacket(); radio->addAirtime(written);
radio->beginPacket();
radio->write(header);
@ -565,7 +650,14 @@ void transmit(RadioInterface* radio, uint16_t size) {
}
}
radio->endPacket(); radio->addAirtime(written);
if (!radio->endPacket()) {
kiss_indicate_error(ERROR_MODEM_TIMEOUT);
kiss_indicate_error(ERROR_TXFAILED);
led_indicate_error(5);
hard_reset();
}
radio->addAirtime(written);
} else {
// In promiscuous mode, we only send out
// plain raw LoRa packets with a maximum
@ -800,6 +892,7 @@ void serialCallback(uint8_t sbyte) {
kiss_indicate_implicit_length();
} else if (command == CMD_LEAVE) {
if (sbyte == 0xFF) {
//display_unblank();
cable_state = CABLE_STATE_DISCONNECTED;
//current_rssi = -292;
last_rssi = -292;
@ -1041,7 +1134,13 @@ void serialCallback(uint8_t sbyte) {
bt_start();
bt_conf_save(true);
} else if (sbyte == 0x02) {
bt_enable_pairing();
if (bt_state == BT_STATE_OFF) {
bt_start();
bt_conf_save(true);
}
if (bt_state != BT_STATE_CONNECTED) {
bt_enable_pairing();
}
}
#endif
} else if (command == CMD_DISP_INT) {
@ -1056,6 +1155,7 @@ void serialCallback(uint8_t sbyte) {
}
display_intensity = sbyte;
di_conf_save(display_intensity);
//display_unblank();
}
#endif
@ -1089,6 +1189,37 @@ void serialCallback(uint8_t sbyte) {
if (frame_len == FW_LENGTH_LEN) {
set_fw_length(cmdbuf);
}
} else if (command == CMD_DISP_BLNK) {
#if HAS_DISPLAY
if (sbyte == FESC) {
ESCAPE = true;
} else {
if (ESCAPE) {
if (sbyte == TFEND) sbyte = FEND;
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
db_conf_save(sbyte);
//display_unblank();
}
#endif
} else if (command == CMD_NP_INT) {
#if HAS_NP
if (sbyte == FESC) {
ESCAPE = true;
} else {
if (ESCAPE) {
if (sbyte == TFEND) sbyte = FEND;
if (sbyte == TFESC) sbyte = FESC;
ESCAPE = false;
}
sbyte;
led_set_intensity(sbyte);
np_int_conf_save(sbyte);
}
#endif
}
}
}
@ -1154,7 +1285,7 @@ void validate_status() {
}
} else {
hw_ready = false;
Serial.write("No valid radio module found\r\n");
Serial.write("No radio module found\r\n");
#if HAS_DISPLAY
if (disp_ready) {
device_init_done = true;
@ -1164,6 +1295,7 @@ void validate_status() {
}
} else {
hw_ready = false;
Serial.write("Invalid EEPROM checksum\r\n");
#if HAS_DISPLAY
if (disp_ready) {
device_init_done = true;
@ -1173,6 +1305,7 @@ void validate_status() {
}
} else {
hw_ready = false;
Serial.write("Invalid EEPROM configuration\r\n");
#if HAS_DISPLAY
if (disp_ready) {
device_init_done = true;
@ -1182,6 +1315,7 @@ void validate_status() {
}
} else {
hw_ready = false;
Serial.write("Device unprovisioned, no device configuration found in EEPROM\r\n");
#if HAS_DISPLAY
if (disp_ready) {
device_init_done = true;
@ -1203,23 +1337,38 @@ void validate_status() {
}
void loop() {
if (packet_ready) {
#if MCU_VARIANT == MCU_ESP32
portENTER_CRITICAL(&update_lock);
#elif MCU_VARIANT == MCU_NRF52
portENTER_CRITICAL();
#endif
last_rssi = selected_radio->packetRssi();
last_snr_raw = selected_radio->packetSnrRaw();
#if MCU_VARIANT == MCU_ESP32
portEXIT_CRITICAL(&update_lock);
#elif MCU_VARIANT == MCU_NRF52
portEXIT_CRITICAL();
#endif
#if MCU_VARIANT == MCU_ESP32
modem_packet_t *modem_packet = NULL;
if(modem_packet_queue && xQueueReceive(modem_packet_queue, &modem_packet, 0) == pdTRUE && modem_packet) {
read_len = modem_packet->len;
last_rssi = modem_packet->rssi;
last_snr_raw = modem_packet->snr_raw;
packet_interface = modem_packet->interface;
memcpy(&pbuf, modem_packet->data, modem_packet->len);
free(modem_packet);
modem_packet = NULL;
kiss_indicate_stat_rssi();
kiss_indicate_stat_snr();
kiss_write_packet(packet_interface);
}
}
#elif MCU_VARIANT == MCU_NRF52
modem_packet_t *modem_packet = NULL;
if(modem_packet_queue && xQueueReceive(modem_packet_queue, &modem_packet, 0) == pdTRUE && modem_packet) {
memcpy(&pbuf, modem_packet->data, modem_packet->len);
read_len = modem_packet->len;
last_rssi = modem_packet->rssi;
last_snr_raw = modem_packet->snr_raw;
packet_interface = modem_packet->interface;
free(modem_packet);
modem_packet = NULL;
kiss_indicate_stat_rssi();
kiss_indicate_stat_snr();
kiss_write_packet(packet_interface);
}
#endif
bool ready = false;
for (int i = 0; i < INTERFACE_COUNT; i++) {
@ -1240,19 +1389,6 @@ void loop() {
continue;
}
// If a higher data rate interface has received a packet after its
// loop, it still needs to be the first to transmit, so check if this
// is the case.
for (int j = 0; j < INTERFACE_COUNT; j++) {
if (!interface_obj_sorted[j]->calculateALock() && interface_obj_sorted[j]->getRadioOnline()) {
if (interface_obj_sorted[j]->getBitrate() > selected_radio->getBitrate()) {
if (queue_height[interface_obj_sorted[j]->getIndex()] > 0) {
selected_radio = interface_obj_sorted[j];
}
}
}
}
if (queue_height[selected_radio->getIndex()] > 0) {
uint32_t check_time = millis();
if (check_time > selected_radio->getPostTxYieldTimeout()) {
@ -1335,6 +1471,17 @@ void loop() {
#if HAS_BUZZER
update_buzzer_notone();
#endif
if (memory_low) {
#if PLATFORM == PLATFORM_ESP32
if (esp_get_free_heap_size() < 8192) {
kiss_indicate_error(ERROR_MEMORY_LOW); memory_low = false;
} else {
memory_low = false;
}
#else
kiss_indicate_error(ERROR_MEMORY_LOW); memory_low = false;
#endif
}
}
void process_serial() {
@ -1347,6 +1494,7 @@ void button_event(uint8_t event, unsigned long duration) {
if (duration > BUTTON_MIN_DURATION) {
if (duration > BUTTON_6S_DURATION) {
bt_stop();
bt_conf_save(false);
} else if (duration > BUTTON_3S_DURATION) {
bt_enable_pairing();
} else {

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
# Copyright (C) 2023, Mark Qvist
# Copyright (C) 2024, Mark Qvist
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
#!/bin/python3
# Copyright (C) 2023, Mark Qvist
# Copyright (C) 2024, Mark Qvist
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

155
src/ble/BLESerial.cpp Normal file
View File

@ -0,0 +1,155 @@
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// This class is for BLE serial functionality on ESP32 boards ONLY
#include <Arduino.h>
#include "../../Boards.h"
#if PLATFORM != PLATFORM_NRF52
#if HAS_BLE
#include "BLESerial.h"
uint32_t bt_passkey_callback();
void bt_passkey_notify_callback(uint32_t passkey);
bool bt_security_request_callback();
void bt_authentication_complete_callback(esp_ble_auth_cmpl_t auth_result);
bool bt_confirm_pin_callback(uint32_t pin);
void bt_connect_callback(BLEServer *server);
void bt_disconnect_callback(BLEServer *server);
bool bt_client_authenticated();
uint32_t BLESerial::onPassKeyRequest() { return bt_passkey_callback(); }
void BLESerial::onPassKeyNotify(uint32_t passkey) { bt_passkey_notify_callback(passkey); }
bool BLESerial::onSecurityRequest() { return bt_security_request_callback(); }
void BLESerial::onAuthenticationComplete(esp_ble_auth_cmpl_t auth_result) { bt_authentication_complete_callback(auth_result); }
void BLESerial::onConnect(BLEServer *server) { bt_connect_callback(server); }
void BLESerial::onDisconnect(BLEServer *server) { bt_disconnect_callback(server); ble_server->startAdvertising(); }
bool BLESerial::onConfirmPIN(uint32_t pin) { return bt_confirm_pin_callback(pin); };
bool BLESerial::connected() { return ble_server->getConnectedCount() > 0; }
int BLESerial::read() {
int result = this->rx_buffer.pop();
if (result == '\n') { this->numAvailableLines--; }
return result;
}
size_t BLESerial::readBytes(uint8_t *buffer, size_t bufferSize) {
int i = 0;
while (i < bufferSize && available()) { buffer[i] = (uint8_t)this->rx_buffer.pop(); i++; }
return i;
}
int BLESerial::peek() {
if (this->rx_buffer.getLength() == 0) return -1;
return this->rx_buffer.get(0);
}
int BLESerial::available() { return this->rx_buffer.getLength(); }
size_t BLESerial::print(const char *str) {
if (ble_server->getConnectedCount() <= 0) return 0;
size_t written = 0; for (size_t i = 0; str[i] != '\0'; i++) { written += this->write(str[i]); }
flush();
return written;
}
size_t BLESerial::write(const uint8_t *buffer, size_t bufferSize) {
if (ble_server->getConnectedCount() <= 0) { return 0; } else {
size_t written = 0; for (int i = 0; i < bufferSize; i++) { written += this->write(buffer[i]); }
flush();
return written;
}
}
size_t BLESerial::write(uint8_t byte) {
if (bt_client_authenticated()) {
if (ble_server->getConnectedCount() <= 0) { return 0; } else {
this->transmitBuffer[this->transmitBufferLength] = byte;
this->transmitBufferLength++;
if (this->transmitBufferLength == maxTransferSize) { flush(); }
return 1;
}
} else {
return 0;
}
}
void BLESerial::flush() {
if (this->transmitBufferLength > 0) {
TxCharacteristic->setValue(this->transmitBuffer, this->transmitBufferLength);
this->transmitBufferLength = 0;
this->lastFlushTime = millis();
TxCharacteristic->notify(true);
}
}
void BLESerial::begin(const char *name) {
ConnectedDeviceCount = 0;
BLEDevice::init(name);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9);
ble_server = BLEDevice::createServer();
ble_server->setCallbacks(this);
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);
BLEDevice::setSecurityCallbacks(this);
SetupSerialService();
ble_adv = BLEDevice::getAdvertising();
ble_adv->addServiceUUID(BLE_SERIAL_SERVICE_UUID);
ble_adv->setMinPreferred(0x20);
ble_adv->setMaxPreferred(0x40);
ble_adv->setScanResponse(true);
ble_adv->start();
}
void BLESerial::end() { BLEDevice::deinit(); }
void BLESerial::onWrite(BLECharacteristic *characteristic) {
if (characteristic->getUUID().toString() == BLE_RX_UUID) {
auto value = characteristic->getValue();
for (int i = 0; i < value.length(); i++) { rx_buffer.push(value[i]); }
}
}
void BLESerial::SetupSerialService() {
SerialService = ble_server->createService(BLE_SERIAL_SERVICE_UUID);
RxCharacteristic = SerialService->createCharacteristic(BLE_RX_UUID, BLECharacteristic::PROPERTY_WRITE);
RxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM);
RxCharacteristic->addDescriptor(new BLE2902());
RxCharacteristic->setWriteProperty(true);
RxCharacteristic->setCallbacks(this);
TxCharacteristic = SerialService->createCharacteristic(BLE_TX_UUID, BLECharacteristic::PROPERTY_NOTIFY);
TxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM);
TxCharacteristic->addDescriptor(new BLE2902());
TxCharacteristic->setNotifyProperty(true);
TxCharacteristic->setReadProperty(true);
SerialService->start();
}
BLESerial::BLESerial() { }
#endif
#endif

135
src/ble/BLESerial.h Normal file
View File

@ -0,0 +1,135 @@
// Copyright (C) 2024, Mark Qvist
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// This class is for BLE serial functionality on ESP32 boards ONLY
#include "../../Boards.h"
#if PLATFORM != PLATFORM_NRF52
#if HAS_BLE
#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
template <size_t n>
class BLEFIFO {
private:
uint8_t buffer[n];
int head = 0;
int tail = 0;
public:
void push(uint8_t value) {
buffer[head] = value;
head = (head + 1) % n;
if (head == tail) { tail = (tail + 1) % n; }
}
int pop() {
if (head == tail) {
return -1;
} else {
uint8_t value = buffer[tail];
tail = (tail + 1) % n;
return value;
}
}
void clear() { head = 0; tail = 0; }
int get(size_t index) {
if (index >= this->getLength()) {
return -1;
} else {
return buffer[(tail + index) % n];
}
}
size_t getLength() {
if (head >= tail) {
return head - tail;
} else {
return n - tail + head;
}
}
};
#define RX_BUFFER_SIZE 6144
#define BLE_BUFFER_SIZE 512 // Must fit in max GATT attribute length
#define MIN_MTU 50
class BLESerial : public BLECharacteristicCallbacks, public BLEServerCallbacks, public BLESecurityCallbacks, public Stream {
public:
BLESerial();
void begin(const char *name);
void end();
void onWrite(BLECharacteristic *characteristic);
int available();
int peek();
int read();
size_t readBytes(uint8_t *buffer, size_t bufferSize);
size_t write(uint8_t byte);
size_t write(const uint8_t *buffer, size_t bufferSize);
size_t print(const char *value);
void flush();
void onConnect(BLEServer *server);
void onDisconnect(BLEServer *server);
uint32_t onPassKeyRequest();
void onPassKeyNotify(uint32_t passkey);
bool onSecurityRequest();
void onAuthenticationComplete(esp_ble_auth_cmpl_t);
bool onConfirmPIN(uint32_t pin);
bool connected();
BLEServer *ble_server;
BLEAdvertising *ble_adv;
BLEService *SerialService;
BLECharacteristic *TxCharacteristic;
BLECharacteristic *RxCharacteristic;
size_t transmitBufferLength;
unsigned long long lastFlushTime;
private:
BLESerial(BLESerial const &other) = delete;
void operator=(BLESerial const &other) = delete;
BLEFIFO<RX_BUFFER_SIZE> rx_buffer;
size_t numAvailableLines;
uint8_t transmitBuffer[BLE_BUFFER_SIZE];
int ConnectedDeviceCount;
void SetupSerialService();
uint16_t peerMTU;
uint16_t maxTransferSize = BLE_BUFFER_SIZE;
bool checkMTU();
const char *BLE_SERIAL_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
const char *BLE_RX_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
const char *BLE_TX_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
bool started = false;
};
#endif
#endif