Compare commits
10 Commits
8db47d4d01
...
a57b3bc6de
| Author | SHA1 | Date | |
|---|---|---|---|
| a57b3bc6de | |||
|
|
b3b6cd4302 | ||
|
|
7e56611fe6 | ||
|
|
56c1a6b881 | ||
|
|
79cb2d49e8 | ||
|
|
d8c925769d | ||
|
|
300676e5ae | ||
|
|
d49c55a843 | ||
|
|
85d8fc7f78 | ||
|
|
949c13c7b1 |
46
Boards.h
46
Boards.h
@@ -122,6 +122,8 @@
|
|||||||
#define MODEL_FE 0xFE // Homebrew board, max 17dBm output power
|
#define MODEL_FE 0xFE // Homebrew board, max 17dBm output power
|
||||||
#define MODEL_FF 0xFF // Homebrew board, max 14dBm output power
|
#define MODEL_FF 0xFF // Homebrew board, max 14dBm output power
|
||||||
|
|
||||||
|
#define BOARD_MESHADVENTURER_S3 0xF2
|
||||||
|
|
||||||
#if defined(__AVR_ATmega1284P__)
|
#if defined(__AVR_ATmega1284P__)
|
||||||
#define PLATFORM PLATFORM_AVR
|
#define PLATFORM PLATFORM_AVR
|
||||||
#define MCU_VARIANT MCU_1284P
|
#define MCU_VARIANT MCU_1284P
|
||||||
@@ -449,6 +451,50 @@
|
|||||||
const int pin_miso = 11;
|
const int pin_miso = 11;
|
||||||
const int pin_sclk = 9;
|
const int pin_sclk = 9;
|
||||||
|
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
#define IS_ESP32S3 true
|
||||||
|
#define HAS_DISPLAY true
|
||||||
|
#define HAS_NP true
|
||||||
|
#define HAS_BLUETOOTH false
|
||||||
|
#define HAS_BLE true
|
||||||
|
#define HAS_WIFI true
|
||||||
|
#define HAS_CONSOLE true
|
||||||
|
#define HAS_EEPROM true
|
||||||
|
#define HAS_BUSY true
|
||||||
|
#define HAS_INPUT true
|
||||||
|
#define HAS_TCXO true
|
||||||
|
#define MODEM SX1262
|
||||||
|
#define DIO2_AS_RF_SWITCH false
|
||||||
|
#define HAS_RF_SWITCH_RX_TX true
|
||||||
|
#define HAS_LORA_LNA true
|
||||||
|
#define LORA_LNA_GAIN 30
|
||||||
|
#define LORA_LNA_GVT 14
|
||||||
|
#define PA_MAX_OUTPUT 22
|
||||||
|
|
||||||
|
const int pin_cs = 39;
|
||||||
|
const int pin_sclk = 38;
|
||||||
|
const int pin_miso = 40;
|
||||||
|
const int pin_mosi = 18;
|
||||||
|
const int pin_busy = 7;
|
||||||
|
const int pin_reset = 43;
|
||||||
|
const int pin_dio = 15;
|
||||||
|
const int pin_txen = 9;
|
||||||
|
const int pin_rxen = 8;
|
||||||
|
const int pin_tcxo_enable = -1;
|
||||||
|
|
||||||
|
const int pin_btn_usr1 = 4;
|
||||||
|
const int pin_np = 48;
|
||||||
|
|
||||||
|
#if HAS_NP == false
|
||||||
|
#if defined(EXTERNAL_LEDS)
|
||||||
|
const int pin_led_rx = 48;
|
||||||
|
const int pin_led_tx = 48;
|
||||||
|
#else
|
||||||
|
const int pin_led_rx = 48;
|
||||||
|
const int pin_led_tx = 48;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif BOARD_MODEL == BOARD_RNODE_NG_20
|
#elif BOARD_MODEL == BOARD_RNODE_NG_20
|
||||||
#define HAS_DISPLAY true
|
#define HAS_DISPLAY true
|
||||||
#define HAS_BLUETOOTH true
|
#define HAS_BLUETOOTH true
|
||||||
|
|||||||
75
BoundaryConfig.h
Normal file → Executable file
75
BoundaryConfig.h
Normal file → Executable file
@@ -1,7 +1,10 @@
|
|||||||
// Copyright (C) 2026, Boundary Mode Extension
|
// Copyright (C) 2026, Boundary Mode Extension
|
||||||
// Based on microReticulum_Firmware by Mark Qvist
|
// Based on microReticulum_Firmware by Mark Qvist
|
||||||
//
|
//
|
||||||
// BoundaryConfig.h — Captive-portal web configuration for Boundary Mode.
|
// BoundaryConfig.h — Captive-portal web configuration for the legacy
|
||||||
|
// "Boundary Mode" path. This should be renamed to "Transport Mode"
|
||||||
|
// together with the rest of the boundary-mode terminology. In this fork,
|
||||||
|
// transport/boundary mode is the only intended mode of operation.
|
||||||
// When triggered (first boot with no config, or button hold >5s),
|
// When triggered (first boot with no config, or button hold >5s),
|
||||||
// the device starts a WiFi AP with a web form for all settings:
|
// the device starts a WiFi AP with a web form for all settings:
|
||||||
// WiFi STA credentials, TCP backbone params, LoRa radio params,
|
// WiFi STA credentials, TCP backbone params, LoRa radio params,
|
||||||
@@ -59,6 +62,16 @@ static const char* const BW_OPTIONS_LABELS[] PROGMEM = {
|
|||||||
};
|
};
|
||||||
static const int BW_OPTIONS_COUNT = sizeof(BW_OPTIONS_HZ) / sizeof(BW_OPTIONS_HZ[0]);
|
static const int BW_OPTIONS_COUNT = sizeof(BW_OPTIONS_HZ) / sizeof(BW_OPTIONS_HZ[0]);
|
||||||
|
|
||||||
|
static uint8_t config_default_display_rotation() {
|
||||||
|
#if BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_RAK4631
|
||||||
|
return 0;
|
||||||
|
#elif BOARD_MODEL == BOARD_HELTEC32_V2 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TBEAM_S_V1
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// ─── HTML Page Generation ────────────────────────────────────────────────────
|
// ─── HTML Page Generation ────────────────────────────────────────────────────
|
||||||
|
|
||||||
static void config_send_html() {
|
static void config_send_html() {
|
||||||
@@ -87,10 +100,10 @@ static void config_send_html() {
|
|||||||
if (cur_txp == 0xFF) cur_txp = PA_MAX_OUTPUT; // Default to board max
|
if (cur_txp == 0xFF) cur_txp = PA_MAX_OUTPUT; // Default to board max
|
||||||
|
|
||||||
// Default frequency if not set
|
// Default frequency if not set
|
||||||
if (cur_freq == 0) cur_freq = 914875000; // 914.875 MHz default
|
if (cur_freq == 0) cur_freq = 868825000; // 914.875 MHz default
|
||||||
if (cur_bw == 0) cur_bw = 125000; // 125 kHz default
|
if (cur_bw == 0) cur_bw = 125000; // 125 kHz default
|
||||||
if (cur_sf == 0) cur_sf = 10; // SF10 default
|
if (cur_sf == 0) cur_sf = 10; // SF10 default
|
||||||
if (cur_cr < 5 || cur_cr > 8) cur_cr = 5; // CR 4/5 default
|
if (cur_cr < 5 || cur_cr > 8) cur_cr = 7; // CR 4/5 default
|
||||||
|
|
||||||
// Build the HTML page
|
// Build the HTML page
|
||||||
String html = F(
|
String html = F(
|
||||||
@@ -221,9 +234,9 @@ static void config_send_html() {
|
|||||||
}
|
}
|
||||||
html += F("</select>");
|
html += F("</select>");
|
||||||
|
|
||||||
// Spreading Factor — dropdown 6-12
|
// Spreading Factor — dropdown 5-12
|
||||||
html += F("<label>Spreading Factor</label><select name='sf'>");
|
html += F("<label>Spreading Factor</label><select name='sf'>");
|
||||||
for (int sf = 6; sf <= 12; sf++) {
|
for (int sf = 5; sf <= 12; sf++) {
|
||||||
html += F("<option value='");
|
html += F("<option value='");
|
||||||
html += String(sf);
|
html += String(sf);
|
||||||
html += "'";
|
html += "'";
|
||||||
@@ -299,11 +312,16 @@ static void config_send_html() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Read current blanking timeout from EEPROM (stored as minutes, 0 = never)
|
// Read current blanking timeout from EEPROM (stored as minutes, 0 = never)
|
||||||
uint8_t cur_blank = 0;
|
uint8_t cur_blank = 5;
|
||||||
if (EEPROM.read(eeprom_addr(ADDR_CONF_BSET)) == CONF_OK_BYTE) {
|
if (EEPROM.read(eeprom_addr(ADDR_CONF_BSET)) == CONF_OK_BYTE) {
|
||||||
cur_blank = EEPROM.read(eeprom_addr(ADDR_CONF_DBLK));
|
cur_blank = EEPROM.read(eeprom_addr(ADDR_CONF_DBLK));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t cur_rotation = EEPROM.read(eeprom_addr(ADDR_CONF_DROT));
|
||||||
|
if (cur_rotation > 3) {
|
||||||
|
cur_rotation = config_default_display_rotation();
|
||||||
|
}
|
||||||
|
|
||||||
static const uint8_t blank_vals[] = { 0, 1, 5, 10, 30, 60 };
|
static const uint8_t blank_vals[] = { 0, 1, 5, 10, 30, 60 };
|
||||||
static const char* blank_labels[] = { "Never", "1 minute", "5 minutes", "10 minutes", "30 minutes", "60 minutes" };
|
static const char* blank_labels[] = { "Never", "1 minute", "5 minutes", "10 minutes", "30 minutes", "60 minutes" };
|
||||||
static const int blank_count = 6;
|
static const int blank_count = 6;
|
||||||
@@ -320,6 +338,23 @@ static void config_send_html() {
|
|||||||
html += F("</select>");
|
html += F("</select>");
|
||||||
html += F("<p class='note'>Turn off display after inactivity to save power</p>");
|
html += F("<p class='note'>Turn off display after inactivity to save power</p>");
|
||||||
|
|
||||||
|
html += F("<label>Display Orientation</label><select name='disp_rot'>");
|
||||||
|
html += F("<option value='0'");
|
||||||
|
if (cur_rotation == 0) html += F(" selected");
|
||||||
|
html += F(">Landscape</option>");
|
||||||
|
html += F("<option value='1'");
|
||||||
|
if (cur_rotation == 1) html += F(" selected");
|
||||||
|
html += F(">Portrait</option>");
|
||||||
|
html += F("<option value='2'");
|
||||||
|
if (cur_rotation == 2) html += F(" selected");
|
||||||
|
html += F(">Landscape Flipped</option>");
|
||||||
|
html += F("<option value='3'");
|
||||||
|
if (cur_rotation == 3) html += F(" selected");
|
||||||
|
html += F(">Portrait Flipped</option>");
|
||||||
|
html += F("</select>");
|
||||||
|
html += F("<p class='note'>Choose the orientation that matches your OLED mounting. "
|
||||||
|
"Landscape modes place the two status panes side by side; portrait modes stack them.</p>");
|
||||||
|
|
||||||
// ── Submit ──
|
// ── Submit ──
|
||||||
html += F(
|
html += F(
|
||||||
"<button type='submit'>Save & Reboot</button>"
|
"<button type='submit'>Save & Reboot</button>"
|
||||||
@@ -353,6 +388,14 @@ static void config_handle_save() {
|
|||||||
// Set WiFi mode to STA
|
// Set WiFi mode to STA
|
||||||
EEPROM.write(eeprom_addr(ADDR_CONF_WIFI), WR_WIFI_STA);
|
EEPROM.write(eeprom_addr(ADDR_CONF_WIFI), WR_WIFI_STA);
|
||||||
|
|
||||||
|
// Boundary mode always uses DHCP on the STA interface. Clear the legacy
|
||||||
|
// static IP and netmask slots so stale values from older firmware or tools
|
||||||
|
// cannot force a persistent static address.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_IP + i), 0x00);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_NM + i), 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
// ── WiFi enable setting ──
|
// ── WiFi enable setting ──
|
||||||
boundary_state.wifi_enabled = (config_server->arg("wifi_en").toInt() == 1);
|
boundary_state.wifi_enabled = (config_server->arg("wifi_en").toInt() == 1);
|
||||||
|
|
||||||
@@ -370,6 +413,12 @@ static void config_handle_save() {
|
|||||||
eeprom_update(eeprom_addr(ADDR_CONF_DBLK), blank_val);
|
eeprom_update(eeprom_addr(ADDR_CONF_DBLK), blank_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int display_rotation = config_server->arg("disp_rot").toInt();
|
||||||
|
if (display_rotation < 0 || display_rotation > 3) {
|
||||||
|
display_rotation = config_default_display_rotation();
|
||||||
|
}
|
||||||
|
eeprom_update(eeprom_addr(ADDR_CONF_DROT), (uint8_t)display_rotation);
|
||||||
|
|
||||||
// ── TCP backbone settings ──
|
// ── TCP backbone settings ──
|
||||||
boundary_state.tcp_mode = (uint8_t)config_server->arg("tcp_mode").toInt(); // 0=disabled, 1=client
|
boundary_state.tcp_mode = (uint8_t)config_server->arg("tcp_mode").toInt(); // 0=disabled, 1=client
|
||||||
if (boundary_state.tcp_mode > 1) boundary_state.tcp_mode = 0;
|
if (boundary_state.tcp_mode > 1) boundary_state.tcp_mode = 0;
|
||||||
@@ -421,7 +470,7 @@ static void config_handle_save() {
|
|||||||
if (bw_val > 0) lora_bw = bw_val;
|
if (bw_val > 0) lora_bw = bw_val;
|
||||||
|
|
||||||
int sf_val = config_server->arg("sf").toInt();
|
int sf_val = config_server->arg("sf").toInt();
|
||||||
if (sf_val >= 6 && sf_val <= 12) lora_sf = sf_val;
|
if (sf_val >= 5 && sf_val <= 12) lora_sf = sf_val;
|
||||||
|
|
||||||
int cr_val = config_server->arg("cr").toInt();
|
int cr_val = config_server->arg("cr").toInt();
|
||||||
if (cr_val >= 5 && cr_val <= 8) lora_cr = cr_val;
|
if (cr_val >= 5 && cr_val <= 8) lora_cr = cr_val;
|
||||||
@@ -481,6 +530,14 @@ static void config_handle_redirect() {
|
|||||||
|
|
||||||
// ─── Check if config is needed ───────────────────────────────────────────────
|
// ─── Check if config is needed ───────────────────────────────────────────────
|
||||||
bool boundary_needs_config() {
|
bool boundary_needs_config() {
|
||||||
|
// If the RTNode app marker is missing, this node was either never
|
||||||
|
// configured by RTNode or was flashed from a different firmware family
|
||||||
|
// such as stock RNode. Force the portal so RTNode can claim and rewrite
|
||||||
|
// its persisted settings explicitly.
|
||||||
|
if (!boundary_app_marker_valid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if WiFi SSID is configured
|
// Check if WiFi SSID is configured
|
||||||
char ssid[33];
|
char ssid[33];
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
@@ -557,6 +614,10 @@ void config_portal_start() {
|
|||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// Headless: LED ramp will be driven from the WCC portal loop
|
||||||
|
if (headless_mode) {
|
||||||
|
Serial.println("[Config] Headless mode — LED will breathe during config portal");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Stop Config Portal ──────────────────────────────────────────────────────
|
// ─── Stop Config Portal ──────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
// Copyright (C) 2026, Boundary Mode Extension
|
// Copyright (C) 2026, Boundary Mode Extension
|
||||||
// Based on microReticulum_Firmware by Mark Qvist
|
// Based on microReticulum_Firmware by Mark Qvist
|
||||||
//
|
//
|
||||||
// BoundaryMode.h — Configuration and runtime state for the Boundary Mode
|
// BoundaryMode.h — Configuration and runtime state for the legacy
|
||||||
// firmware variant. This header defines the WiFi backbone connection
|
// "Boundary Mode" firmware variant. Going forward this should be renamed
|
||||||
// parameters and boundary-specific operational settings.
|
// "Transport Mode". It is the only intended operating mode for this fork;
|
||||||
|
// the old multi-mode split is kept only for compatibility while the codebase
|
||||||
|
// is being simplified.
|
||||||
//
|
//
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
@@ -15,8 +17,19 @@
|
|||||||
|
|
||||||
#ifdef BOUNDARY_MODE
|
#ifdef BOUNDARY_MODE
|
||||||
|
|
||||||
|
// Compatibility alias for the planned rename from Boundary Mode to
|
||||||
|
// Transport Mode. New code should prefer the transport terminology even
|
||||||
|
// while the legacy BOUNDARY_MODE compile-time flag still exists.
|
||||||
|
#ifndef TRANSPORT_MODE
|
||||||
|
#define TRANSPORT_MODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// ─── Boundary Mode Configuration ────────────────────────────────────────────
|
// ─── Boundary Mode Configuration ────────────────────────────────────────────
|
||||||
//
|
//
|
||||||
|
// NOTE: "Boundary Mode" is the legacy name. This should be relabeled
|
||||||
|
// "Transport Mode" once the remaining non-transport code paths are removed.
|
||||||
|
// In practice this is the only supported mode in this firmware branch.
|
||||||
|
//
|
||||||
// The boundary node operates with TWO RNS interfaces:
|
// The boundary node operates with TWO RNS interfaces:
|
||||||
//
|
//
|
||||||
// 1. LoRaInterface (MODE_GATEWAY) — radio side, handles LoRa mesh
|
// 1. LoRaInterface (MODE_GATEWAY) — radio side, handles LoRa mesh
|
||||||
@@ -72,10 +85,16 @@
|
|||||||
#define ADDR_CONF_IFAC_EN 0xD6 // IFAC enable flag (1 byte, 0x73 = enabled)
|
#define ADDR_CONF_IFAC_EN 0xD6 // IFAC enable flag (1 byte, 0x73 = enabled)
|
||||||
#define ADDR_CONF_IFAC_NAME 0xD7 // Network name (33 bytes, null-terminated)
|
#define ADDR_CONF_IFAC_NAME 0xD7 // Network name (33 bytes, null-terminated)
|
||||||
#define ADDR_CONF_IFAC_PASS 0xF8 // Passphrase (33 bytes, null-terminated)
|
#define ADDR_CONF_IFAC_PASS 0xF8 // Passphrase (33 bytes, null-terminated)
|
||||||
// Total: 0x119 (281 bytes — extends beyond 256-byte CONFIG area into
|
#define ADDR_CONF_APP_MARKER0 0x119 // RTNode app marker byte 0
|
||||||
|
#define ADDR_CONF_APP_MARKER1 0x11A // RTNode app marker byte 1
|
||||||
|
#define ADDR_CONF_APP_VERSION 0x11B // RTNode app config version
|
||||||
|
// Total: 0x11C (284 bytes — extends beyond 256-byte CONFIG area into
|
||||||
// unused EEPROM gap; safe on ESP32 where EEPROM starts at 824)
|
// unused EEPROM gap; safe on ESP32 where EEPROM starts at 824)
|
||||||
|
|
||||||
#define BOUNDARY_ENABLE_BYTE 0x73
|
#define BOUNDARY_ENABLE_BYTE 0x73
|
||||||
|
#define BOUNDARY_APP_MARKER0 0x52
|
||||||
|
#define BOUNDARY_APP_MARKER1 0x54
|
||||||
|
#define BOUNDARY_APP_VERSION 0x01
|
||||||
|
|
||||||
// ─── Boundary Mode Runtime State ─────────────────────────────────────────────
|
// ─── Boundary Mode Runtime State ─────────────────────────────────────────────
|
||||||
#ifndef BOUNDARY_STATE_DEFINED
|
#ifndef BOUNDARY_STATE_DEFINED
|
||||||
@@ -115,6 +134,24 @@ extern BoundaryState boundary_state;
|
|||||||
|
|
||||||
// ─── Boundary Mode EEPROM Load/Save ─────────────────────────────────────────
|
// ─── Boundary Mode EEPROM Load/Save ─────────────────────────────────────────
|
||||||
|
|
||||||
|
inline bool boundary_app_marker_valid() {
|
||||||
|
return EEPROM.read(config_addr(ADDR_CONF_APP_MARKER0)) == BOUNDARY_APP_MARKER0 &&
|
||||||
|
EEPROM.read(config_addr(ADDR_CONF_APP_MARKER1)) == BOUNDARY_APP_MARKER1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool boundary_app_version_matches() {
|
||||||
|
return boundary_app_marker_valid() &&
|
||||||
|
EEPROM.read(config_addr(ADDR_CONF_APP_VERSION)) == BOUNDARY_APP_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void boundary_clear_app_marker() {
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER0), 0xFF);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER1), 0xFF);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_VERSION), 0xFF);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_BMODE), 0xFF);
|
||||||
|
EEPROM.commit();
|
||||||
|
}
|
||||||
|
|
||||||
inline void boundary_load_config() {
|
inline void boundary_load_config() {
|
||||||
// Check if boundary mode is configured
|
// Check if boundary mode is configured
|
||||||
uint8_t bmode = EEPROM.read(config_addr(ADDR_CONF_BMODE));
|
uint8_t bmode = EEPROM.read(config_addr(ADDR_CONF_BMODE));
|
||||||
@@ -258,6 +295,9 @@ inline void boundary_save_config() {
|
|||||||
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + i), boundary_state.ifac_passphrase[i]);
|
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + i), boundary_state.ifac_passphrase[i]);
|
||||||
}
|
}
|
||||||
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + 32), 0x00);
|
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + 32), 0x00);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER0), BOUNDARY_APP_MARKER0);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER1), BOUNDARY_APP_MARKER1);
|
||||||
|
EEPROM.write(config_addr(ADDR_CONF_APP_VERSION), BOUNDARY_APP_VERSION);
|
||||||
|
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
}
|
}
|
||||||
|
|||||||
8
Config.h
8
Config.h
@@ -114,7 +114,14 @@
|
|||||||
#define CSMA_CW_PER_BAND_WINDOWS 15
|
#define CSMA_CW_PER_BAND_WINDOWS 15
|
||||||
#define CSMA_BAND_1_MAX_AIRTIME 7
|
#define CSMA_BAND_1_MAX_AIRTIME 7
|
||||||
#define CSMA_BAND_N_MIN_AIRTIME 85
|
#define CSMA_BAND_N_MIN_AIRTIME 85
|
||||||
|
|
||||||
|
// Increase threshold for specific boards
|
||||||
|
#if BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
#define CSMA_INFR_THRESHOLD_DB 14
|
||||||
|
#else
|
||||||
#define CSMA_INFR_THRESHOLD_DB 11
|
#define CSMA_INFR_THRESHOLD_DB 11
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CSMA_RFENV_RECAL_MS 2500
|
#define CSMA_RFENV_RECAL_MS 2500
|
||||||
#define CSMA_RFENV_RECAL_LIMIT_DB -83
|
#define CSMA_RFENV_RECAL_LIMIT_DB -83
|
||||||
bool interference_detected = false;
|
bool interference_detected = false;
|
||||||
@@ -145,6 +152,7 @@
|
|||||||
bool hw_ready = false;
|
bool hw_ready = false;
|
||||||
bool radio_error = false;
|
bool radio_error = false;
|
||||||
bool disp_ready = false;
|
bool disp_ready = false;
|
||||||
|
bool headless_mode = false;
|
||||||
bool pmu_ready = false;
|
bool pmu_ready = false;
|
||||||
bool promisc = false;
|
bool promisc = false;
|
||||||
bool implicit = false;
|
bool implicit = false;
|
||||||
|
|||||||
10
Display.h
10
Display.h
@@ -97,6 +97,11 @@ extern BoundaryState boundary_state;
|
|||||||
#define DISP_ADDR 0x3C
|
#define DISP_ADDR 0x3C
|
||||||
#define SCL_OLED 18
|
#define SCL_OLED 18
|
||||||
#define SDA_OLED 17
|
#define SDA_OLED 17
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
#define DISP_RST -1
|
||||||
|
#define DISP_ADDR 0x3C
|
||||||
|
#define SCL_OLED 44
|
||||||
|
#define SDA_OLED 42
|
||||||
#elif BOARD_MODEL == BOARD_RAK4631
|
#elif BOARD_MODEL == BOARD_RAK4631
|
||||||
// RAK1921/SSD1306
|
// RAK1921/SSD1306
|
||||||
#define DISP_RST -1
|
#define DISP_RST -1
|
||||||
@@ -334,6 +339,8 @@ bool display_init() {
|
|||||||
digitalWrite(pin_display_en, HIGH);
|
digitalWrite(pin_display_en, HIGH);
|
||||||
delay(50);
|
delay(50);
|
||||||
Wire.begin(SDA_OLED, SCL_OLED);
|
Wire.begin(SDA_OLED, SCL_OLED);
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
Wire.begin(SDA_OLED, SCL_OLED);
|
||||||
#elif BOARD_MODEL == BOARD_LORA32_V1_0
|
#elif BOARD_MODEL == BOARD_LORA32_V1_0
|
||||||
int pin_display_en = 16;
|
int pin_display_en = 16;
|
||||||
digitalWrite(pin_display_en, LOW);
|
digitalWrite(pin_display_en, LOW);
|
||||||
@@ -455,6 +462,9 @@ bool display_init() {
|
|||||||
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
||||||
disp_mode = DISP_MODE_PORTRAIT;
|
disp_mode = DISP_MODE_PORTRAIT;
|
||||||
display.setRotation(1);
|
display.setRotation(1);
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
disp_mode = DISP_MODE_LANDSCAPE;
|
||||||
|
display.setRotation(0);
|
||||||
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
||||||
disp_mode = DISP_MODE_PORTRAIT;
|
disp_mode = DISP_MODE_PORTRAIT;
|
||||||
display.setRotation(1);
|
display.setRotation(1);
|
||||||
|
|||||||
3
Input.h
3
Input.h
@@ -96,6 +96,9 @@
|
|||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
headless_led_fast_blink();
|
||||||
|
} else if (display_lock_white) {
|
||||||
|
headless_led_fast_blink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
Power.h
17
Power.h
@@ -147,6 +147,23 @@ float pmu_temperature = PMU_TEMP_MIN-1;
|
|||||||
bool bat_voltage_dropping = false;
|
bool bat_voltage_dropping = false;
|
||||||
float bat_delay_v = 0;
|
float bat_delay_v = 0;
|
||||||
float bat_state_change_v = 0;
|
float bat_state_change_v = 0;
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
#define BAT_V_MIN 3.05
|
||||||
|
#define BAT_V_MAX 4.0
|
||||||
|
#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;
|
||||||
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
||||||
#define BAT_V_MIN 3.15
|
#define BAT_V_MIN 3.15
|
||||||
#define BAT_V_MAX 4.165
|
#define BAT_V_MAX 4.165
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
A custom firmware for the **Heltec WiFi LoRa 32 V4** (ESP32-S3 + SX1262) that operates as a **Transport Node** — bridging a local LoRa radio network with a remote TCP/IP backbone (such as [rmap.world](https://rmap.world)) over WiFi.
|
A custom firmware for the **Heltec WiFi LoRa 32 V4** (ESP32-S3 + SX1262) that operates as a **Transport Node** — bridging a local LoRa radio network with a remote TCP/IP backbone (such as [rmap.world](https://rmap.world)) over WiFi.
|
||||||
|
|
||||||
|
This project was primarily developed with the use of AI assistance.
|
||||||
|
|
||||||
```
|
```
|
||||||
Android / Sideband Remote
|
Android / Sideband Remote
|
||||||
┌──────────┐ ┌────────────┐ Reticulum
|
┌──────────┐ ┌────────────┐ Reticulum
|
||||||
@@ -52,25 +54,27 @@ This firmware was designed for the **Heltec WiFi LoRa 32 V4**. This board was ch
|
|||||||
The easiest way to flash a pre-built firmware. You only need Python 3 and a USB cable.
|
The easiest way to flash a pre-built firmware. You only need Python 3 and a USB cable.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install esptool (one time)
|
|
||||||
pip install esptool
|
|
||||||
|
|
||||||
# Clone this repo (or download just flash.py + the firmware binary)
|
# Clone this repo (or download just flash.py + the firmware binary)
|
||||||
git clone https://github.com/jrl290/RTNode-HeltecV4.git
|
git clone https://github.com/jrl290/RTNode-HeltecV4.git
|
||||||
cd RTNode-HeltecV4
|
cd RTNode-HeltecV4
|
||||||
|
|
||||||
# Download latest firmware from GitHub Releases and flash
|
# Download latest firmware from GitHub Releases and flash
|
||||||
# (auto-detects V3 vs V4 from flash size)
|
# (auto-detects V3 vs V4 from flash size)
|
||||||
python flash.py --download
|
python flash.py
|
||||||
|
|
||||||
|
# Optional: use your machine's installed esptool instead of the bundled copy
|
||||||
|
python flash.py --use-system-esptool
|
||||||
|
|
||||||
# Or specify board explicitly
|
# Or specify board explicitly
|
||||||
python flash.py --download --board v3
|
python flash.py --board v3
|
||||||
python flash.py --download --board v4
|
python flash.py --board v4
|
||||||
|
|
||||||
# Or flash a local binary
|
# Or flash a local binary
|
||||||
python flash.py --file rtnode_heltec_v4.bin
|
python flash.py --file rtnode_heltec_v4.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, `flash.py` uses the bundled `Release/esptool/esptool.py` for reproducible flashing. Only use `--use-system-esptool` if you explicitly want to override that with a host-installed esptool.
|
||||||
|
|
||||||
The flash utility auto-detects whether a V3 or V4 is connected by querying the flash size (8MB = V3, 16MB = V4). You can override with `--board v3` or `--board v4`. It will list all available serial ports and prompt you to choose one. If no ports are detected, you may need to hold the **BOOT** button while pressing **RESET** to enter download mode.
|
The flash utility auto-detects whether a V3 or V4 is connected by querying the flash size (8MB = V3, 16MB = V4). You can override with `--board v3` or `--board v4`. It will list all available serial ports and prompt you to choose one. If no ports are detected, you may need to hold the **BOOT** button while pressing **RESET** to enter download mode.
|
||||||
|
|
||||||
### Option B: Build from Source (PlatformIO)
|
### Option B: Build from Source (PlatformIO)
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
#include "Utilities.h"
|
#include "Utilities.h"
|
||||||
|
|
||||||
// CBA Boundary Mode
|
// CBA Boundary Mode
|
||||||
|
// NOTE: Boundary Mode is the legacy name. This firmware branch intends to
|
||||||
|
// converge on a single Transport Mode, with the BOUNDARY_MODE symbol kept
|
||||||
|
// temporarily as a compatibility shim during cleanup.
|
||||||
#ifdef BOUNDARY_MODE
|
#ifdef BOUNDARY_MODE
|
||||||
#include "BoundaryMode.h"
|
#include "BoundaryMode.h"
|
||||||
#include "TcpInterface.h"
|
#include "TcpInterface.h"
|
||||||
@@ -243,6 +246,9 @@ TcpInterface* local_tcp_interface_ptr = nullptr;
|
|||||||
// RTC memory flag — survives software reset but not power cycle
|
// RTC memory flag — survives software reset but not power cycle
|
||||||
RTC_NOINIT_ATTR uint32_t boundary_config_request;
|
RTC_NOINIT_ATTR uint32_t boundary_config_request;
|
||||||
#define BOUNDARY_CONFIG_MAGIC 0xC0F19A7E
|
#define BOUNDARY_CONFIG_MAGIC 0xC0F19A7E
|
||||||
|
// RTC flag to skip config portal on next boot (set when user powers off from WCC)
|
||||||
|
RTC_NOINIT_ATTR uint32_t boundary_skip_config;
|
||||||
|
#define BOUNDARY_SKIP_MAGIC 0x5E1FC0F0
|
||||||
|
|
||||||
// Bootloop detection: count rapid reboots in RTC memory.
|
// Bootloop detection: count rapid reboots in RTC memory.
|
||||||
// After BOOTLOOP_THRESHOLD consecutive reboots within BOOTLOOP_WINDOW_MS,
|
// After BOOTLOOP_THRESHOLD consecutive reboots within BOOTLOOP_WINDOW_MS,
|
||||||
@@ -350,7 +356,7 @@ void setup() {
|
|||||||
boot_seq();
|
boot_seq();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_HELTEC32_V4 && BOARD_MODEL != BOARD_HELTEC32_V3
|
#if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_HELTEC32_V4 && BOARD_MODEL != BOARD_HELTEC32_V3 && BOARD_MODEL != BOARD_MESHADVENTURER_S3
|
||||||
// Some boards need to wait until the hardware UART is set up before booting
|
// Some boards need to wait until the hardware UART is set up before booting
|
||||||
// the full firmware. In the case of the RAK4631, Heltec T114, and Heltec V3,
|
// the full firmware. In the case of the RAK4631, Heltec T114, and Heltec V3,
|
||||||
// the line below will wait until a serial connection is actually established
|
// the line below will wait until a serial connection is actually established
|
||||||
@@ -473,7 +479,17 @@ void setup() {
|
|||||||
|
|
||||||
display_unblank();
|
display_unblank();
|
||||||
disp_ready = display_init();
|
disp_ready = display_init();
|
||||||
|
if (disp_ready) {
|
||||||
update_display();
|
update_display();
|
||||||
|
} else {
|
||||||
|
headless_mode = true;
|
||||||
|
Serial.println("[Headless] No display detected — running in headless mode");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// LED solid on at boot for V3/V4 boards (with or without display)
|
||||||
|
#if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3
|
||||||
|
headless_led_solid();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ── Boundary Mode: check if config portal is needed ──
|
// ── Boundary Mode: check if config portal is needed ──
|
||||||
@@ -512,22 +528,66 @@ void setup() {
|
|||||||
|
|
||||||
// Enter config mode if: first boot with no config, OR button-triggered reboot,
|
// Enter config mode if: first boot with no config, OR button-triggered reboot,
|
||||||
// OR bootloop detected
|
// OR bootloop detected
|
||||||
|
bool app_marker_missing = !boundary_app_marker_valid();
|
||||||
bool need_config = boundary_needs_config();
|
bool need_config = boundary_needs_config();
|
||||||
bool config_requested = (boundary_config_request == BOUNDARY_CONFIG_MAGIC);
|
bool config_requested = (boundary_config_request == BOUNDARY_CONFIG_MAGIC);
|
||||||
|
bool skip_config = (boundary_skip_config == BOUNDARY_SKIP_MAGIC);
|
||||||
boundary_config_request = 0; // Clear flag immediately
|
boundary_config_request = 0; // Clear flag immediately
|
||||||
|
boundary_skip_config = 0; // Clear skip flag immediately
|
||||||
|
|
||||||
|
// Skip flag only suppresses a button-triggered re-entry, not a genuinely
|
||||||
|
// unconfigured device. If there's no config saved, always show the portal.
|
||||||
|
if (skip_config && config_requested) {
|
||||||
|
Serial.println("[Boundary] Skipping config portal — user requested normal boot");
|
||||||
|
config_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (need_config || config_requested || bootloop_detected) {
|
if (need_config || config_requested || bootloop_detected) {
|
||||||
if (bootloop_detected) {
|
if (bootloop_detected) {
|
||||||
Serial.println("[Boundary] Entering config portal due to bootloop recovery");
|
Serial.println("[Boundary] Entering config portal due to bootloop recovery");
|
||||||
} else if (config_requested) {
|
} else if (config_requested) {
|
||||||
Serial.println("[Boundary] Config mode requested via button hold");
|
Serial.println("[Boundary] Config mode requested via button hold");
|
||||||
|
} else if (app_marker_missing) {
|
||||||
|
Serial.println("[Boundary] RTNode app marker missing — previous firmware was not RTNode or config is unclaimed");
|
||||||
|
Serial.println("[Boundary] Starting config portal to migrate settings into RTNode");
|
||||||
} else {
|
} else {
|
||||||
Serial.println("[Boundary] No configuration found — starting config portal");
|
Serial.println("[Boundary] No configuration found — starting config portal");
|
||||||
}
|
}
|
||||||
config_portal_start();
|
config_portal_start();
|
||||||
// Block here: only run the config portal until user saves and device reboots
|
// Block here: only run the config portal until user saves and device reboots
|
||||||
|
// Track button state for "off" action (1-3s press = sleep)
|
||||||
|
bool wcc_btn_down = false;
|
||||||
|
uint32_t wcc_btn_down_at = 0;
|
||||||
while (config_portal_is_active()) {
|
while (config_portal_is_active()) {
|
||||||
config_portal_loop();
|
config_portal_loop();
|
||||||
|
|
||||||
|
// Headless LED: slow ramp breathe effect during WCC mode
|
||||||
|
headless_led_ramp();
|
||||||
|
|
||||||
|
// Button handling: allow 1-3s press to turn off (deep sleep)
|
||||||
|
// Next power-on boots to normal mode since boundary_config_request is cleared
|
||||||
|
#if HAS_INPUT
|
||||||
|
{
|
||||||
|
int btn = digitalRead(pin_btn_usr1);
|
||||||
|
if (btn == LOW && !wcc_btn_down) {
|
||||||
|
wcc_btn_down = true;
|
||||||
|
wcc_btn_down_at = millis();
|
||||||
|
} else if (btn == HIGH && wcc_btn_down) {
|
||||||
|
uint32_t held = millis() - wcc_btn_down_at;
|
||||||
|
wcc_btn_down = false;
|
||||||
|
if (held >= 700 && held <= 5000) {
|
||||||
|
Serial.println("[Boundary] Button press in WCC mode — powering off");
|
||||||
|
boundary_skip_config = BOUNDARY_SKIP_MAGIC; // Skip config on next boot
|
||||||
|
headless_led_off();
|
||||||
|
config_portal_stop();
|
||||||
|
#if HAS_SLEEP
|
||||||
|
sleep_now();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if MCU_VARIANT == MCU_ESP32
|
#if MCU_VARIANT == MCU_ESP32
|
||||||
esp_task_wdt_reset();
|
esp_task_wdt_reset();
|
||||||
#endif
|
#endif
|
||||||
@@ -1681,6 +1741,9 @@ void serial_callback(uint8_t sbyte) {
|
|||||||
eeprom_conf_save();
|
eeprom_conf_save();
|
||||||
} else if (command == CMD_CONF_DELETE) {
|
} else if (command == CMD_CONF_DELETE) {
|
||||||
eeprom_conf_delete();
|
eeprom_conf_delete();
|
||||||
|
#ifdef BOUNDARY_MODE
|
||||||
|
boundary_clear_app_marker();
|
||||||
|
#endif
|
||||||
} else if (command == CMD_FB_EXT) {
|
} else if (command == CMD_FB_EXT) {
|
||||||
#if HAS_DISPLAY == true
|
#if HAS_DISPLAY == true
|
||||||
if (sbyte == 0xFF) {
|
if (sbyte == 0xFF) {
|
||||||
@@ -2511,6 +2574,13 @@ void loop() {
|
|||||||
if (disp_ready && !display_updating) update_display();
|
if (disp_ready && !display_updating) update_display();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// LED solid when operational on V3/V4 boards (yield to fast blink during white screen)
|
||||||
|
#if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3
|
||||||
|
if (radio_online && !display_lock_white) {
|
||||||
|
headless_led_solid();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAS_PMU
|
#if HAS_PMU
|
||||||
if (pmu_ready) update_pmu();
|
if (pmu_ready) update_pmu();
|
||||||
#endif
|
#endif
|
||||||
@@ -2558,6 +2628,8 @@ void sleep_now() {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if BOARD_MODEL == BOARD_HELTEC32_V4
|
#if BOARD_MODEL == BOARD_HELTEC32_V4
|
||||||
|
headless_led_off();
|
||||||
|
headless_led_detach_pwm();
|
||||||
digitalWrite(LORA_PA_CPS, LOW);
|
digitalWrite(LORA_PA_CPS, LOW);
|
||||||
digitalWrite(LORA_PA_CSD, LOW);
|
digitalWrite(LORA_PA_CSD, LOW);
|
||||||
digitalWrite(LORA_PA_PWR_EN, LOW);
|
digitalWrite(LORA_PA_PWR_EN, LOW);
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Release/rnode_firmware_heltec32v3.bin
Executable file
BIN
Release/rnode_firmware_heltec32v3.bin
Executable file
Binary file not shown.
Binary file not shown.
8
Remote.h
8
Remote.h
@@ -78,6 +78,13 @@ void wifi_remote_start_ap() {
|
|||||||
void wifi_remote_start_sta() {
|
void wifi_remote_start_sta() {
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
|
||||||
|
#ifdef BOUNDARY_MODE
|
||||||
|
// Boundary mode does not expose static STA addressing in its config flow.
|
||||||
|
// Always return the station interface to DHCP so stale legacy EEPROM data
|
||||||
|
// cannot pin the node to an unintended address.
|
||||||
|
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||||
|
#else
|
||||||
|
|
||||||
uint8_t ip[4]; bool ip_ok = true;
|
uint8_t ip[4]; bool ip_ok = true;
|
||||||
for (uint8_t i = 0; i < 4; i++) { ip[i] = EEPROM.read(config_addr(ADDR_CONF_IP+i)); }
|
for (uint8_t i = 0; i < 4; i++) { ip[i] = EEPROM.read(config_addr(ADDR_CONF_IP+i)); }
|
||||||
if (ip[0]==0x00 && ip[1]==0x00 && ip[2]==0x00 && ip[3]==0x00) { ip_ok = false; }
|
if (ip[0]==0x00 && ip[1]==0x00 && ip[2]==0x00 && ip[3]==0x00) { ip_ok = false; }
|
||||||
@@ -97,6 +104,7 @@ void wifi_remote_start_sta() {
|
|||||||
IPAddress dns2(1, 1, 1, 1);
|
IPAddress dns2(1, 1, 1, 1);
|
||||||
WiFi.config(sta_ip, sta_gw, sta_nm, dns1, dns2);
|
WiFi.config(sta_ip, sta_gw, sta_nm, dns1, dns2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
delay(100);
|
delay(100);
|
||||||
if (wr_ssid[0] != 0x00) {
|
if (wr_ssid[0] != 0x00) {
|
||||||
|
|||||||
86
Utilities.h
86
Utilities.h
@@ -72,6 +72,10 @@ uint8_t eeprom_read(uint32_t mapped_addr);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAS_INPUT == true
|
#if HAS_INPUT == true
|
||||||
|
// Forward declarations for headless LED functions (defined later in this file)
|
||||||
|
void headless_led_fast_blink();
|
||||||
|
void headless_led_ramp();
|
||||||
|
void headless_led_off();
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -320,6 +324,13 @@ extern RNS::Reticulum reticulum;
|
|||||||
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
|
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
|
||||||
void led_id_on() { }
|
void led_id_on() { }
|
||||||
void led_id_off() { }
|
void led_id_off() { }
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
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); }
|
||||||
|
void led_id_on() { }
|
||||||
|
void led_id_off() { }
|
||||||
#elif BOARD_MODEL == BOARD_LORA32_V2_1
|
#elif BOARD_MODEL == BOARD_LORA32_V2_1
|
||||||
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
|
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
|
||||||
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
|
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
|
||||||
@@ -382,6 +393,79 @@ extern RNS::Reticulum reticulum;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ── Headless LED indicators (for Heltec V4 without OLED) ─────────────────
|
||||||
|
// Uses LEDC PWM for smooth ramp effects on pin_led_tx (GPIO 35)
|
||||||
|
#if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == MESHADVENTURER_S3
|
||||||
|
#define HEADLESS_LED_CHANNEL 0
|
||||||
|
bool headless_led_pwm_attached = false;
|
||||||
|
|
||||||
|
void headless_led_ensure_pwm() {
|
||||||
|
if (!headless_led_pwm_attached) {
|
||||||
|
ledcSetup(HEADLESS_LED_CHANNEL, 5000, 8); // channel 0, 5kHz, 8-bit
|
||||||
|
ledcAttachPin(pin_led_tx, HEADLESS_LED_CHANNEL);
|
||||||
|
headless_led_pwm_attached = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void headless_led_detach_pwm() {
|
||||||
|
if (headless_led_pwm_attached) {
|
||||||
|
ledcDetachPin(pin_led_tx);
|
||||||
|
headless_led_pwm_attached = false;
|
||||||
|
pinMode(pin_led_tx, OUTPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solid ON — normal headless operation
|
||||||
|
void headless_led_solid() {
|
||||||
|
headless_led_ensure_pwm();
|
||||||
|
ledcWrite(HEADLESS_LED_CHANNEL, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast blink — replaces "white screen" indicator (non-blocking, call from loop)
|
||||||
|
void headless_led_fast_blink() {
|
||||||
|
headless_led_ensure_pwm();
|
||||||
|
static uint32_t last_toggle = 0;
|
||||||
|
static bool on = false;
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - last_toggle >= 100) { // 5Hz blink
|
||||||
|
last_toggle = now;
|
||||||
|
on = !on;
|
||||||
|
ledcWrite(HEADLESS_LED_CHANNEL, on ? 255 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow ramp in/out — breathe effect for WiFi Captive Configure mode
|
||||||
|
void headless_led_ramp() {
|
||||||
|
headless_led_ensure_pwm();
|
||||||
|
static uint32_t last_step = 0;
|
||||||
|
static uint8_t brightness = 0;
|
||||||
|
static int8_t direction = 1;
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - last_step >= 10) { // ~100 steps/sec, full cycle ~5 seconds
|
||||||
|
last_step = now;
|
||||||
|
brightness += direction;
|
||||||
|
if (brightness >= 255) { brightness = 255; direction = -1; }
|
||||||
|
if (brightness == 0) { direction = 1; }
|
||||||
|
ledcWrite(HEADLESS_LED_CHANNEL, brightness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void headless_led_off() {
|
||||||
|
if (headless_led_pwm_attached) {
|
||||||
|
ledcWrite(HEADLESS_LED_CHANNEL, 0);
|
||||||
|
} else {
|
||||||
|
digitalWrite(pin_led_tx, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void headless_led_ensure_pwm() {}
|
||||||
|
void headless_led_detach_pwm() {}
|
||||||
|
void headless_led_solid() {}
|
||||||
|
void headless_led_fast_blink() {}
|
||||||
|
void headless_led_ramp() {}
|
||||||
|
void headless_led_off() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void hard_reset(void) {
|
void hard_reset(void) {
|
||||||
#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560
|
#if MCU_VARIANT == MCU_1284P || MCU_VARIANT == MCU_2560
|
||||||
wdt_enable(WDTO_15MS);
|
wdt_enable(WDTO_15MS);
|
||||||
@@ -1696,6 +1780,8 @@ bool eeprom_model_valid() {
|
|||||||
if (model == MODEL_C5 || model == MODEL_CA) {
|
if (model == MODEL_C5 || model == MODEL_CA) {
|
||||||
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
||||||
if (model == MODEL_C8) {
|
if (model == MODEL_C8) {
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
if (model == MODEL_C8) {
|
||||||
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
#elif BOARD_MODEL == BOARD_HELTEC_T114
|
||||||
if (model == MODEL_C6 || model == MODEL_C7) {
|
if (model == MODEL_C6 || model == MODEL_C7) {
|
||||||
#elif BOARD_MODEL == BOARD_RAK4631
|
#elif BOARD_MODEL == BOARD_RAK4631
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ def device_provision(env):
|
|||||||
env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
||||||
elif variant in ("heltec32v4", "heltec32v4_local", "heltec32v4_boundary", "heltec32v4_boundary_local"):
|
elif variant in ("heltec32v4", "heltec32v4_local", "heltec32v4_boundary", "heltec32v4_boundary_local"):
|
||||||
env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
||||||
|
elif variant in ("meshadventurer_s3_boundary"):
|
||||||
|
env.Execute("rnodeconf --product f0 --model fe --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
||||||
elif variant in ("rak4631", "rak4631_local"):
|
elif variant in ("rak4631", "rak4631_local"):
|
||||||
env.Execute("rnodeconf --product 10 --model 12 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
env.Execute("rnodeconf --product 10 --model 12 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT"))
|
||||||
elif variant in ("heltec_t114", "heltec_t114_local"):
|
elif variant in ("heltec_t114", "heltec_t114_local"):
|
||||||
|
|||||||
16
flash.py
16
flash.py
@@ -323,8 +323,6 @@ def find_esptool():
|
|||||||
usually the newest version), then fall back to the bundled script.
|
usually the newest version), then fall back to the bundled script.
|
||||||
"""
|
"""
|
||||||
# 1. pip-installed esptool on PATH
|
# 1. pip-installed esptool on PATH
|
||||||
if shutil.which("esptool.py"):
|
|
||||||
return ["esptool.py"]
|
|
||||||
if shutil.which("esptool"):
|
if shutil.which("esptool"):
|
||||||
return ["esptool"]
|
return ["esptool"]
|
||||||
|
|
||||||
@@ -851,8 +849,8 @@ def flash_firmware(firmware_path, port, esptool_cmd, baud=None,
|
|||||||
flash_addr = f"0x{APP_ADDR:x}"
|
flash_addr = f"0x{APP_ADDR:x}"
|
||||||
print(f" Detected: app-only binary -> flash at {flash_addr}")
|
print(f" Detected: app-only binary -> flash at {flash_addr}")
|
||||||
|
|
||||||
before_arg = "no_reset" if no_reset_before else "default_reset"
|
before_arg = "no_reset" if no_reset_before else "default-reset"
|
||||||
after_arg = "no_reset" if no_hard_reset else "hard_reset"
|
after_arg = "no_reset" if no_hard_reset else "hard-reset"
|
||||||
|
|
||||||
cmd = esptool_cmd + [
|
cmd = esptool_cmd + [
|
||||||
"--chip", CHIP,
|
"--chip", CHIP,
|
||||||
@@ -860,14 +858,14 @@ def flash_firmware(firmware_path, port, esptool_cmd, baud=None,
|
|||||||
"--baud", baud,
|
"--baud", baud,
|
||||||
"--before", before_arg,
|
"--before", before_arg,
|
||||||
"--after", after_arg,
|
"--after", after_arg,
|
||||||
"write_flash",
|
"write-flash",
|
||||||
"-z",
|
"-z",
|
||||||
"--flash_mode", mode,
|
"--flash-mode", mode,
|
||||||
"--flash_freq", FLASH_FREQ,
|
"--flash-freq", FLASH_FREQ,
|
||||||
"--flash_size", flash_size,
|
"--flash-size", flash_size,
|
||||||
]
|
]
|
||||||
if verify:
|
if verify:
|
||||||
cmd.append("--verify")
|
cmd.append("--no-diff-verify")
|
||||||
cmd += [flash_addr, firmware_path]
|
cmd += [flash_addr, firmware_path]
|
||||||
|
|
||||||
print("Running: " + " ".join(cmd[-8:]))
|
print("Running: " + " ".join(cmd[-8:]))
|
||||||
|
|||||||
106
platformio.ini
106
platformio.ini
@@ -9,7 +9,6 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
; Change source and include directories to root of project since RNode places them here
|
|
||||||
include_dir = .
|
include_dir = .
|
||||||
src_dir = .
|
src_dir = .
|
||||||
|
|
||||||
@@ -19,32 +18,18 @@ monitor_speed = 115200
|
|||||||
upload_speed = 460800
|
upload_speed = 460800
|
||||||
build_flags =
|
build_flags =
|
||||||
-Wall
|
-Wall
|
||||||
;-Wextra
|
|
||||||
-Wno-missing-field-initializers
|
-Wno-missing-field-initializers
|
||||||
-Wno-format
|
-Wno-format
|
||||||
-I.
|
-I.
|
||||||
; CBA Define following to disable DEBUG build
|
|
||||||
;-DNDEBUG
|
|
||||||
; CBA Define following to include RNS stack
|
|
||||||
-DHAS_RNS
|
-DHAS_RNS
|
||||||
-DRNS_USE_FS
|
-DRNS_USE_FS
|
||||||
-DRNS_PERSIST_PATHS
|
-DRNS_PERSIST_PATHS
|
||||||
-DMSGPACK_USE_BOOST=OFF
|
-DMSGPACK_USE_BOOST=OFF
|
||||||
; CBA Define following to disable LFS asserts
|
|
||||||
;-DLFS_NO_ASSERT
|
|
||||||
; ???
|
|
||||||
;-DLFS_YES_TRACE
|
|
||||||
; ???
|
|
||||||
;-DCORE_DEBUG_LEVEL=5
|
|
||||||
; ??? NO
|
|
||||||
;-DLOG_LOCAL_LEVEL=5
|
|
||||||
;-DCONFIG_LOG_DEFAULT_LEVEL=5
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
ArduinoJson@^7.4.2
|
ArduinoJson@^7.4.2
|
||||||
MsgPack@^0.4.2
|
MsgPack@^0.4.2
|
||||||
adafruit/Adafruit SSD1306@^2.5.9
|
adafruit/Adafruit SSD1306@^2.5.9
|
||||||
https://github.com/attermann/Crypto.git
|
https://github.com/attermann/Crypto.git
|
||||||
; Exclude directories in root from sources
|
|
||||||
build_src_filter = +<*> -<variants/>
|
build_src_filter = +<*> -<variants/>
|
||||||
extra_scripts = pre:extra_script.py
|
extra_scripts = pre:extra_script.py
|
||||||
|
|
||||||
@@ -60,7 +45,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
adafruit/Adafruit NeoPixel@^1.12.0
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:rnode-ng-21]
|
[env:rnode-ng-21]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -74,7 +59,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
adafruit/Adafruit NeoPixel@^1.12.0
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-t-beam]
|
[env:ttgo-t-beam]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -88,6 +73,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-t-beam-sx1262]
|
[env:ttgo-t-beam-sx1262]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -102,6 +88,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-t-beam-supreme]
|
[env:ttgo-t-beam-supreme]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -118,6 +105,7 @@ lib_deps =
|
|||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
Adafruit_SH110X
|
Adafruit_SH110X
|
||||||
adafruit/Adafruit SH110X@^2.1.14
|
adafruit/Adafruit SH110X@^2.1.14
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:lilygo-t3-s3]
|
[env:lilygo-t3-s3]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -132,6 +120,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:lilygo-t3-s3-sx127x]
|
[env:lilygo-t3-s3-sx127x]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -146,6 +135,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:lilygo-t3-s3-sx1280-pa]
|
[env:lilygo-t3-s3-sx1280-pa]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -160,17 +150,16 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:lilygo-t-deck]
|
[env:lilygo-t-deck]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
custom_variant = tdeck
|
custom_variant = tdeck
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
; Flash / memory layout
|
|
||||||
board_upload.flash_size = 16MB
|
board_upload.flash_size = 16MB
|
||||||
board_upload.maximum_size = 16777216
|
board_upload.maximum_size = 16777216
|
||||||
board_build.partitions = default_16MB.csv
|
board_build.partitions = default_16MB.csv
|
||||||
; Enable PSRAM + correct flash mode
|
|
||||||
board_build.flash_mode = qio
|
board_build.flash_mode = qio
|
||||||
board_build.psram_type = opi
|
board_build.psram_type = opi
|
||||||
board_build.arduino.memory_type = qio_opi
|
board_build.arduino.memory_type = qio_opi
|
||||||
@@ -180,13 +169,11 @@ build_flags =
|
|||||||
-DBOARD_HAS_PSRAM=1
|
-DBOARD_HAS_PSRAM=1
|
||||||
-DARDUINO_USB_MODE=1
|
-DARDUINO_USB_MODE=1
|
||||||
-DCORE_DEBUG_LEVEL=1
|
-DCORE_DEBUG_LEVEL=1
|
||||||
; Enable UARDUINO_ USB_ CDC_ ON_ BOOT will start printing and wait for terminal access during startup
|
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
; Enable UARDUINO_USB_CDC_ON_BOOT will turn off printing and will not block when using the battery
|
|
||||||
; -UARDUINO_USB_CDC_ON_BOOT
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v1]
|
[env:ttgo-lora32-v1]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -200,6 +187,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v2]
|
[env:ttgo-lora32-v2]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -213,6 +201,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v2-extled]
|
[env:ttgo-lora32-v2-extled]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -227,6 +216,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v21]
|
[env:ttgo-lora32-v21]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -240,6 +230,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v21-extled]
|
[env:ttgo-lora32-v21-extled]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -254,6 +245,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:ttgo-lora32-v21-tcxo]
|
[env:ttgo-lora32-v21-tcxo]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -268,6 +260,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:heltec_wifi_lora_32_V2]
|
[env:heltec_wifi_lora_32_V2]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -281,6 +274,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:heltec_wifi_lora_32_V2-extled]
|
[env:heltec_wifi_lora_32_V2-extled]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -295,6 +289,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:heltec_wifi_lora_32_V3]
|
[env:heltec_wifi_lora_32_V3]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -308,16 +303,13 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:heltec_V3_boundary]
|
[env:heltec_V3_boundary]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = heltec_wifi_lora_32_V3
|
board = heltec_wifi_lora_32_V3
|
||||||
custom_variant = heltec32v3
|
custom_variant = heltec32v3
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
; Flash / memory layout for 8MB flash
|
|
||||||
; PSRAM: V3 ESP32-S3FN8 has NO PSRAM — firmware detects this at runtime
|
|
||||||
; and falls back to internal SRAM for TLSF pool.
|
|
||||||
; BOARD_HAS_PSRAM tells Arduino to *attempt* psramInit(); harmless if absent.
|
|
||||||
board_upload.flash_size = 8MB
|
board_upload.flash_size = 8MB
|
||||||
board_upload.maximum_size = 8388608
|
board_upload.maximum_size = 8388608
|
||||||
board_build.partitions = default_8MB.csv
|
board_build.partitions = default_8MB.csv
|
||||||
@@ -330,17 +322,14 @@ build_flags =
|
|||||||
-DBOARD_MODEL=BOARD_HELTEC32_V3
|
-DBOARD_MODEL=BOARD_HELTEC32_V3
|
||||||
-DBOARD_HAS_PSRAM=1
|
-DBOARD_HAS_PSRAM=1
|
||||||
-DBOUNDARY_MODE
|
-DBOUNDARY_MODE
|
||||||
;-DNDEBUG
|
|
||||||
-DRNS_USE_TLSF=1
|
-DRNS_USE_TLSF=1
|
||||||
-DRNS_USE_ALLOCATOR=1
|
-DRNS_USE_ALLOCATOR=1
|
||||||
; --- Boundary mode defaults (override via EEPROM at runtime) ---
|
|
||||||
; TCP server mode (0=server, 1=client)
|
|
||||||
-DBOUNDARY_TCP_MODE=0
|
-DBOUNDARY_TCP_MODE=0
|
||||||
; TCP listen/connect port
|
|
||||||
-DBOUNDARY_TCP_PORT=4242
|
-DBOUNDARY_TCP_PORT=4242
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:heltec_wifi_lora_32_V4]
|
[env:heltec_wifi_lora_32_V4]
|
||||||
@@ -356,13 +345,41 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
|
[env:meshadventurer_S3_boundary]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
custom_variant = meshadventurer_s3_boundary
|
||||||
|
board_build.filesystem = littlefs
|
||||||
|
board_upload.flash_size = 16MB
|
||||||
|
board_upload.maximum_size = 16777216
|
||||||
|
board_build.partitions = default_16MB.csv
|
||||||
|
board_build.flash_mode = qio
|
||||||
|
board_build.psram_type = qio
|
||||||
|
board_build.arduino.memory_type = qio_qspi
|
||||||
|
monitor_speed = 921600
|
||||||
|
build_flags =
|
||||||
|
${env.build_flags}
|
||||||
|
-DBOARD_MODEL=BOARD_MESHADVENTURER_S3
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
-DBOARD_HAS_PSRAM=1
|
||||||
|
-DBOUNDARY_MODE
|
||||||
|
-DRNS_USE_TLSF=1
|
||||||
|
-DRNS_USE_ALLOCATOR=1
|
||||||
|
-DBOUNDARY_TCP_MODE=0
|
||||||
|
-DBOUNDARY_TCP_PORT=4242
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:heltec_V4_boundary]
|
[env:heltec_V4_boundary]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
custom_variant = heltec32v4_boundary
|
custom_variant = heltec32v4_boundary
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
; Flash / memory layout for 16MB flash + 2MB PSRAM
|
|
||||||
board_upload.flash_size = 16MB
|
board_upload.flash_size = 16MB
|
||||||
board_upload.maximum_size = 16777216
|
board_upload.maximum_size = 16777216
|
||||||
board_build.partitions = default_16MB.csv
|
board_build.partitions = default_16MB.csv
|
||||||
@@ -376,20 +393,14 @@ build_flags =
|
|||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
-DBOARD_HAS_PSRAM=1
|
-DBOARD_HAS_PSRAM=1
|
||||||
-DBOUNDARY_MODE
|
-DBOUNDARY_MODE
|
||||||
;-DNDEBUG
|
|
||||||
-DRNS_USE_TLSF=1
|
-DRNS_USE_TLSF=1
|
||||||
-DRNS_USE_ALLOCATOR=1
|
-DRNS_USE_ALLOCATOR=1
|
||||||
; --- Boundary mode defaults (override via EEPROM at runtime) ---
|
|
||||||
; TCP server mode (0=server, 1=client)
|
|
||||||
-DBOUNDARY_TCP_MODE=0
|
-DBOUNDARY_TCP_MODE=0
|
||||||
; TCP listen/connect port
|
|
||||||
-DBOUNDARY_TCP_PORT=4242
|
-DBOUNDARY_TCP_PORT=4242
|
||||||
; Backbone host for client mode (empty = server mode)
|
|
||||||
; -DBOUNDARY_BACKBONE_HOST=\"192.168.1.100\"
|
|
||||||
; -DBOUNDARY_BACKBONE_PORT=4242
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:heltec_V4_boundary-local]
|
[env:heltec_V4_boundary-local]
|
||||||
@@ -414,6 +425,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:featheresp32]
|
[env:featheresp32]
|
||||||
@@ -428,6 +440,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:seeed_xiao_esp32s3]
|
[env:seeed_xiao_esp32s3]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -441,6 +454,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:generic-esp32]
|
[env:generic-esp32]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -454,6 +468,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:wiscore_rak4631]
|
[env:wiscore_rak4631]
|
||||||
platform = nordicnrf52
|
platform = nordicnrf52
|
||||||
@@ -471,8 +486,7 @@ build_flags =
|
|||||||
-DRNS_USE_ALLOCATOR=1
|
-DRNS_USE_ALLOCATOR=1
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
|
|
||||||
[env:ttgo-t-beam-local]
|
[env:ttgo-t-beam-local]
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
@@ -485,12 +499,11 @@ build_flags =
|
|||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
-fexceptions
|
-fexceptions
|
||||||
-DBOARD_MODEL=BOARD_TBEAM
|
-DBOARD_MODEL=BOARD_TBEAM
|
||||||
; CBA TEST
|
|
||||||
;-DUSE_FLASHFS=1
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash
|
Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:ttgo-lora32-v21-local]
|
[env:ttgo-lora32-v21-local]
|
||||||
@@ -506,6 +519,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:heltec_wifi_lora_32_V4-local]
|
[env:heltec_wifi_lora_32_V4-local]
|
||||||
@@ -521,6 +535,7 @@ build_flags =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
XPowersLib@^0.2.1
|
XPowersLib@^0.2.1
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:wiscore_rak4631-local]
|
[env:wiscore_rak4631-local]
|
||||||
@@ -535,17 +550,15 @@ build_flags =
|
|||||||
-I variants/rak4630
|
-I variants/rak4630
|
||||||
-fexceptions
|
-fexceptions
|
||||||
-DBOARD_MODEL=BOARD_RAK4631
|
-DBOARD_MODEL=BOARD_RAK4631
|
||||||
; CBA TEST
|
|
||||||
-DRNS_USE_TLSF=1
|
-DRNS_USE_TLSF=1
|
||||||
-DRNS_USE_ALLOCATOR=1
|
-DRNS_USE_ALLOCATOR=1
|
||||||
;-DUSE_FLASHFS=1
|
|
||||||
build_unflags = -fno-exceptions
|
build_unflags = -fno-exceptions
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash
|
Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash
|
||||||
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|
||||||
[env:heltec_t114_local]
|
[env:heltec_t114_local]
|
||||||
;upload_port = /dev/cu.usbmodem1101
|
|
||||||
platform = nordicnrf52
|
platform = nordicnrf52
|
||||||
board = nrf52840_dk_adafruit
|
board = nrf52840_dk_adafruit
|
||||||
custom_variant = heltec_t114_local
|
custom_variant = heltec_t114_local
|
||||||
@@ -555,11 +568,10 @@ build_flags =
|
|||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
-fexceptions
|
-fexceptions
|
||||||
-DBOARD_MODEL=BOARD_HELTEC_T114
|
-DBOARD_MODEL=BOARD_HELTEC_T114
|
||||||
; CBA TEST
|
|
||||||
-DRNS_USE_TLSF=1
|
-DRNS_USE_TLSF=1
|
||||||
-DRNS_USE_ALLOCATOR=1
|
-DRNS_USE_ALLOCATOR=1
|
||||||
build_unflags = -fno-exceptions
|
build_unflags = -fno-exceptions
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
https://github.com/liamcottle/esp8266-oled-ssd1306#e16cee124fe26490cb14880c679321ad8ac89c95
|
https://github.com/liamcottle/esp8266-oled-ssd1306#e16cee124fe26490cb14880c679321ad8ac89c95
|
||||||
adafruit/Adafruit NeoPixel@^1.12.0
|
adafruit/Adafruit NeoPixel@^1.15.4
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ bool sx126x::preInit() {
|
|||||||
pinMode(_ss, OUTPUT);
|
pinMode(_ss, OUTPUT);
|
||||||
digitalWrite(_ss, HIGH);
|
digitalWrite(_ss, HIGH);
|
||||||
|
|
||||||
#if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_XIAO_S3
|
#if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_XIAO_S3 || BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
SPI.begin(pin_sclk, pin_miso, pin_mosi, pin_cs);
|
SPI.begin(pin_sclk, pin_miso, pin_mosi, pin_cs);
|
||||||
#elif BOARD_MODEL == BOARD_TECHO
|
#elif BOARD_MODEL == BOARD_TECHO
|
||||||
SPI.setPins(pin_miso, pin_sclk, pin_mosi);
|
SPI.setPins(pin_miso, pin_sclk, pin_mosi);
|
||||||
@@ -643,6 +643,8 @@ void sx126x::enableTCXO() {
|
|||||||
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
|
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
|
||||||
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
#elif BOARD_MODEL == BOARD_HELTEC32_V4
|
||||||
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
|
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
|
||||||
|
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3
|
||||||
|
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
|
||||||
#endif
|
#endif
|
||||||
executeOpcode(OP_DIO3_TCXO_CTRL_6X, buf, 4);
|
executeOpcode(OP_DIO3_TCXO_CTRL_6X, buf, 4);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user