diff --git a/Bluetooth.h b/Bluetooth.h
index 61505a5..5812b8e 100644
--- a/Bluetooth.h
+++ b/Bluetooth.h
@@ -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,8 +304,8 @@ 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
diff --git a/Boards.h b/Boards.h
index c9193fe..1aa6804 100644
--- a/Boards.h
+++ b/Boards.h
@@ -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
diff --git a/Config.h b/Config.h
index bba27d4..45b1e7b 100644
--- a/Config.h
+++ b/Config.h
@@ -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
diff --git a/Console.h b/Console.h
index 4321d9f..c59d348 100644
--- a/Console.h
+++ b/Console.h
@@ -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
diff --git a/Console/Makefile b/Console/Makefile
index 6fdfc65..15d06d2 100644
--- a/Console/Makefile
+++ b/Console/Makefile
@@ -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...
diff --git a/Console/build.py b/Console/build.py
index 5d8a119..f61fc04 100644
--- a/Console/build.py
+++ b/Console/build.py
@@ -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",
diff --git a/Device.h b/Device.h
index 760ff40..54a7e6c 100644
--- a/Device.h
+++ b/Device.h
@@ -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
diff --git a/Display.h b/Display.h
index 3b20efe..c9f9b3f 100644
--- a/Display.h
+++ b/Display.h
@@ -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,12 +13,29 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-
#include
#if DISPLAY == OLED
#include
#include
+#define DISPLAY_BLACK SSD1306_BLACK
+#define DISPLAY_WHITE SSD1306_WHITE
+
+#if BOARD_MODEL == BOARD_TDECK
+ #include
+ #define DISPLAY_BLACK ST77XX_BLACK
+ #define DISPLAY_WHITE ST77XX_WHITE
+#elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ #include
+ #define DISPLAY_BLACK ST77XX_BLACK
+ #define DISPLAY_WHITE ST77XX_WHITE
+#else
+ #include
+ #include
+#endif
+
+#include "Fonts/Org_01.h"
+
#define DISP_W 128
#define DISP_H 64
#elif DISPLAY == EINK_BW || DISPLAY == EINK_3C
@@ -29,6 +46,8 @@ void display_add_callback(void (*callback)()) {
void busyCallback(const void* p) {
display_callback();
}
+#define DISPLAY_BLACK GxEPD_BLACK
+#define DISPLAY_WHITE GxEPD_WHITE
#endif
#if DISPLAY == EINK_BW
// use GxEPD2 because adafruit EPD support for partial refresh is bad
@@ -75,10 +94,16 @@ void busyCallback(const void* p) {
#define SCL_OLED 17
#define SDA_OLED 18
#endif
-#elif BOARD_MODEL == BOARD_FREENODE
+#elif BOARD_MODEL == BOARD_OPENCOM_XL
#if DISPLAY == OLED
+ // RAK1921/SSD1306
+ #define DISP_RST -1
+ #define DISP_ADDR 0x3C
+ #define SCL_OLED 14
+ #define SDA_OLED 13
// todo: add support for OLED board
#elif DISPLAY == EINK_BW
+ // todo: change this to be defined in Boards.h in the future
#define DISP_W 250
#define DISP_H 122
#define DISP_ADDR -1
@@ -89,53 +114,71 @@ void busyCallback(const void* p) {
#define DISP_ADDR -1
#define DISPLAY_MODEL GxEPD2_213_Z98c
#endif
+#elif BOARD_MODEL == BOARD_TECHO
+ SPIClass displaySPI = SPIClass(NRF_SPIM0, pin_disp_miso, pin_disp_sck, pin_disp_mosi);
+ #define DISP_W 128
+ #define DISP_H 64
+ #define DISP_ADDR -1
+#elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ #define DISP_RST -1
+ #define DISP_ADDR 0x3C
+ #define SCL_OLED 18
+ #define SDA_OLED 17
+ #define DISP_CUSTOM_ADDR false
#else
#define DISP_RST -1
#define DISP_ADDR 0x3C
#define DISP_CUSTOM_ADDR true
#endif
-#define UNSCALED_MAX 64
-
#define SMALL_FONT &Org_01
#include "Graphics.h"
-#if BOARD_MODEL != BOARD_FREENODE
-// support for BOARD_FREENODE OLED not implemented yet
-#if DISPLAY == OLED
-Adafruit_SSD1306 display(DISP_W, DISP_H, &Wire, DISP_RST);
-float disp_target_fps = 7;
-#define SCREENSAVER_TIME 500 // ms
-uint32_t last_screensaver = 0;
-#define SCREENSAVER_INTERVAL 600000 // 10 minutes in ms
-bool screensaver_enabled = false;
-#endif
-#endif
-#if BOARD_MODEL == BOARD_FREENODE
-#if DISPLAY == EINK_BW
+#if BOARD_MODEL == BOARD_OPENCOM_XL
+ #if DISPLAY == EINK_BW
+ GxEPD2_BW display(DISPLAY_MODEL(pin_disp_cs, pin_disp_dc, pin_disp_reset, pin_disp_busy));
+ float disp_target_fps = 0.2;
+ uint32_t last_epd_refresh = 0;
+ #define REFRESH_PERIOD 300000 // 5 minutes in ms
+ #elif DISPLAY == EINK_3C
+ GxEPD2_3C display(DISPLAY_MODEL(pin_disp_cs, pin_disp_dc, pin_disp_reset, pin_disp_busy));
+ float disp_target_fps = 0.05; // refresh usually takes longer on 3C, hence this is 4x the BW refresh period
+ uint32_t last_epd_refresh = 0;
+ #define REFRESH_PERIOD 600000 // 10 minutes in ms
+ #endif
+#elif BOARD_MODEL == BOARD_TECHO
GxEPD2_BW display(DISPLAY_MODEL(pin_disp_cs, pin_disp_dc, pin_disp_reset, pin_disp_busy));
float disp_target_fps = 0.2;
uint32_t last_epd_refresh = 0;
#define REFRESH_PERIOD 300000 // 5 minutes in ms
-#elif DISPLAY == EINK_3C
-GxEPD2_3C display(DISPLAY_MODEL(pin_disp_cs, pin_disp_dc, pin_disp_reset, pin_disp_busy));
-float disp_target_fps = 0.05; // refresh usually takes longer on 3C, hence this is 4x the BW refresh period
-uint32_t last_epd_refresh = 0;
-#define REFRESH_PERIOD 600000 // 10 minutes in ms
-#endif
#else
-// add more eink compatible boards here
+ #if DISPLAY == OLED
+ #if BOARD_MODEL == BOARD_TDECK
+ Adafruit_ST7789 display = Adafruit_ST7789(DISPLAY_CS, DISPLAY_DC, -1);
+ #elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ Adafruit_SH1106G display = Adafruit_SH1106G(DISP_W, DISP_H, &Wire, -1);
+ #else
+ Adafruit_SSD1306 display(DISP_W, DISP_H, &Wire, DISP_RST);
+ #endif
+ float disp_target_fps = 7;
+ #define SCREENSAVER_TIME 500 // ms
+ uint32_t last_screensaver = 0;
+ #define SCREENSAVER_INTERVAL 600000 // 10 minutes in ms
+ bool screensaver_enabled = false;
+ #endif
#endif
#define DISP_MODE_UNKNOWN 0x00
#define DISP_MODE_LANDSCAPE 0x01
#define DISP_MODE_PORTRAIT 0x02
#define DISP_PIN_SIZE 6
+#define DISPLAY_BLANKING_TIMEOUT 15*1000
uint8_t disp_mode = DISP_MODE_UNKNOWN;
uint8_t disp_ext_fb = false;
unsigned char fb[512];
uint32_t last_disp_update = 0;
+bool display_tx = false;
int disp_update_interval = 1000/disp_target_fps;
uint32_t last_page_flip = 0;
@@ -156,12 +199,12 @@ uint8_t online_interface_list[INTERFACE_COUNT] = {0};
uint8_t online_interfaces = 0;
-#if DISPLAY == OLED
+#if DISP_H == 64
#define WATERFALL_SIZE 46
-#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+#elif DISP_H == 122
#define WATERFALL_SIZE 92
#else
-// add more eink compatible boards here
+#define WATERFALL_SIZE int(DISP_H * 0.75) // default to 75% of the display height
#endif
int waterfall[INTERFACE_COUNT][WATERFALL_SIZE] = {0};
@@ -172,12 +215,12 @@ int p_ad_y = 0;
int p_as_x = 0;
int p_as_y = 0;
-#if DISPLAY == OLED
-GFXcanvas1 stat_area(64, 64);
-GFXcanvas1 disp_area(64, 64);
-#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+#if DISP_H == 122
GFXcanvas1 stat_area(DISP_H, DISP_W/2);
GFXcanvas1 disp_area(DISP_H, DISP_W/2);
+#else
+GFXcanvas1 stat_area(64, 64);
+GFXcanvas1 disp_area(64, 64);
#endif
void update_area_positions() {
@@ -196,10 +239,40 @@ void update_area_positions() {
uint8_t display_contrast = 0x00;
#if DISPLAY == OLED
-void set_contrast(Adafruit_SSD1306 *display, uint8_t contrast) {
+#if BOARD_MODEL == BOARD_TBEAM_S_V1
+void set_contrast(Adafruit_SH1106G *display, uint8_t value) {
+}
+#elif BOARD_MODEL == BOARD_TDECK
+void set_contrast(Adafruit_ST7789 *display, uint8_t value) {
+static uint8_t level = 0;
+static uint8_t steps = 16;
+if (value > 15) value = 15;
+if (value == 0) {
+ digitalWrite(DISPLAY_BL_PIN, 0);
+ delay(3);
+ level = 0;
+ return;
+}
+if (level == 0) {
+ digitalWrite(DISPLAY_BL_PIN, 1);
+ level = steps;
+ delayMicroseconds(30);
+}
+int from = steps - level;
+int to = steps - value;
+int num = (steps + to - from) % steps;
+for (int i = 0; i < num; i++) {
+ digitalWrite(DISPLAY_BL_PIN, 0);
+ digitalWrite(DISPLAY_BL_PIN, 1);
+}
+level = value;
+}
+#else
+ void set_contrast(Adafruit_SSD1306 *display, uint8_t contrast) {
display->ssd1306_command(SSD1306_SETCONTRAST);
display->ssd1306_command(contrast);
-}
+ }
+#endif
#endif
bool display_init() {
@@ -231,7 +304,19 @@ bool display_init() {
delay(50);
digitalWrite(pin_display_en, HIGH);
Wire.begin(SDA_OLED, SCL_OLED);
- #elif BOARD_MODEL == BOARD_FREENODE
+ #elif BOARD_MODEL == BOARD_TECHO
+ pinMode(pin_disp_en, INPUT_PULLUP);
+ digitalWrite(pin_disp_en, HIGH);
+
+ display.init(0, true, 10, false, displaySPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
+ display.setPartialWindow(0, 0, DISP_W, DISP_H);
+
+ // Because refreshing this display can take some time, sometimes serial
+ // commands will be missed. Therefore, during periods where the device is
+ // waiting for the display to update, it will poll the serial buffer to
+ // check for any commands from the host.
+ display.epd2.setBusyCallback(busyCallback);
+ #elif BOARD_MODEL == BOARD_OPENCOM_XL
#if DISPLAY == OLED
#elif DISPLAY == EINK_BW || DISPLAY == EINK_3C
pinMode(pin_disp_en, INPUT_PULLUP);
@@ -245,6 +330,8 @@ bool display_init() {
// check for any commands from the host.
display.epd2.setBusyCallback(busyCallback);
#endif
+ #elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ Wire.begin(SDA_OLED, SCL_OLED);
#endif
#if DISP_CUSTOM_ADDR == true
@@ -258,12 +345,17 @@ bool display_init() {
uint8_t display_address = DISP_ADDR;
#endif
-
- #if DISPLAY == OLED
- if(!display.begin(SSD1306_SWITCHCAPVCC, display_address)) {
- #elif DISPLAY == EINK_BW || DISPLAY == EINK_3C
+ #if DISPLAY == EINK_BW || DISPLAY == EINK_3C
// don't check if display is actually connected
if(false) {
+ #elif BOARD_MODEL == BOARD_TDECK
+ display.init(240, 320);
+ display.setSPISpeed(80e6);
+ if (false) {
+ #elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ if (!display.begin(display_address, true)) {
+ #else
+ if (!display.begin(SSD1306_SWITCHCAPVCC, display_address)) {
#endif
return false;
} else {
@@ -288,20 +380,29 @@ bool display_init() {
#elif BOARD_MODEL == BOARD_TBEAM
disp_mode = DISP_MODE_LANDSCAPE;
display.setRotation(0);
+ #elif BOARD_MODEL == BOARD_TBEAM_S_V1
+ disp_mode = DISP_MODE_PORTRAIT;
+ display.setRotation(1);
#elif BOARD_MODEL == BOARD_HELTEC32_V2
disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(1);
- #elif BOARD_MODEL == BOARD_FREENODE
+ #elif BOARD_MODEL == BOARD_OPENCOM_XL
#if DISPLAY == OLED
#elif DISPLAY == EINK_BW || DISPLAY == EINK_3C
disp_mode = DISP_MODE_PORTRAIT;
#endif
+ #elif BOARD_MODEL == BOARD_TECHO
+ disp_mode = DISP_MODE_LANDSCAPE;
+ display.setRotation(3);
#elif BOARD_MODEL == BOARD_HELTEC32_V3
disp_mode = DISP_MODE_PORTRAIT;
- // Antenna conx up
display.setRotation(1);
- // USB-C up
- // display.setRotation(3);
+ #elif BOARD_MODEL == BOARD_RAK4631
+ disp_mode = DISP_MODE_LANDSCAPE;
+ display.setRotation(0);
+ #elif BOARD_MODEL == BOARD_TDECK
+ disp_mode = DISP_MODE_PORTRAIT;
+ display.setRotation(3);
#else
disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(3);
@@ -315,10 +416,14 @@ bool display_init() {
disp_area.cp437(true);
display.cp437(true);
- #if HAS_EEPROM
- display_intensity = EEPROM.read(eeprom_addr(ADDR_CONF_DINT));
- #elif MCU_VARIANT == MCU_NRF52
- display_intensity = eeprom_read(eeprom_addr(ADDR_CONF_DINT));
+ #if MCU_VARIANT != MCU_NRF52
+ display_intensity = EEPROM.read(eeprom_addr(ADDR_CONF_DINT));
+ #else
+ display_intensity = eeprom_read(eeprom_addr(ADDR_CONF_DINT));
+ #endif
+
+ #if BOARD_MODEL == BOARD_TDECK
+ display.fillScreen(DISPLAY_BLACK);
#endif
return true;
@@ -330,50 +435,50 @@ bool display_init() {
void draw_cable_icon(int px, int py) {
if (cable_state == CABLE_STATE_DISCONNECTED) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_cable+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_cable+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_cable+0*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_cable+0*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else if (cable_state == CABLE_STATE_CONNECTED) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_cable+1*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_cable+1*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_cable+1*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_cable+1*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
void draw_bt_icon(int px, int py) {
if (bt_state == BT_STATE_OFF) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_bt+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_bt+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_bt+0*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_bt+0*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else if (bt_state == BT_STATE_ON) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_bt+1*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_bt+1*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_bt+1*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_bt+1*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else if (bt_state == BT_STATE_PAIRING) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_bt+2*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_bt+2*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_bt+2*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_bt+2*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else if (bt_state == BT_STATE_CONNECTED) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_bt+3*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_bt+3*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_bt+3*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_bt+3*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_bt+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_bt+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_bt+0*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_bt+0*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
@@ -381,60 +486,60 @@ void draw_bt_icon(int px, int py) {
void draw_lora_icon(RadioInterface* radio, int px, int py) {
// todo: make display show other interfaces
if (radio_online) {
- #if DISPLAY == OLED
- if (online_interface_list[interface_page] != radio->getIndex()) {
- stat_area.drawBitmap(px - 1, py-1, bm_dot_sqr, 18, 19, SSD1306_WHITE, SSD1306_BLACK);
+ #if DISP_H == 122
+ if (online_interface_list[interface_page] != radio->getIndex()) {
+ stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 34, 36, DISPLAY_WHITE, DISPLAY_BLACK);
- // redraw stat area on next refresh
- stat_area_initialised = false;
- }
- if (radio->getRadioOnline()) {
- stat_area.drawBitmap(px, py, bm_rf+1*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- } else {
- stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- }
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- if (online_interface_list[interface_page] != radio->getIndex()) {
- stat_area.drawBitmap(px - 2, py - 2, bm_dot_sqr, 34, 36, GxEPD_WHITE, GxEPD_BLACK);
+ // redraw stat area on next refresh
+ stat_area_initialised = false;
+ }
+ if (radio->getRadioOnline()) {
+ stat_area.drawBitmap(px, py, bm_rf+1*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ } else {
+ stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ }
+ #else
+ if (online_interface_list[interface_page] != radio->getIndex()) {
+ stat_area.drawBitmap(px - 1, py - 1, bm_dot_sqr, 18, 19, DISPLAY_WHITE, DISPLAY_BLACK);
- // redraw stat area on next refresh
- stat_area_initialised = false;
- }
- if (radio->getRadioOnline()) {
- stat_area.drawBitmap(px, py, bm_rf+1*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
- } else {
- stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
- }
- #endif
- } else {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
- #endif
- }
+ // redraw stat area on next refresh
+ stat_area_initialised = false;
+ }
+ if (radio->getRadioOnline()) {
+ stat_area.drawBitmap(px, py, bm_rf+1*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
+ } else {
+ stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
+ }
+ #endif
+ } else {
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_rf+0*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_rf+0*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
+ #endif
+ }
}
void draw_mw_icon(int px, int py) {
if (INTERFACE_COUNT >= 2) {
if (interface_obj[1]->getRadioOnline()) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_rf+3*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_rf+3*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_rf+3*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_rf+3*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_rf+2*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_rf+2*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_rf+2*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_rf+2*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
} else {
- #if DISPLAY == OLED
- stat_area.drawBitmap(px, py, bm_rf+2*32, 16, 16, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(px, py, bm_rf+2*128, 30, 32, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(px, py, bm_rf+2*128, 30, 32, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(px, py, bm_rf+2*32, 16, 16, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
@@ -444,79 +549,87 @@ void draw_battery_bars(int px, int py) {
if (pmu_ready) {
if (battery_ready) {
if (battery_installed) {
- float battery_value = battery_percent;
+ float battery_value = battery_percent;
+
+ // Disable charging state display for now, since
+ // boards without dedicated PMU are completely
+ // unreliable for determining actual charging state.
+ bool disable_charge_status = false;
+ if (battery_indeterminate && battery_state == BATTERY_STATE_CHARGING) {
+ disable_charge_status = true;
+ }
- if (battery_state == BATTERY_STATE_CHARGING) {
+ if (battery_state == BATTERY_STATE_CHARGING && !disable_charge_status) {
battery_value = charge_tick;
charge_tick += 3;
if (charge_tick > 100) charge_tick = 0;
}
- if (battery_indeterminate && battery_state == BATTERY_STATE_CHARGING) {
- #if DISPLAY == OLED
- stat_area.fillRect(px-2, py-2, 18, 7, SSD1306_BLACK);
- stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px-2, py-2, 24, 9, GxEPD_BLACK);
- stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, GxEPD_WHITE, GxEPD_BLACK);
+ if (battery_indeterminate && battery_state == BATTERY_STATE_CHARGING && !disable_charge_status) {
+ #if DISP_H == 122
+ stat_area.fillRect(px-2, py-2, 24, 9, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.fillRect(px-2, py-2, 18, 7, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
if (battery_state == BATTERY_STATE_CHARGED) {
- #if DISPLAY == OLED
- stat_area.fillRect(px-2, py-2, 18, 7, SSD1306_BLACK);
- stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px-2, py-2, 24, 9, GxEPD_BLACK);
- stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.fillRect(px-2, py-2, 24, 9, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.fillRect(px-2, py-2, 18, 7, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- stat_area.fillRect(px, py, 14, 3, SSD1306_BLACK);
- stat_area.fillRect(px-2, py-2, 18, 7, SSD1306_BLACK);
- stat_area.drawRect(px-2, py-2, 17, 7, SSD1306_WHITE);
- stat_area.drawLine(px+15, py, px+15, py+3, SSD1306_WHITE);
- if (battery_value > 7) stat_area.drawLine(px, py, px, py+2, SSD1306_WHITE);
- if (battery_value > 20) stat_area.drawLine(px+1*2, py, px+1*2, py+2, SSD1306_WHITE);
- if (battery_value > 33) stat_area.drawLine(px+2*2, py, px+2*2, py+2, SSD1306_WHITE);
- if (battery_value > 46) stat_area.drawLine(px+3*2, py, px+3*2, py+2, SSD1306_WHITE);
- if (battery_value > 59) stat_area.drawLine(px+4*2, py, px+4*2, py+2, SSD1306_WHITE);
- if (battery_value > 72) stat_area.drawLine(px+5*2, py, px+5*2, py+2, SSD1306_WHITE);
- if (battery_value > 85) stat_area.drawLine(px+6*2, py, px+6*2, py+2, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px, py, 20, 5, GxEPD_BLACK);
- stat_area.fillRect(px-2, py-4, 34, 19, GxEPD_BLACK);
- stat_area.drawRect(px-2, py-2, 23, 9, GxEPD_WHITE);
- stat_area.drawLine(px+21, py, px+21, py+5, GxEPD_WHITE);
- if (battery_value > 0) stat_area.drawLine(px, py, px, py+4, GxEPD_WHITE);
- if (battery_value >= 10) stat_area.drawLine(px+1*2, py, px+1*2, py+4, GxEPD_WHITE);
- if (battery_value >= 20) stat_area.drawLine(px+2*2, py, px+2*2, py+4, GxEPD_WHITE);
- if (battery_value >= 30) stat_area.drawLine(px+3*2, py, px+3*2, py+4, GxEPD_WHITE);
- if (battery_value >= 40) stat_area.drawLine(px+4*2, py, px+4*2, py+4, GxEPD_WHITE);
- if (battery_value >= 50) stat_area.drawLine(px+5*2, py, px+5*2, py+4, GxEPD_WHITE);
- if (battery_value >= 60) stat_area.drawLine(px+6*2, py, px+6*2, py+4, GxEPD_WHITE);
- if (battery_value >= 70) stat_area.drawLine(px+7*2, py, px+7*2, py+4, GxEPD_WHITE);
- if (battery_value >= 80) stat_area.drawLine(px+8*2, py, px+8*2, py+4, GxEPD_WHITE);
- if (battery_value >= 90) stat_area.drawLine(px+9*2, py, px+9*2, py+4, GxEPD_WHITE);
+ #if DISP_H == 122
+ stat_area.fillRect(px, py, 20, 5, DISPLAY_BLACK);
+ stat_area.fillRect(px-2, py-4, 34, 19, DISPLAY_BLACK);
+ stat_area.drawRect(px-2, py-2, 23, 9, DISPLAY_WHITE);
+ stat_area.drawLine(px+21, py, px+21, py+5, DISPLAY_WHITE);
+ if (battery_value > 0) stat_area.drawLine(px, py, px, py+4, DISPLAY_WHITE);
+ if (battery_value >= 10) stat_area.drawLine(px+1*2, py, px+1*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 20) stat_area.drawLine(px+2*2, py, px+2*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 30) stat_area.drawLine(px+3*2, py, px+3*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 40) stat_area.drawLine(px+4*2, py, px+4*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 50) stat_area.drawLine(px+5*2, py, px+5*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 60) stat_area.drawLine(px+6*2, py, px+6*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 70) stat_area.drawLine(px+7*2, py, px+7*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 80) stat_area.drawLine(px+8*2, py, px+8*2, py+4, DISPLAY_WHITE);
+ if (battery_value >= 90) stat_area.drawLine(px+9*2, py, px+9*2, py+4, DISPLAY_WHITE);
+ #else
+ stat_area.fillRect(px, py, 14, 3, DISPLAY_BLACK);
+ stat_area.fillRect(px-2, py-2, 18, 7, DISPLAY_BLACK);
+ stat_area.drawRect(px-2, py-2, 17, 7, DISPLAY_WHITE);
+ stat_area.drawLine(px+15, py, px+15, py+3, DISPLAY_WHITE);
+ if (battery_value > 7) stat_area.drawLine(px, py, px, py+2, DISPLAY_WHITE);
+ if (battery_value > 20) stat_area.drawLine(px+1*2, py, px+1*2, py+2, DISPLAY_WHITE);
+ if (battery_value > 33) stat_area.drawLine(px+2*2, py, px+2*2, py+2, DISPLAY_WHITE);
+ if (battery_value > 46) stat_area.drawLine(px+3*2, py, px+3*2, py+2, DISPLAY_WHITE);
+ if (battery_value > 59) stat_area.drawLine(px+4*2, py, px+4*2, py+2, DISPLAY_WHITE);
+ if (battery_value > 72) stat_area.drawLine(px+5*2, py, px+5*2, py+2, DISPLAY_WHITE);
+ if (battery_value > 85) stat_area.drawLine(px+6*2, py, px+6*2, py+2, DISPLAY_WHITE);
#endif
}
}
} else {
- #if DISPLAY == OLED
- stat_area.fillRect(px-2, py-2, 18, 7, SSD1306_BLACK);
- stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px-2, py-2, 24, 9, GxEPD_BLACK);
- stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.fillRect(px-2, py-2, 24, 9, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.fillRect(px-2, py-2, 18, 7, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
} else {
- #if DISPLAY == OLED
- stat_area.fillRect(px-2, py-2, 18, 7, SSD1306_BLACK);
- stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px-2, py-2, 24, 9, GxEPD_BLACK);
- stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.fillRect(px-2, py-2, 24, 9, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-5, bm_plug, 34, 13, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.fillRect(px-2, py-2, 18, 7, DISPLAY_BLACK);
+ stat_area.drawBitmap(px-2, py-2, bm_plug, 17, 7, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
@@ -524,145 +637,154 @@ void draw_battery_bars(int px, int py) {
#define Q_SNR_STEP 2.0
#define Q_SNR_MIN_BASE -9.0
#define Q_SNR_MAX 6.0
-void draw_quality_bars(int px, int py) {
- signed char t_snr = (signed int)last_snr_raw;
- int snr_int = (int)t_snr;
- float snr_min = Q_SNR_MIN_BASE-(int)interface_obj[interface_page]->getSpreadingFactor()*Q_SNR_STEP;
- float snr_span = (Q_SNR_MAX-snr_min);
- float snr = ((int)snr_int) * 0.25;
- float quality = ((snr-snr_min)/(snr_span))*100;
- if (quality > 100.0) quality = 100.0;
- if (quality < 0.0) quality = 0.0;
- #if DISPLAY == OLED
- stat_area.fillRect(px, py, 13, 7, SSD1306_BLACK);
- if (quality > 0) stat_area.drawLine(px+0*2, py+7, px+0*2, py+6, SSD1306_WHITE);
- if (quality > 15) stat_area.drawLine(px+1*2, py+7, px+1*2, py+5, SSD1306_WHITE);
- if (quality > 30) stat_area.drawLine(px+2*2, py+7, px+2*2, py+4, SSD1306_WHITE);
- if (quality > 45) stat_area.drawLine(px+3*2, py+7, px+3*2, py+3, SSD1306_WHITE);
- if (quality > 60) stat_area.drawLine(px+4*2, py+7, px+4*2, py+2, SSD1306_WHITE);
- if (quality > 75) stat_area.drawLine(px+5*2, py+7, px+5*2, py+1, SSD1306_WHITE);
- if (quality > 90) stat_area.drawLine(px+6*2, py+7, px+6*2, py+0, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px, py, 26, 14, GxEPD_BLACK);
- if (quality > 0) {
- stat_area.drawLine(px+0*4, py+14, px+0*4, py+6, GxEPD_WHITE);
- stat_area.drawLine(px+0*4+1, py+14, px+0*4+1, py+6, GxEPD_WHITE);
- }
- if (quality > 15) {
- stat_area.drawLine(px+1*4, py+14, px+1*4, py+5, GxEPD_WHITE);
- stat_area.drawLine(px+1*4+1, py+14, px+1*4+1, py+5, GxEPD_WHITE);
- }
- if (quality > 30) {
- stat_area.drawLine(px+2*4, py+14, px+2*4, py+4, GxEPD_WHITE);
- stat_area.drawLine(px+2*4+1, py+14, px+2*4+1, py+4, GxEPD_WHITE);
- }
- if (quality > 45) {
- stat_area.drawLine(px+3*4, py+14, px+3*4, py+3, GxEPD_WHITE);
- stat_area.drawLine(px+3*4+1, py+14, px+3*4+1, py+3, GxEPD_WHITE);
- }
- if (quality > 60) {
- stat_area.drawLine(px+4*4, py+14, px+4*4, py+2, GxEPD_WHITE);
- stat_area.drawLine(px+4*4+1, py+14, px+4*4+1, py+2, GxEPD_WHITE);
- }
- if (quality > 75) {
- stat_area.drawLine(px+5*4, py+14, px+5*4, py+1, GxEPD_WHITE);
- stat_area.drawLine(px+5*4+1, py+14, px+5*4+1, py+1, GxEPD_WHITE);
- }
- if (quality > 90) {
- stat_area.drawLine(px+6*4, py+14, px+6*4, py+0, GxEPD_WHITE);
- stat_area.drawLine(px+6*4+1, py+14, px+6*4+1, py+0, GxEPD_WHITE);
- }
- #endif
- // Serial.printf("Last SNR: %.2f\n, quality: %.2f\n", snr, quality);
+void draw_quality_bars(int px, int py) {
+ signed char t_snr = (signed int)last_snr_raw;
+ int snr_int = (int)t_snr;
+ float snr_min = Q_SNR_MIN_BASE-(int)interface_obj[interface_page]->getSpreadingFactor()*Q_SNR_STEP;
+ float snr_span = (Q_SNR_MAX-snr_min);
+ float snr = ((int)snr_int) * 0.25;
+ float quality = ((snr-snr_min)/(snr_span))*100;
+ if (quality > 100.0) quality = 100.0;
+ if (quality < 0.0) quality = 0.0;
+
+#if DISP_H == 122
+ stat_area.fillRect(px, py, 26, 14, DISPLAY_BLACK);
+ if (quality > 0) {
+ stat_area.drawLine(px+0*4, py+14, px+0*4, py+6, DISPLAY_WHITE);
+ stat_area.drawLine(px+0*4+1, py+14, px+0*4+1, py+6, DISPLAY_WHITE);
+ }
+ if (quality > 15) {
+ stat_area.drawLine(px+1*4, py+14, px+1*4, py+5, DISPLAY_WHITE);
+ stat_area.drawLine(px+1*4+1, py+14, px+1*4+1, py+5, DISPLAY_WHITE);
+ }
+ if (quality > 30) {
+ stat_area.drawLine(px+2*4, py+14, px+2*4, py+4, DISPLAY_WHITE);
+ stat_area.drawLine(px+2*4+1, py+14, px+2*4+1, py+4, DISPLAY_WHITE);
+ }
+ if (quality > 45) {
+ stat_area.drawLine(px+3*4, py+14, px+3*4, py+3, DISPLAY_WHITE);
+ stat_area.drawLine(px+3*4+1, py+14, px+3*4+1, py+3, DISPLAY_WHITE);
+ }
+ if (quality > 60) {
+ stat_area.drawLine(px+4*4, py+14, px+4*4, py+2, DISPLAY_WHITE);
+ stat_area.drawLine(px+4*4+1, py+14, px+4*4+1, py+2, DISPLAY_WHITE);
+ }
+ if (quality > 75) {
+ stat_area.drawLine(px+5*4, py+14, px+5*4, py+1, DISPLAY_WHITE);
+ stat_area.drawLine(px+5*4+1, py+14, px+5*4+1, py+1, DISPLAY_WHITE);
+ }
+ if (quality > 90) {
+ stat_area.drawLine(px+6*4, py+14, px+6*4, py+0, DISPLAY_WHITE);
+ stat_area.drawLine(px+6*4+1, py+14, px+6*4+1, py+0, DISPLAY_WHITE);
+ }
+#else
+ stat_area.fillRect(px, py, 13, 7, DISPLAY_BLACK);
+ if (quality > 0) stat_area.drawLine(px+0*2, py+7, px+0*2, py+6, DISPLAY_WHITE);
+ if (quality > 15) stat_area.drawLine(px+1*2, py+7, px+1*2, py+5, DISPLAY_WHITE);
+ if (quality > 30) stat_area.drawLine(px+2*2, py+7, px+2*2, py+4, DISPLAY_WHITE);
+ if (quality > 45) stat_area.drawLine(px+3*2, py+7, px+3*2, py+3, DISPLAY_WHITE);
+ if (quality > 60) stat_area.drawLine(px+4*2, py+7, px+4*2, py+2, DISPLAY_WHITE);
+ if (quality > 75) stat_area.drawLine(px+5*2, py+7, px+5*2, py+1, DISPLAY_WHITE);
+ if (quality > 90) stat_area.drawLine(px+6*2, py+7, px+6*2, py+0, DISPLAY_WHITE);
+#endif
+ // Serial.printf("Last SNR: %.2f\n, quality: %.2f\n", snr, quality);
}
#define S_RSSI_MIN -135.0
#define S_RSSI_MAX -75.0
#define S_RSSI_SPAN (S_RSSI_MAX-S_RSSI_MIN)
void draw_signal_bars(int px, int py) {
- int rssi_val = last_rssi;
- if (rssi_val < S_RSSI_MIN) rssi_val = S_RSSI_MIN;
- if (rssi_val > S_RSSI_MAX) rssi_val = S_RSSI_MAX;
- int signal = ((rssi_val - S_RSSI_MIN)*(1.0/S_RSSI_SPAN))*100.0;
+ int rssi_val = last_rssi;
+ if (rssi_val < S_RSSI_MIN) rssi_val = S_RSSI_MIN;
+ if (rssi_val > S_RSSI_MAX) rssi_val = S_RSSI_MAX;
+ int signal = ((rssi_val - S_RSSI_MIN)*(1.0/S_RSSI_SPAN))*100.0;
- if (signal > 100.0) signal = 100.0;
- if (signal < 0.0) signal = 0.0;
+ if (signal > 100.0) signal = 100.0;
+ if (signal < 0.0) signal = 0.0;
- #if DISPLAY == OLED
- stat_area.fillRect(px, py, 13, 7, SSD1306_BLACK);
- if (signal > 85) stat_area.drawLine(px+0*2, py+7, px+0*2, py+0, SSD1306_WHITE);
- if (signal > 72) stat_area.drawLine(px+1*2, py+7, px+1*2, py+1, SSD1306_WHITE);
- if (signal > 59) stat_area.drawLine(px+2*2, py+7, px+2*2, py+2, SSD1306_WHITE);
- if (signal > 46) stat_area.drawLine(px+3*2, py+7, px+3*2, py+3, SSD1306_WHITE);
- if (signal > 33) stat_area.drawLine(px+4*2, py+7, px+4*2, py+4, SSD1306_WHITE);
- if (signal > 20) stat_area.drawLine(px+5*2, py+7, px+5*2, py+5, SSD1306_WHITE);
- if (signal > 7) stat_area.drawLine(px+6*2, py+7, px+6*2, py+6, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px, py, 26, 14, GxEPD_BLACK);
- if (signal > 85) {
- stat_area.drawLine(px+0*4, py+14, px+0*4, py+0, GxEPD_WHITE);
- stat_area.drawLine(px+0*4+1, py+14, px+0*4+1, py+0, GxEPD_WHITE);
- }
- if (signal > 72) {
- stat_area.drawLine(px+1*4, py+14, px+1*4, py+1, GxEPD_WHITE);
- stat_area.drawLine(px+1*4+1, py+14, px+1*4+1, py+1, GxEPD_WHITE);
- }
- if (signal > 59) {
- stat_area.drawLine(px+2*4, py+14, px+2*4, py+2, GxEPD_WHITE);
- stat_area.drawLine(px+2*4+1, py+14, px+2*4+1, py+2, GxEPD_WHITE);
- }
- if (signal > 46) {
- stat_area.drawLine(px+3*4, py+14, px+3*4, py+3, GxEPD_WHITE);
- stat_area.drawLine(px+3*4+1, py+14, px+3*4+1, py+3, GxEPD_WHITE);
- }
- if (signal > 33) {
- stat_area.drawLine(px+4*4, py+14, px+4*4, py+4, GxEPD_WHITE);
- stat_area.drawLine(px+4*4+1, py+14, px+4*4+1, py+4, GxEPD_WHITE);
- }
- if (signal > 20) {
- stat_area.drawLine(px+5*4, py+14, px+5*4, py+5, GxEPD_WHITE);
- stat_area.drawLine(px+5*4+1, py+14, px+5*4+1, py+5, GxEPD_WHITE);
- }
- if (signal > 7) {
- stat_area.drawLine(px+6*4, py+14, px+6*4, py+6, GxEPD_WHITE);
- stat_area.drawLine(px+6*4+1, py+14, px+6*4+1, py+6, GxEPD_WHITE);
- }
- #endif
- // Serial.printf("Last SNR: %.2f\n, quality: %.2f\n", snr, quality);
+#if DISP_H == 122
+ stat_area.fillRect(px, py, 26, 14, DISPLAY_BLACK);
+ if (signal > 85) {
+ stat_area.drawLine(px+0*4, py+14, px+0*4, py+0, DISPLAY_WHITE);
+ stat_area.drawLine(px+0*4+1, py+14, px+0*4+1, py+0, DISPLAY_WHITE);
+ }
+ if (signal > 72) {
+ stat_area.drawLine(px+1*4, py+14, px+1*4, py+1, DISPLAY_WHITE);
+ stat_area.drawLine(px+1*4+1, py+14, px+1*4+1, py+1, DISPLAY_WHITE);
+ }
+ if (signal > 59) {
+ stat_area.drawLine(px+2*4, py+14, px+2*4, py+2, DISPLAY_WHITE);
+ stat_area.drawLine(px+2*4+1, py+14, px+2*4+1, py+2, DISPLAY_WHITE);
+ }
+ if (signal > 46) {
+ stat_area.drawLine(px+3*4, py+14, px+3*4, py+3, DISPLAY_WHITE);
+ stat_area.drawLine(px+3*4+1, py+14, px+3*4+1, py+3, DISPLAY_WHITE);
+ }
+ if (signal > 33) {
+ stat_area.drawLine(px+4*4, py+14, px+4*4, py+4, DISPLAY_WHITE);
+ stat_area.drawLine(px+4*4+1, py+14, px+4*4+1, py+4, DISPLAY_WHITE);
+ }
+ if (signal > 20) {
+ stat_area.drawLine(px+5*4, py+14, px+5*4, py+5, DISPLAY_WHITE);
+ stat_area.drawLine(px+5*4+1, py+14, px+5*4+1, py+5, DISPLAY_WHITE);
+ }
+ if (signal > 7) {
+ stat_area.drawLine(px+6*4, py+14, px+6*4, py+6, DISPLAY_WHITE);
+ stat_area.drawLine(px+6*4+1, py+14, px+6*4+1, py+6, DISPLAY_WHITE);
+ }
+#else
+ stat_area.fillRect(px, py, 13, 7, DISPLAY_BLACK);
+ if (signal > 85) stat_area.drawLine(px+0*2, py+7, px+0*2, py+0, DISPLAY_WHITE);
+ if (signal > 72) stat_area.drawLine(px+1*2, py+7, px+1*2, py+1, DISPLAY_WHITE);
+ if (signal > 59) stat_area.drawLine(px+2*2, py+7, px+2*2, py+2, DISPLAY_WHITE);
+ if (signal > 46) stat_area.drawLine(px+3*2, py+7, px+3*2, py+3, DISPLAY_WHITE);
+ if (signal > 33) stat_area.drawLine(px+4*2, py+7, px+4*2, py+4, DISPLAY_WHITE);
+ if (signal > 20) stat_area.drawLine(px+5*2, py+7, px+5*2, py+5, DISPLAY_WHITE);
+ if (signal > 7) stat_area.drawLine(px+6*2, py+7, px+6*2, py+6, DISPLAY_WHITE);
+#endif
+ // Serial.printf("Last SNR: %.2f\n, quality: %.2f\n", snr, quality);
}
+#define WF_TX_SIZE 5
+#define WF_TX_WIDTH 5
#define WF_RSSI_MAX -60
#define WF_RSSI_MIN -135
-#define WF_RSSI_SPAN (WF_RSSI_MAX-WF_RSSI_MIN)
-#if DISPLAY == OLED
-#define WF_PIXEL_WIDTH 10
-#elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+#define WF_RSSI_SPAN (WF_RSSI_MAX - WF_RSSI_MIN)
+#if DISP_H == 122
#define WF_PIXEL_WIDTH 22
+#elif disp_mode == DISP_MODE_LANDSCAPE
+#define WF_PIXEL_WIDTH (DISP_H / WF_RSSI_SPAN)
+#else
+#define WF_PIXEL_WIDTH (DISP_W / WF_RSSI_SPAN)
#endif
void draw_waterfall(int px, int py) {
int rssi_val = interface_obj[interface_page]->currentRssi();
if (rssi_val < WF_RSSI_MIN) rssi_val = WF_RSSI_MIN;
if (rssi_val > WF_RSSI_MAX) rssi_val = WF_RSSI_MAX;
int rssi_normalised = ((rssi_val - WF_RSSI_MIN)*(1.0/WF_RSSI_SPAN))*WF_PIXEL_WIDTH;
+ if (display_tx) {
+ for (uint8_t i; i < WF_TX_SIZE; i++) {
+ waterfall[interface_page][waterfall_head[interface_page]++] = -1;
+ if (waterfall_head[interface_page] >= WATERFALL_SIZE) waterfall_head[interface_page] = 0;
+ }
+ display_tx = false;
+ } else {
+ waterfall[interface_page][waterfall_head[interface_page]++] = rssi_normalised;
+ if (waterfall_head[interface_page] >= WATERFALL_SIZE) waterfall_head[interface_page] = 0;
+ }
- waterfall[interface_page][waterfall_head[interface_page]++] = rssi_normalised;
- if (waterfall_head[interface_page] >= WATERFALL_SIZE) waterfall_head[interface_page] = 0;
-
- #if DISPLAY == OLED
- stat_area.fillRect(px,py,WF_PIXEL_WIDTH, WATERFALL_SIZE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.fillRect(px,py,WF_PIXEL_WIDTH, WATERFALL_SIZE, GxEPD_BLACK);
- #endif
+ stat_area.fillRect(px,py,WF_PIXEL_WIDTH, WATERFALL_SIZE, DISPLAY_BLACK);
for (int i = 0; i < WATERFALL_SIZE; i++){
int wi = (waterfall_head[interface_page]+i)%WATERFALL_SIZE;
int ws = waterfall[interface_page][wi];
if (ws > 0) {
- #if DISPLAY == OLED
- stat_area.drawLine(px, py+i, px+ws-1, py+i, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawLine(px, py+i, px+ws-1, py+i, GxEPD_WHITE);
- #endif
+ stat_area.drawLine(px, py+i, px+ws-1, py+i, DISPLAY_WHITE);
+ } else if (ws == -1) {
+ uint8_t o = i%2;
+ for (uint8_t ti = 0; ti < WF_PIXEL_WIDTH/2; ti++) {
+ stat_area.drawPixel(px+ti*2+o, py+i, DISPLAY_WHITE);
+ }
}
}
}
@@ -670,10 +792,10 @@ void draw_waterfall(int px, int py) {
void draw_stat_area() {
if (device_init_done) {
if (!stat_area_initialised) {
- #if DISPLAY == OLED
- stat_area.drawBitmap(0, 0, bm_frame, 64, 64, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- stat_area.drawBitmap(0, 0, bm_frame, stat_area.width(), stat_area.height(), GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ stat_area.drawBitmap(0, 0, bm_frame, stat_area.width(), stat_area.height(), DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ stat_area.drawBitmap(0, 0, bm_frame, 64, 64, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
stat_area_initialised = true;
}
@@ -713,17 +835,7 @@ void draw_stat_area() {
last_interface_page_flip = millis();
}
- #if DISPLAY == OLED
- draw_cable_icon(3, 8);
- draw_bt_icon(3, 30);
- draw_lora_icon(interface_obj[0], 45, 8);
-
- // todo, expand support to show more than two interfaces on screen
- if (INTERFACE_COUNT > 1) {
- draw_lora_icon(interface_obj[1], 45, 30);
- }
- draw_battery_bars(4, 58);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ #if DISP_H == 122
draw_cable_icon(6, 18);
draw_bt_icon(6, 60);
draw_lora_icon(interface_obj[0], 86, 18);
@@ -733,6 +845,16 @@ void draw_stat_area() {
draw_lora_icon(interface_obj[1], 86, 60);
}
draw_battery_bars(8, 113);
+ #else
+ draw_cable_icon(3, 8);
+ draw_bt_icon(3, 30);
+ draw_lora_icon(interface_obj[0], 45, 8);
+
+ // todo, expand support to show more than two interfaces on screen
+ if (INTERFACE_COUNT > 1) {
+ draw_lora_icon(interface_obj[1], 45, 30);
+ }
+ draw_battery_bars(4, 58);
#endif
radio_online = false;
for (int i = 0; i < INTERFACE_COUNT; i++) {
@@ -742,14 +864,14 @@ void draw_stat_area() {
}
}
if (radio_online) {
- #if DISPLAY == OLED
- draw_quality_bars(28, 56);
- draw_signal_bars(44, 56);
- draw_waterfall(27, 4);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ #if DISP_H == 122
draw_quality_bars(53, 109);
draw_signal_bars(83, 109);
draw_waterfall(50, 8);
+ #else
+ draw_quality_bars(28, 56);
+ draw_signal_bars(44, 56);
+ draw_waterfall(27, 4);
#endif
}
}
@@ -759,40 +881,19 @@ void update_stat_area() {
if (eeprom_ok && !firmware_update_mode && !console_active) {
draw_stat_area();
if (disp_mode == DISP_MODE_PORTRAIT) {
- #if DISPLAY == OLED
- display.drawBitmap(p_as_x, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawBitmap(p_as_x, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), GxEPD_WHITE, GxEPD_BLACK);
- #endif
+ display.drawBitmap(p_as_x, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), DISPLAY_WHITE, DISPLAY_BLACK);
} else if (disp_mode == DISP_MODE_LANDSCAPE) {
- #if DISPLAY == OLED
- display.drawBitmap(p_as_x+2, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), SSD1306_WHITE, SSD1306_BLACK);
- if (device_init_done && !disp_ext_fb) display.drawLine(p_as_x, 0, p_as_x, 64, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawBitmap(p_as_x+2, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), GxEPD_WHITE, GxEPD_BLACK);
- if (device_init_done && !disp_ext_fb) display.drawLine(p_as_x, 0, p_as_x, DISP_W/2, GxEPD_WHITE);
- #endif
+ display.drawBitmap(p_as_x+2, p_as_y, stat_area.getBuffer(), stat_area.width(), stat_area.height(), DISPLAY_WHITE, DISPLAY_BLACK);
+ if (device_init_done && !disp_ext_fb) display.drawLine(p_as_x, 0, p_as_x, DISP_W/2, DISPLAY_WHITE);
}
} else {
if (firmware_update_mode) {
- #if DISPLAY == OLED
- display.drawBitmap(p_as_x, p_as_y, bm_updating, stat_area.width(), stat_area.height(), SSD1306_BLACK, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawBitmap(p_as_x, p_as_y, bm_updating, stat_area.width(), stat_area.height(), GxEPD_BLACK, GxEPD_WHITE);
- #endif
+ display.drawBitmap(p_as_x, p_as_y, bm_updating, stat_area.width(), stat_area.height(), DISPLAY_BLACK, DISPLAY_WHITE);
} else if (console_active && device_init_done) {
- #if DISPLAY == OLED
- display.drawBitmap(p_as_x, p_as_y, bm_console, stat_area.width(), stat_area.height(), SSD1306_BLACK, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawBitmap(p_as_x, p_as_y, bm_console, stat_area.width(), stat_area.height(), GxEPD_BLACK, GxEPD_WHITE);
- #endif
+ display.drawBitmap(p_as_x, p_as_y, bm_console, stat_area.width(), stat_area.height(), DISPLAY_BLACK, DISPLAY_WHITE);
if (disp_mode == DISP_MODE_LANDSCAPE) {
- #if DISPLAY == OLED
- display.drawLine(p_as_x, 0, p_as_x, 64, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawLine(p_as_x, 0, p_as_x, DISP_W/2, GxEPD_WHITE);
- #endif
+ display.drawLine(p_as_x, 0, p_as_x, DISP_W/2, DISPLAY_WHITE);
}
}
}
@@ -803,82 +904,22 @@ void draw_disp_area() {
uint8_t p_by = 37;
if (disp_mode == DISP_MODE_LANDSCAPE || firmware_update_mode) {
p_by = 18;
- #if DISPLAY == OLED
- disp_area.fillRect(0, 0, disp_area.width(), disp_area.height(), SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.fillRect(0, 0, disp_area.width(), disp_area.height(), GxEPD_BLACK);
- #endif
+ disp_area.fillRect(0, 0, disp_area.width(), disp_area.height(), DISPLAY_BLACK);
}
- #if DISPLAY == OLED
- if (!device_init_done) disp_area.drawBitmap(0, p_by, bm_boot, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- if (firmware_update_mode) disp_area.drawBitmap(0, p_by, bm_fw_update, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- if (!device_init_done) disp_area.drawBitmap(0, p_by, bm_boot, disp_area.width(), 54, GxEPD_WHITE);
- if (firmware_update_mode) disp_area.drawBitmap(0, p_by, bm_fw_update, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ if (!device_init_done) disp_area.drawBitmap(0, p_by, bm_boot, disp_area.width(), 54, DISPLAY_WHITE);
+ if (firmware_update_mode) disp_area.drawBitmap(0, p_by, bm_fw_update, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ if (!device_init_done) disp_area.drawBitmap(0, p_by, bm_boot, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
+ if (firmware_update_mode) disp_area.drawBitmap(0, p_by, bm_fw_update, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
if (!disp_ext_fb or bt_ssp_pin != 0) {
if (radio_online && display_diagnostics) {
- #if DISPLAY == OLED
+ #if DISP_H == 122
selected_radio = interface_obj[online_interface_list[interface_page]];
- disp_area.fillRect(0,8,disp_area.width(),37, SSD1306_BLACK); disp_area.fillRect(0,37,disp_area.width(),27, SSD1306_WHITE);
- disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(SSD1306_WHITE);
-
- disp_area.setCursor(2, 13);
- disp_area.print("On");
- disp_area.setCursor(14, 13);
- disp_area.print("@");
- disp_area.setCursor(21, 13);
- disp_area.printf("%.1fKbps", (float)(selected_radio->getBitrate())/1000.0);
-
- disp_area.setCursor(2, 23-1);
- disp_area.print("Airtime:");
-
- disp_area.setCursor(11, 33-1);
- if (selected_radio->getTotalChannelUtil() < 0.099) {
- disp_area.printf("%.1f%%", selected_radio->getAirtime()*100.0);
- } else {
- disp_area.printf("%.0f%%", selected_radio->getAirtime()*100.0);
- }
-
- disp_area.drawBitmap(2, 26-1, bm_hg_low, 5, 9, SSD1306_WHITE, SSD1306_BLACK);
-
- disp_area.setCursor(32+11, 33-1);
-
- if (selected_radio->getLongtermChannelUtil() < 0.099) {
- disp_area.printf("%.1f%%", selected_radio->getLongtermAirtime()*100.0);
- } else {
- disp_area.printf("%.0f%%", selected_radio->getLongtermAirtime()*100.0);
- }
- disp_area.drawBitmap(32+2, 26-1, bm_hg_high, 5, 9, SSD1306_WHITE, SSD1306_BLACK);
-
- disp_area.setTextColor(SSD1306_BLACK);
-
- disp_area.setCursor(2, 46);
- disp_area.print("Channel");
- disp_area.setCursor(38, 46);
- disp_area.print("Load:");
-
- disp_area.setCursor(11, 57);
- if (selected_radio->getTotalChannelUtil() < 0.099) {
- disp_area.printf("%.1f%%", selected_radio->getTotalChannelUtil()*100.0);
- } else {
- disp_area.printf("%.0f%%", selected_radio->getTotalChannelUtil()*100.0);
- }
- disp_area.drawBitmap(2, 50, bm_hg_low, 5, 9, SSD1306_BLACK, SSD1306_WHITE);
-
- disp_area.setCursor(32+11, 57);
- if (selected_radio->getLongtermChannelUtil() < 0.099) {
- disp_area.printf("%.1f%%", selected_radio->getLongtermChannelUtil()*100.0);
- } else {
- disp_area.printf("%.0f%%", selected_radio->getLongtermChannelUtil()*100.0);
- }
- disp_area.drawBitmap(32+2, 50, bm_hg_high, 5, 9, SSD1306_BLACK, SSD1306_WHITE);
-
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- selected_radio = interface_obj[online_interface_list[interface_page]];
- disp_area.fillRect(0,12,disp_area.width(),57, GxEPD_BLACK); disp_area.fillRect(0,69,disp_area.width(),56, GxEPD_WHITE);
- disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(GxEPD_WHITE);
+ disp_area.fillRect(0,12,disp_area.width(),57, DISPLAY_BLACK); disp_area.fillRect(0,69,disp_area.width(),56, DISPLAY_WHITE);
+ disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(DISPLAY_WHITE);
disp_area.setTextSize(2); // scale text 2x
disp_area.setCursor(2, 22);
@@ -898,7 +939,7 @@ void draw_disp_area() {
disp_area.printf("%.0f%%", selected_radio->getAirtime()*100.0);
}
- disp_area.drawBitmap(2, 41, bm_hg_low, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
+ disp_area.drawBitmap(2, 41, bm_hg_low, 10, 18, DISPLAY_WHITE, DISPLAY_BLACK);
disp_area.setCursor(64+17, 53);
if (selected_radio->getLongtermChannelUtil() < 0.099) {
@@ -906,9 +947,9 @@ void draw_disp_area() {
} else {
disp_area.printf("%.0f%%", selected_radio->getLongtermAirtime()*100.0);
}
- disp_area.drawBitmap(64, 41, bm_hg_high, 10, 18, GxEPD_WHITE, GxEPD_BLACK);
+ disp_area.drawBitmap(64, 41, bm_hg_high, 10, 18, DISPLAY_WHITE, DISPLAY_BLACK);
- disp_area.setTextColor(GxEPD_BLACK);
+ disp_area.setTextColor(DISPLAY_BLACK);
disp_area.setCursor(2, 88);
disp_area.print("Channel");
@@ -921,7 +962,7 @@ void draw_disp_area() {
} else {
disp_area.printf("%.0f%%", selected_radio->getTotalChannelUtil()*100.0);
}
- disp_area.drawBitmap(2, 98, bm_hg_low, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
+ disp_area.drawBitmap(2, 98, bm_hg_low, 10, 18, DISPLAY_BLACK, DISPLAY_WHITE);
disp_area.setCursor(64+17, 110);
if (selected_radio->getLongtermChannelUtil() < 0.099) {
@@ -929,44 +970,99 @@ void draw_disp_area() {
} else {
disp_area.printf("%.0f%%", selected_radio->getLongtermChannelUtil()*100.0);
}
- disp_area.drawBitmap(64, 98, bm_hg_high, 10, 18, GxEPD_BLACK, GxEPD_WHITE);
+ disp_area.drawBitmap(64, 98, bm_hg_high, 10, 18, DISPLAY_BLACK, DISPLAY_WHITE);
+ #else
+ selected_radio = interface_obj[online_interface_list[interface_page]];
+ disp_area.fillRect(0,8,disp_area.width(),37, DISPLAY_BLACK); disp_area.fillRect(0,37,disp_area.width(),27, DISPLAY_WHITE);
+ disp_area.setFont(SMALL_FONT); disp_area.setTextWrap(false); disp_area.setTextColor(DISPLAY_WHITE);
+
+ disp_area.setCursor(2, 13);
+ disp_area.print("On");
+ disp_area.setCursor(14, 13);
+ disp_area.print("@");
+ disp_area.setCursor(21, 13);
+ disp_area.printf("%.1fKbps", (float)(selected_radio->getBitrate())/1000.0);
+
+ disp_area.setCursor(2, 23-1);
+ disp_area.print("Airtime:");
+
+ disp_area.setCursor(11, 33-1);
+ if (selected_radio->getTotalChannelUtil() < 0.099) {
+ disp_area.printf("%.1f%%", selected_radio->getAirtime()*100.0);
+ } else {
+ disp_area.printf("%.0f%%", selected_radio->getAirtime()*100.0);
+ }
+
+ disp_area.drawBitmap(2, 26-1, bm_hg_low, 5, 9, DISPLAY_WHITE, DISPLAY_BLACK);
+
+ disp_area.setCursor(32+11, 33-1);
+
+ if (selected_radio->getLongtermChannelUtil() < 0.099) {
+ disp_area.printf("%.1f%%", selected_radio->getLongtermAirtime()*100.0);
+ } else {
+ disp_area.printf("%.0f%%", selected_radio->getLongtermAirtime()*100.0);
+ }
+ disp_area.drawBitmap(32+2, 26-1, bm_hg_high, 5, 9, DISPLAY_WHITE, DISPLAY_BLACK);
+
+ disp_area.setTextColor(DISPLAY_BLACK);
+
+ disp_area.setCursor(2, 46);
+ disp_area.print("Channel");
+ disp_area.setCursor(38, 46);
+ disp_area.print("Load:");
+
+ disp_area.setCursor(11, 57);
+ if (selected_radio->getTotalChannelUtil() < 0.099) {
+ disp_area.printf("%.1f%%", selected_radio->getTotalChannelUtil()*100.0);
+ } else {
+ disp_area.printf("%.0f%%", selected_radio->getTotalChannelUtil()*100.0);
+ }
+ disp_area.drawBitmap(2, 50, bm_hg_low, 5, 9, DISPLAY_BLACK, DISPLAY_WHITE);
+
+ disp_area.setCursor(32+11, 57);
+ if (selected_radio->getLongtermChannelUtil() < 0.099) {
+ disp_area.printf("%.1f%%", selected_radio->getLongtermChannelUtil()*100.0);
+ } else {
+ disp_area.printf("%.0f%%", selected_radio->getLongtermChannelUtil()*100.0);
+ }
+ disp_area.drawBitmap(32+2, 50, bm_hg_high, 5, 9, DISPLAY_BLACK, DISPLAY_WHITE);
#endif
} else {
if (device_signatures_ok()) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 71, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 71, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 0, bm_def_lc, disp_area.width(), 37, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 37, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 71, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 71, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 0, bm_def, disp_area.width(), 37, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
if (!hw_ready || !device_firmware_ok()) {
if (!device_firmware_ok()) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_fw_corrupt, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_fw_corrupt, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_fw_corrupt, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_fw_corrupt, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
if (!modems_installed) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_no_radio, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_no_radio, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_no_radio, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_no_radio, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_hwfail, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_hwfail, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_hwfail, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_hwfail, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
}
@@ -974,19 +1070,19 @@ void draw_disp_area() {
char *pin_str = (char*)malloc(DISP_PIN_SIZE+1);
sprintf(pin_str, "%06d", bt_ssp_pin);
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_pairing, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_pairing, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_pairing, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_pairing, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
for (int i = 0; i < DISP_PIN_SIZE; i++) {
uint8_t numeric = pin_str[i]-48;
- #if DISPLAY == OLED
- uint8_t offset = numeric*5;
- disp_area.drawBitmap(7+9*i, 37+16, bm_n_uh+offset, 8, 5, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ #if DISP_H == 122
uint8_t offset = numeric*20;
- disp_area.drawBitmap(14+17*i, 71+32, bm_n_uh+offset, 10, 10, GxEPD_WHITE, GxEPD_BLACK);
+ disp_area.drawBitmap(14+17*i, 71+32, bm_n_uh+offset, 10, 10, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ uint8_t offset = numeric*5;
+ disp_area.drawBitmap(7+9*i, 37+16, bm_n_uh+offset, 8, 5, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
free(pin_str);
@@ -999,155 +1095,147 @@ void draw_disp_area() {
if (radio_online) {
if (!display_diagnostics) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_online, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_online, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 37, bm_online, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 71, bm_online, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
} else {
if (disp_page == 0) {
if (true || device_signatures_ok()) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_checks, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_checks, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_checks, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_checks, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_nfr, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_nfr, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_nfr, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_nfr, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
} else if (disp_page == 1) {
if (!console_active) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_hwok, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_hwok, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_hwok, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_hwok, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
} else {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_console_active, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_console_active, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_console_active, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_console_active, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
} else if (disp_page == 2) {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 37, bm_version, disp_area.width(), 27, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 71, bm_version, disp_area.width(), 54, GxEPD_WHITE, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawBitmap(0, 71, bm_version, disp_area.width(), 54, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(0, 37, bm_version, disp_area.width(), 27, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
char *v_str = (char*)malloc(3+1);
sprintf(v_str, "%01d%02d", MAJ_VERS, MIN_VERS);
for (int i = 0; i < 3; i++) {
- #if DISPLAY == OLED
- uint8_t dxp = 20;
- uint8_t numeric = v_str[i]-48; uint8_t bm_offset = numeric*5;
- if (i == 2) dxp += 9*2+4;
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ #if DISP_H == 122
uint8_t dxp = 43;
uint8_t numeric = v_str[i]-48; uint8_t bm_offset = numeric*20;
if (i == 2) dxp += 9*2+6;
+ #else
+ uint8_t dxp = DISP_H * 0.32;
+ uint8_t numeric = v_str[i]-48; uint8_t bm_offset = numeric*20;
+ if (i == 2) dxp += 9*2+6;
#endif
if (i == 1) dxp += 9*1+4;
- #if DISPLAY == OLED
- disp_area.drawBitmap(dxp, 37+16, bm_n_uh+bm_offset, 8, 5, SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ #if DISP_H == 122
// add gap manually rather than oversizing bitmap, as the gfx lib fills in the extra space with black
- disp_area.drawBitmap(dxp, 71+32, bm_n_uh+bm_offset, 10, 10, GxEPD_WHITE, GxEPD_BLACK);
+ disp_area.drawBitmap(dxp, 71+32, bm_n_uh+bm_offset, 10, 10, DISPLAY_WHITE, DISPLAY_BLACK);
+ #else
+ disp_area.drawBitmap(dxp, 37+16, bm_n_uh+bm_offset, 8, 5, DISPLAY_WHITE, DISPLAY_BLACK);
#endif
}
free(v_str);
- #if DISPLAY == OLED
- disp_area.drawLine(27, 37+19, 28, 37+19, SSD1306_BLACK);
- disp_area.drawLine(27, 37+19, 28, 37+19, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawLine(27, 37+20, 28, 37+20, GxEPD_BLACK);
- disp_area.drawLine(27, 37+20, 28, 37+20, GxEPD_BLACK);
+ #if DISP_H == 122
+ disp_area.drawLine(27, 37+20, 28, 37+20, DISPLAY_BLACK);
+ disp_area.drawLine(27, 37+20, 28, 37+20, DISPLAY_BLACK);
+ #else
+ disp_area.drawLine(27, 37+19, 28, 37+19, DISPLAY_BLACK);
+ disp_area.drawLine(27, 37+19, 28, 37+19, DISPLAY_BLACK);
#endif
}
}
}
} else {
- #if DISPLAY == OLED
- disp_area.drawBitmap(0, 0, fb, disp_area.width(), disp_area.height(), SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- disp_area.drawBitmap(0, 0, fb, disp_area.width(), disp_area.height(), GxEPD_WHITE, GxEPD_BLACK);
- #endif
+ disp_area.drawBitmap(0, 0, fb, disp_area.width(), disp_area.height(), DISPLAY_WHITE, DISPLAY_BLACK);
}
}
}
void update_disp_area() {
draw_disp_area();
- #if DISPLAY == OLED
- display.drawBitmap(p_ad_x, p_ad_y, disp_area.getBuffer(), disp_area.width(), disp_area.height(), SSD1306_WHITE, SSD1306_BLACK);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawBitmap(p_ad_x, p_ad_y, disp_area.getBuffer(), disp_area.width(), disp_area.height(), GxEPD_WHITE, GxEPD_BLACK);
- #endif
+ display.drawBitmap(p_ad_x, p_ad_y, disp_area.getBuffer(), disp_area.width(), disp_area.height(), DISPLAY_WHITE, DISPLAY_BLACK);
if (disp_mode == DISP_MODE_LANDSCAPE) {
if (device_init_done && !firmware_update_mode && !disp_ext_fb) {
- #if DISPLAY == OLED
- display.drawLine(0, 0, 0, 63, SSD1306_WHITE);
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
- display.drawLine(0, 0, 0, 63, GxEPD_WHITE);
+ #if DISP_H == 122
+ display.drawLine(0, 0, 0, 63, DISPLAY_WHITE);
+ #else
+ display.drawLine(0, 0, 0, DISP_H / 2, DISPLAY_WHITE);
#endif
}
}
}
+void do_screensaver(uint32_t current){
+ #if DISPLAY == OLED
+ // Invert display to protect against OLED screen burn in
+ //TODO: Make this a option configurable through rnodeconf
+ //TODO: Implement other ways to do the screensaver, such as scrolling the screen.
+ if (screensaver_enabled) {
+ if (current-last_screensaver >= SCREENSAVER_INTERVAL+SCREENSAVER_TIME) {
+ display.invertDisplay(0);
+ last_screensaver = current;
+ screensaver_enabled = false;
+ }
+ }
+ else if (current-last_screensaver >= SCREENSAVER_INTERVAL) {
+ display.invertDisplay(1);
+ screensaver_enabled = true;
+ }
+ #endif
+}
+
void update_display(bool blank = false) {
- if (blank) {
- #if DISPLAY == OLED
+ #if DISPLAY == OLED
if (display_contrast != display_intensity) {
display_contrast = display_intensity;
set_contrast(&display, display_contrast);
}
display.clearDisplay();
- #endif
+ #endif
+ if (blank) {
display.display();
} else {
if (millis()-last_disp_update >= disp_update_interval) {
- #if DISPLAY == OLED
- if (display_contrast != display_intensity) {
- display_contrast = display_intensity;
- set_contrast(&display, display_contrast);
- }
- display.clearDisplay();
- update_stat_area();
- update_disp_area();
- display.display();
-
uint32_t current = millis();
- // Invert display to protect against OLED screen burn in
- if (screensaver_enabled) {
- if (current-last_screensaver >= SCREENSAVER_INTERVAL+SCREENSAVER_TIME) {
- display.invertDisplay(0);
- last_screensaver = current;
- screensaver_enabled = false;
- }
- }
- else if (current-last_screensaver >= SCREENSAVER_INTERVAL) {
- display.invertDisplay(1);
- screensaver_enabled = true;
- }
- #elif DISP_H == 122 && (DISPLAY == EINK_BW || DISPLAY == EINK_3C)
+ do_screensaver(current);
+ #if DISPLAY == EINK_BW || DISPLAY == EINK_3C
display.setFullWindow();
- display.fillScreen(GxEPD_WHITE);
+ display.fillScreen(DISPLAY_WHITE);
+ #endif
update_stat_area();
update_disp_area();
-
- uint32_t current = millis();
+ #if DISPLAY == OLED
+ display.display();
+ #else
if (current-last_epd_refresh >= REFRESH_PERIOD) {
- // Perform a full refresh after the correct time has elapsed
- display.display(false);
- last_epd_refresh = current;
+ // Perform a full refresh after the correct time has elapsed
+ display.display(false);
+ last_epd_refresh = current;
} else {
- // Only perform a partial refresh
- display.display(true);
+ // Only perform a partial refresh
+ display.display(true);
}
#endif
last_disp_update = current;
diff --git a/Framing.h b/Framing.h
index d696a8a..77bda39 100644
--- a/Framing.h
+++ b/Framing.h
@@ -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;
diff --git a/Graphics.h b/Graphics.h
index 049beb0..faf5f2f 100644
--- a/Graphics.h
+++ b/Graphics.h
@@ -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 .
-#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
diff --git a/Graphics/Bitmaps/banner_boot.bmp b/Graphics/Bitmaps/banner_boot.bmp
new file mode 100644
index 0000000..0004681
Binary files /dev/null and b/Graphics/Bitmaps/banner_boot.bmp differ
diff --git a/Graphics/Bitmaps/banner_checks.bmp b/Graphics/Bitmaps/banner_checks.bmp
new file mode 100644
index 0000000..b38c4ab
Binary files /dev/null and b/Graphics/Bitmaps/banner_checks.bmp differ
diff --git a/Graphics/Bitmaps/banner_console.bmp b/Graphics/Bitmaps/banner_console.bmp
new file mode 100644
index 0000000..5fadff2
Binary files /dev/null and b/Graphics/Bitmaps/banner_console.bmp differ
diff --git a/Graphics/Bitmaps/banner_fw_corrupt.bmp b/Graphics/Bitmaps/banner_fw_corrupt.bmp
new file mode 100644
index 0000000..a576097
Binary files /dev/null and b/Graphics/Bitmaps/banner_fw_corrupt.bmp differ
diff --git a/Graphics/Bitmaps/banner_fw_update.bmp b/Graphics/Bitmaps/banner_fw_update.bmp
new file mode 100644
index 0000000..f975a65
Binary files /dev/null and b/Graphics/Bitmaps/banner_fw_update.bmp differ
diff --git a/Graphics/Bitmaps/banner_hwfail.bmp b/Graphics/Bitmaps/banner_hwfail.bmp
new file mode 100644
index 0000000..e79217b
Binary files /dev/null and b/Graphics/Bitmaps/banner_hwfail.bmp differ
diff --git a/Graphics/Bitmaps/banner_hwok.bmp b/Graphics/Bitmaps/banner_hwok.bmp
new file mode 100644
index 0000000..4d546ba
Binary files /dev/null and b/Graphics/Bitmaps/banner_hwok.bmp differ
diff --git a/Graphics/Bitmaps/banner_nfr.bmp b/Graphics/Bitmaps/banner_nfr.bmp
new file mode 100644
index 0000000..e89c41f
Binary files /dev/null and b/Graphics/Bitmaps/banner_nfr.bmp differ
diff --git a/Graphics/Bitmaps/banner_no_radio.bmp b/Graphics/Bitmaps/banner_no_radio.bmp
new file mode 100644
index 0000000..e20ca74
Binary files /dev/null and b/Graphics/Bitmaps/banner_no_radio.bmp differ
diff --git a/Graphics/Bitmaps/banner_online.bmp b/Graphics/Bitmaps/banner_online.bmp
new file mode 100644
index 0000000..7906578
Binary files /dev/null and b/Graphics/Bitmaps/banner_online.bmp differ
diff --git a/Graphics/Bitmaps/banner_pairing.bmp b/Graphics/Bitmaps/banner_pairing.bmp
new file mode 100644
index 0000000..5dfd4bb
Binary files /dev/null and b/Graphics/Bitmaps/banner_pairing.bmp differ
diff --git a/Graphics/Bitmaps/banner_version.bmp b/Graphics/Bitmaps/banner_version.bmp
new file mode 100644
index 0000000..da02744
Binary files /dev/null and b/Graphics/Bitmaps/banner_version.bmp differ
diff --git a/Graphics/Bitmaps/bm_pairing.bmp b/Graphics/Bitmaps/bm_pairing.bmp
new file mode 100644
index 0000000..c4e5fa5
Binary files /dev/null and b/Graphics/Bitmaps/bm_pairing.bmp differ
diff --git a/Graphics/Bitmaps/bm_update.bmp b/Graphics/Bitmaps/bm_update.bmp
new file mode 100644
index 0000000..db3a180
Binary files /dev/null and b/Graphics/Bitmaps/bm_update.bmp differ
diff --git a/Graphics/Bitmaps/bt_icons.bmp b/Graphics/Bitmaps/bt_icons.bmp
new file mode 100644
index 0000000..5da2aa9
Binary files /dev/null and b/Graphics/Bitmaps/bt_icons.bmp differ
diff --git a/Graphics/Bitmaps/cable_icons.bmp b/Graphics/Bitmaps/cable_icons.bmp
new file mode 100644
index 0000000..3521717
Binary files /dev/null and b/Graphics/Bitmaps/cable_icons.bmp differ
diff --git a/Graphics/Bitmaps/console_icon.bmp b/Graphics/Bitmaps/console_icon.bmp
new file mode 100644
index 0000000..fd3a015
Binary files /dev/null and b/Graphics/Bitmaps/console_icon.bmp differ
diff --git a/Graphics/Bitmaps/default_fb.bmp b/Graphics/Bitmaps/default_fb.bmp
new file mode 100644
index 0000000..01e472c
Binary files /dev/null and b/Graphics/Bitmaps/default_fb.bmp differ
diff --git a/Graphics/Bitmaps/default_fb_alt.bmp b/Graphics/Bitmaps/default_fb_alt.bmp
new file mode 100644
index 0000000..fb9d03d
Binary files /dev/null and b/Graphics/Bitmaps/default_fb_alt.bmp differ
diff --git a/Graphics/Bitmaps/default_fb_lc.bmp b/Graphics/Bitmaps/default_fb_lc.bmp
new file mode 100644
index 0000000..f6d4442
Binary files /dev/null and b/Graphics/Bitmaps/default_fb_lc.bmp differ
diff --git a/Graphics/Bitmaps/frame.bmp b/Graphics/Bitmaps/frame.bmp
new file mode 100644
index 0000000..d9d7ffc
Binary files /dev/null and b/Graphics/Bitmaps/frame.bmp differ
diff --git a/Graphics/Bitmaps/hourglass_high.png b/Graphics/Bitmaps/hourglass_high.png
new file mode 100644
index 0000000..a149af7
Binary files /dev/null and b/Graphics/Bitmaps/hourglass_high.png differ
diff --git a/Graphics/Bitmaps/hourglass_low.png b/Graphics/Bitmaps/hourglass_low.png
new file mode 100644
index 0000000..ec199ec
Binary files /dev/null and b/Graphics/Bitmaps/hourglass_low.png differ
diff --git a/Graphics/Bitmaps/numbers_upheaval.bmp b/Graphics/Bitmaps/numbers_upheaval.bmp
new file mode 100644
index 0000000..d50e1fb
Binary files /dev/null and b/Graphics/Bitmaps/numbers_upheaval.bmp differ
diff --git a/Graphics/Bitmaps/plug.bmp b/Graphics/Bitmaps/plug.bmp
new file mode 100644
index 0000000..1258b5a
Binary files /dev/null and b/Graphics/Bitmaps/plug.bmp differ
diff --git a/Graphics/Bitmaps/rf_icons.bmp b/Graphics/Bitmaps/rf_icons.bmp
new file mode 100644
index 0000000..7913a96
Binary files /dev/null and b/Graphics/Bitmaps/rf_icons.bmp differ
diff --git a/Graphics/Bitmaps/sideband_fb.bmp b/Graphics/Bitmaps/sideband_fb.bmp
new file mode 100644
index 0000000..24f12c5
Binary files /dev/null and b/Graphics/Bitmaps/sideband_fb.bmp differ
diff --git a/Graphics/Design/Bluetooth.kra b/Graphics/Design/Bluetooth.kra
new file mode 100644
index 0000000..241f24e
Binary files /dev/null and b/Graphics/Design/Bluetooth.kra differ
diff --git a/Graphics/Design/Text.xcf b/Graphics/Design/Text.xcf
new file mode 100644
index 0000000..6686b09
Binary files /dev/null and b/Graphics/Design/Text.xcf differ
diff --git a/Graphics/Design/banners.kra b/Graphics/Design/banners.kra
new file mode 100644
index 0000000..230d6ab
Binary files /dev/null and b/Graphics/Design/banners.kra differ
diff --git a/Graphics/Design/cable_icons.kra b/Graphics/Design/cable_icons.kra
new file mode 100644
index 0000000..a7f45de
Binary files /dev/null and b/Graphics/Design/cable_icons.kra differ
diff --git a/Graphics/Design/console_icon.kra b/Graphics/Design/console_icon.kra
new file mode 100644
index 0000000..bdbf69f
Binary files /dev/null and b/Graphics/Design/console_icon.kra differ
diff --git a/Graphics/Design/cs.kra b/Graphics/Design/cs.kra
new file mode 100644
index 0000000..e105cda
Binary files /dev/null and b/Graphics/Design/cs.kra differ
diff --git a/Graphics/Design/default_fb.kra b/Graphics/Design/default_fb.kra
new file mode 100644
index 0000000..ef8d030
Binary files /dev/null and b/Graphics/Design/default_fb.kra differ
diff --git a/Graphics/Design/default_fb_alt.kra b/Graphics/Design/default_fb_alt.kra
new file mode 100644
index 0000000..4053839
Binary files /dev/null and b/Graphics/Design/default_fb_alt.kra differ
diff --git a/Graphics/Design/firware_update_icon.kra b/Graphics/Design/firware_update_icon.kra
new file mode 100644
index 0000000..b5ac329
Binary files /dev/null and b/Graphics/Design/firware_update_icon.kra differ
diff --git a/Graphics/Design/frame.kra b/Graphics/Design/frame.kra
new file mode 100644
index 0000000..5135fce
Binary files /dev/null and b/Graphics/Design/frame.kra differ
diff --git a/Graphics/Design/icons.kra b/Graphics/Design/icons.kra
new file mode 100644
index 0000000..6626014
Binary files /dev/null and b/Graphics/Design/icons.kra differ
diff --git a/Graphics/Design/numbers_silkscreen.kra b/Graphics/Design/numbers_silkscreen.kra
new file mode 100644
index 0000000..f6910f3
Binary files /dev/null and b/Graphics/Design/numbers_silkscreen.kra differ
diff --git a/Graphics/Design/numbers_upheaval.kra b/Graphics/Design/numbers_upheaval.kra
new file mode 100644
index 0000000..2a6ee1e
Binary files /dev/null and b/Graphics/Design/numbers_upheaval.kra differ
diff --git a/Graphics/Design/plug.kra b/Graphics/Design/plug.kra
new file mode 100644
index 0000000..777be0a
Binary files /dev/null and b/Graphics/Design/plug.kra differ
diff --git a/Graphics/Design/r_icon.kra b/Graphics/Design/r_icon.kra
new file mode 100644
index 0000000..de91694
Binary files /dev/null and b/Graphics/Design/r_icon.kra differ
diff --git a/Graphics/Design/rf_icons.kra b/Graphics/Design/rf_icons.kra
new file mode 100644
index 0000000..3157b86
Binary files /dev/null and b/Graphics/Design/rf_icons.kra differ
diff --git a/Graphics/Design/sideband_fb.kra b/Graphics/Design/sideband_fb.kra
new file mode 100644
index 0000000..57c73c6
Binary files /dev/null and b/Graphics/Design/sideband_fb.kra differ
diff --git a/Makefile b/Makefile
index a57931d..8994971 100644
--- a/Makefile
+++ b/Makefile
@@ -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,179 +13,214 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-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:
make -C Console clean site
-spiffs: console-site spiffs-image
+spiffs: console-site spiffs-image
spiffs-image:
python3 Release/esptool/spiffsgen.py 1966080 ./Console/build Release/console_image.bin
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
diff --git a/Power.h b/Power.h
index 2fa7ac7..e6d7ed6 100644
--- a/Power.h
+++ b/Power.h
@@ -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 .
+
+#if BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_TBEAM_S_V1
#include
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
@@ -446,6 +522,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;
#endif
diff --git a/README.md b/README.md
index e5016ba..6d26977 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/ROM.h b/ROM.h
index 4ecd02a..9ab3a70 100644
--- a/ROM.h
+++ b/ROM.h
@@ -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 .
#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 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 INFO_LOCK_BYTE 0x73
- #define CONF_OK_BYTE 0x73
- #define BT_ENABLE_BYTE 0x73
-
- #define EEPROM_RESERVED 200
+ #define EEPROM_RESERVED 200
+ //////////////////////////////////
#endif
diff --git a/Radio.cpp b/Radio.cpp
index 58035b3..473205a 100644
--- a/Radio.cpp
+++ b/Radio.cpp
@@ -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 {
diff --git a/Radio.hpp b/Radio.hpp
index 8360a04..53648fc 100644
--- a/Radio.hpp
+++ b/Radio.hpp
@@ -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
diff --git a/Release/console_image.bin b/Release/console_image.bin
index ee7e5b1..8fb621b 100644
Binary files a/Release/console_image.bin and b/Release/console_image.bin differ
diff --git a/Utilities.h b/Utilities.h
index 2878e10..1a3702e 100644
--- a/Utilities.h
+++ b/Utilities.h
@@ -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) {
diff --git a/arduino-cli.yaml b/arduino-cli.yaml
index 2f836f0..833fd7b 100644
--- a/arduino-cli.yaml
+++ b/arduino-cli.yaml
@@ -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
diff --git a/esp32_btbufs.py b/esp32_btbufs.py
new file mode 100755
index 0000000..8a5b15e
--- /dev/null
+++ b/esp32_btbufs.py
@@ -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")
\ No newline at end of file
diff --git a/opencom_xl_firmware.ino b/opencom_xl_firmware.ino
index 8fa9fe6..3dae37b 100644
--- a/opencom_xl_firmware.ino
+++ b/opencom_xl_firmware.ino
@@ -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 {
diff --git a/partition_hashes b/partition_hashes
index d6b81fe..fa60868 100755
--- a/partition_hashes
+++ b/partition_hashes
@@ -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
diff --git a/release_hashes.py b/release_hashes.py
index c54a9d1..e1608d8 100644
--- a/release_hashes.py
+++ b/release_hashes.py
@@ -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
diff --git a/src/ble/BLESerial.cpp b/src/ble/BLESerial.cpp
new file mode 100644
index 0000000..94cbb2f
--- /dev/null
+++ b/src/ble/BLESerial.cpp
@@ -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 .
+
+// This class is for BLE serial functionality on ESP32 boards ONLY
+
+#include
+#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
diff --git a/src/ble/BLESerial.h b/src/ble/BLESerial.h
new file mode 100644
index 0000000..1ad2e25
--- /dev/null
+++ b/src/ble/BLESerial.h
@@ -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 .
+
+// This class is for BLE serial functionality on ESP32 boards ONLY
+
+#include "../../Boards.h"
+
+#if PLATFORM != PLATFORM_NRF52
+#if HAS_BLE
+
+#include
+
+#include
+#include
+#include
+#include
+
+template
+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_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
diff --git a/MD5.cpp b/src/misc/MD5.cpp
similarity index 100%
rename from MD5.cpp
rename to src/misc/MD5.cpp
diff --git a/MD5.h b/src/misc/MD5.h
similarity index 100%
rename from MD5.h
rename to src/misc/MD5.h