Compare commits

...

12 Commits

21 changed files with 447 additions and 3156 deletions

1
.gitignore vendored
View File

@@ -16,3 +16,4 @@ Console/build
build/* build/*
.pio/* .pio/*
.vscode/* .vscode/*
Release/*.bin

View File

@@ -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
@@ -149,6 +151,10 @@
#endif #endif
#endif #endif
#define LORA_PA_UNKNOWN 0x00
#define LORA_PA_GC1109 0x01
#define LORA_PA_KCT8103L 0x02
#define HAS_DISPLAY false #define HAS_DISPLAY false
#define HAS_BLUETOOTH false #define HAS_BLUETOOTH false
#define HAS_BLE false #define HAS_BLE false
@@ -361,7 +367,7 @@
#define HAS_SLEEP true #define HAS_SLEEP true
#define PIN_WAKEUP GPIO_NUM_0 #define PIN_WAKEUP GPIO_NUM_0
#define WAKEUP_LEVEL 0 #define WAKEUP_LEVEL 0
#define OCP_TUNED 0x18 #define OCP_TUNED 0x28
const int pin_btn_usr1 = 0; const int pin_btn_usr1 = 0;
@@ -409,8 +415,9 @@
#define HAS_LORA_LNA true #define HAS_LORA_LNA true
#define PIN_WAKEUP GPIO_NUM_0 #define PIN_WAKEUP GPIO_NUM_0
#define WAKEUP_LEVEL 0 #define WAKEUP_LEVEL 0
#define OCP_TUNED 0x18 #define OCP_TUNED 0x28
#define Vext GPIO_NUM_36 #define Vext GPIO_NUM_36
#define LORA_PA_MODEL LORA_PA_UNKNOWN;
const int pin_btn_usr1 = 0; const int pin_btn_usr1 = 0;
@@ -432,14 +439,17 @@
#define LORA_LNA_GAIN 17 #define LORA_LNA_GAIN 17
#define LORA_LNA_GVT 12 #define LORA_LNA_GVT 12
#define LORA_PA_GC1109 true
#define LORA_PA_PWR_EN 7 #define LORA_PA_PWR_EN 7
#define LORA_PA_CSD 2 #define LORA_PA_CSD 2 // Same pin on GC1109
#define LORA_PA_CPS 46 #define LORA_PA_CPS 46 // Same pin on GC1109
#define LORA_PA_CTX 5 // Only used on KCT8103
#define PA_MAX_OUTPUT 28 #define PA_MAX_OUTPUT 28
#define PA_GAIN_POINTS 22 #define PA_GAIN_POINTS 22
#define PA_GAIN_VALUES 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7
#define LORA_LNA_KCT8103L_GAIN 21
const int PA_GC1109_VALUES[PA_GAIN_POINTS] = {11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7};
const int PA_KCT8103L_VALUES[PA_GAIN_POINTS] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 9, 8, 7};
const int pin_cs = 8; const int pin_cs = 8;
const int pin_busy = 13; const int pin_busy = 13;
@@ -449,6 +459,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
@@ -483,13 +537,10 @@
const int pin_np = 12; const int pin_np = 12;
const int pin_dac = 25; const int pin_dac = 25;
const int pin_adc = 34; const int pin_adc = 34;
// CBA already defined by framework const int SD_MISO = 2;
//const int SD_MISO = 2; const int SD_MOSI = 15;
// CBA already defined by framework
//const int SD_MOSI = 15;
const int SD_CLK = 14; const int SD_CLK = 14;
// CBA already defined by framework const int SD_CS = 13;
//const int SD_CS = 13;
#if HAS_NP == false #if HAS_NP == false
#if defined(EXTERNAL_LEDS) #if defined(EXTERNAL_LEDS)
const int pin_led_rx = 12; const int pin_led_rx = 12;
@@ -934,7 +985,7 @@
// Default OCP value if not specified // Default OCP value if not specified
// in board configuration // in board configuration
#ifndef OCP_TUNED #ifndef OCP_TUNED
#define OCP_TUNED 0x18 #define OCP_TUNED 0x28
#endif #endif
#ifndef PA_MAX_OUTPUT #ifndef PA_MAX_OUTPUT

View File

@@ -105,10 +105,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(

View File

@@ -20,7 +20,7 @@
#define CONFIG_H #define CONFIG_H
#define MAJ_VERS 0x01 #define MAJ_VERS 0x01
#define MIN_VERS 0x55 #define MIN_VERS 0x56
#define MODE_HOST 0x11 #define MODE_HOST 0x11
#define MODE_TNC 0x12 #define MODE_TNC 0x12
@@ -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;

View File

@@ -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 0
#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);

17
Power.h
View File

@@ -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

View File

@@ -363,7 +363,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
@@ -411,7 +411,7 @@ void setup() {
#if MODEM == SX1276 || MODEM == SX1278 #if MODEM == SX1276 || MODEM == SX1278
LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy); LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy);
#elif MODEM == SX1262 #elif MODEM == SX1262
LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen); LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen, pin_txen);
#elif MODEM == SX1280 #elif MODEM == SX1280
LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen, pin_txen); LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen, pin_txen);
#endif #endif
@@ -1586,7 +1586,7 @@ void serial_callback(uint8_t sbyte) {
if (txp > 13) txp = 13; if (txp > 13) txp = 13;
#endif #endif
#else #else
if (txp > 17) txp = 17; if (txp > 20) txp = 20;
#endif #endif
lora_txp = txp; lora_txp = txp;
@@ -2648,7 +2648,13 @@ void sleep_now() {
#if BOARD_MODEL == BOARD_HELTEC32_V4 #if BOARD_MODEL == BOARD_HELTEC32_V4
headless_led_off(); headless_led_off();
headless_led_detach_pwm(); headless_led_detach_pwm();
#if LORA_PA_AUTO_DETECT
if (sx126x_modem.isKCT8103L()) {
digitalWrite(LORA_PA_CTX, LOW);
} else {
digitalWrite(LORA_PA_CPS, LOW); digitalWrite(LORA_PA_CPS, LOW);
}
#endif
digitalWrite(LORA_PA_CSD, LOW); digitalWrite(LORA_PA_CSD, LOW);
digitalWrite(LORA_PA_PWR_EN, LOW); digitalWrite(LORA_PA_PWR_EN, LOW);
digitalWrite(Vext, HIGH); digitalWrite(Vext, HIGH);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -324,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); }
@@ -388,7 +395,7 @@ extern RNS::Reticulum reticulum;
// ── Headless LED indicators (for Heltec V4 without OLED) ───────────────── // ── Headless LED indicators (for Heltec V4 without OLED) ─────────────────
// Uses LEDC PWM for smooth ramp effects on pin_led_tx (GPIO 35) // Uses LEDC PWM for smooth ramp effects on pin_led_tx (GPIO 35)
#if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3 #if BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == MESHADVENTURER_S3
#define HEADLESS_LED_CHANNEL 0 #define HEADLESS_LED_CHANNEL 0
bool headless_led_pwm_attached = false; bool headless_led_pwm_attached = false;
@@ -1376,11 +1383,33 @@ int getTxPower() {
} }
#if HAS_LORA_PA #if HAS_LORA_PA
#if BOARD_MODEL == BOARD_HELTEC32_V4
bool pa_values_determined = false;
int tx_gain[PA_GAIN_POINTS] = {100};
#else
bool pa_values_determined = true;
const int tx_gain[PA_GAIN_POINTS] = {PA_GAIN_VALUES}; const int tx_gain[PA_GAIN_POINTS] = {PA_GAIN_VALUES};
#endif
#endif #endif
extern uint8_t lora_pa_model;
void determine_pa_values() {
#if BOARD_MODEL == BOARD_HELTEC32_V4
if (lora_pa_model == LORA_PA_GC1109) {
for (int i=0; i < PA_GAIN_POINTS; i++) { tx_gain[i] = PA_GC1109_VALUES[i]; }
pa_values_determined = true;
for (int i=0; i < PA_GAIN_POINTS; i++) { Serial.print(" "); Serial.printf("%d", tx_gain[i]); }
} else if (lora_pa_model == LORA_PA_KCT8103L) {
for (int i=0; i < PA_GAIN_POINTS; i++) { tx_gain[i] = PA_KCT8103L_VALUES[i]; }
pa_values_determined = true;
for (int i=0; i < PA_GAIN_POINTS; i++) { Serial.print(" "); Serial.printf("%d", tx_gain[i]); }
}
#endif
}
int map_target_power_to_modem_output(int target_tx_power) { int map_target_power_to_modem_output(int target_tx_power) {
#if HAS_LORA_PA #if HAS_LORA_PA
if (!pa_values_determined) { determine_pa_values(); }
int modem_output_dbm = -9; int modem_output_dbm = -9;
for (int i = 0; i < PA_GAIN_POINTS; i++) { for (int i = 0; i < PA_GAIN_POINTS; i++) {
int gain = tx_gain[i]; int gain = tx_gain[i];
@@ -1773,6 +1802,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

View File

@@ -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"):

216
flash.py
View File

@@ -7,19 +7,12 @@ No PlatformIO required — just Python 3 and a USB cable.
By default, downloads the latest firmware from GitHub Releases (if newer than By default, downloads the latest firmware from GitHub Releases (if newer than
the local cache) and flashes the app partition only, preserving bootloader, the local cache) and flashes the app partition only, preserving bootloader,
partition table, NVS, and EEPROM settings. For reproducible flashing, the partition table, NVS, and EEPROM settings.
script prefers the bundled esptool in Release/ over any host-installed copy.
Usage: Usage:
# Update firmware — V4 (default) # Update firmware — V4 (default)
python flash.py python flash.py
# Legacy alias for an app-only update flow
python flash.py --update
# Use a host-installed esptool instead of the bundled copy
python flash.py --use-system-esptool
# Update firmware — V3 # Update firmware — V3
python flash.py --board v3 python flash.py --board v3
@@ -62,7 +55,6 @@ GITHUB_REPO = "jrl290/RTNode-HeltecV4"
# Runtime state (set automatically during main()) # Runtime state (set automatically during main())
_flash_mode_override = None # CLI --flash-mode sets this; otherwise board profile wins _flash_mode_override = None # CLI --flash-mode sets this; otherwise board profile wins
_esptool_write_verify_support = {}
# Flash addresses for ESP32-S3 Arduino framework # Flash addresses for ESP32-S3 Arduino framework
BOOTLOADER_ADDR = 0x0000 BOOTLOADER_ADDR = 0x0000
@@ -324,13 +316,25 @@ def detect_board(port, esptool_cmd):
# ── Helpers ──────────────────────────────────────────────────────────────────── # ── Helpers ────────────────────────────────────────────────────────────────────
def find_esptool(prefer_system=False): def find_esptool():
"""Find esptool, preferring repo-managed copies for reproducible flashing. """Find esptool — pip-installed, user-local, bundled, or PlatformIO's copy.
Default order is bundled Release/ copy, then PlatformIO's packaged copy, Prefer pip/pipx-installed esptool first (handles its own deps and is
then any host-installed esptool. Pass ``prefer_system=True`` to invert that usually the newest version), then fall back to the bundled script.
preference when a user explicitly wants their machine-wide installation.
""" """
# 1. pip-installed esptool on PATH
if shutil.which("esptool"):
return ["esptool"]
# 2. Common user-local install locations (pip install --user)
for candidate in [
os.path.expanduser("~/.local/bin/esptool"),
os.path.expanduser("~/.local/bin/esptool.py"),
]:
if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
print(f" Found user-local esptool: {candidate}")
return [candidate]
# Check if pyserial is available before using script-based esptool # Check if pyserial is available before using script-based esptool
try: try:
import serial # noqa: F401 import serial # noqa: F401
@@ -338,36 +342,20 @@ def find_esptool(prefer_system=False):
except ImportError: except ImportError:
has_pyserial = False has_pyserial = False
# 2. Bundled in Release/
bundled = os.path.join(os.path.dirname(__file__), "Release", "esptool", "esptool.py") bundled = os.path.join(os.path.dirname(__file__), "Release", "esptool", "esptool.py")
if os.path.isfile(bundled) and has_pyserial:
return [sys.executable, bundled]
# 3. PlatformIO's esptool
pio_esptool = os.path.expanduser( pio_esptool = os.path.expanduser(
"~/.platformio/packages/tool-esptoolpy/esptool.py" "~/.platformio/packages/tool-esptoolpy/esptool.py"
) )
if os.path.isfile(pio_esptool) and has_pyserial:
return [sys.executable, pio_esptool]
repo_candidates = [] # 4. Bundled exists but pyserial is missing — tell the user
if has_pyserial: if os.path.isfile(bundled) and not has_pyserial:
if os.path.isfile(bundled):
repo_candidates.append(([sys.executable, bundled], f"bundled esptool: {bundled}"))
if os.path.isfile(pio_esptool):
repo_candidates.append(([sys.executable, pio_esptool], f"PlatformIO esptool: {pio_esptool}"))
system_candidates = []
if shutil.which("esptool.py"):
system_candidates.append((["esptool.py"], "system esptool.py from PATH"))
if shutil.which("esptool"):
system_candidates.append((["esptool"], "system esptool from PATH"))
for candidate in [
os.path.expanduser("~/.local/bin/esptool"),
os.path.expanduser("~/.local/bin/esptool.py"),
]:
if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
system_candidates.append(([candidate], f"user-local esptool: {candidate}"))
search_order = system_candidates + repo_candidates if prefer_system else repo_candidates + system_candidates
for command, source in search_order:
print(f" Found {source}")
return command
if (os.path.isfile(bundled) or os.path.isfile(pio_esptool)) and not has_pyserial:
print("Found bundled esptool but pyserial is not installed.") print("Found bundled esptool but pyserial is not installed.")
print("Install it with: pip install pyserial") print("Install it with: pip install pyserial")
print("Or install the standalone esptool: pip install esptool") print("Or install the standalone esptool: pip install esptool")
@@ -376,33 +364,6 @@ def find_esptool(prefer_system=False):
return None return None
def esptool_supports_write_verify(esptool_cmd):
"""Return True if this esptool build accepts ``write_flash --verify``.
esptool v5 removed ``--verify`` from write-flash, while older releases
still accept it. Probe once and cache the result so flashing can choose
the compatible verification path.
"""
cache_key = tuple(esptool_cmd)
if cache_key in _esptool_write_verify_support:
return _esptool_write_verify_support[cache_key]
try:
result = subprocess.run(
esptool_cmd + ["write_flash", "-h"],
capture_output=True,
text=True,
timeout=10,
)
output = (result.stdout or "") + (result.stderr or "")
supported = "--verify" in output
except Exception:
supported = False
_esptool_write_verify_support[cache_key] = supported
return supported
def find_serial_port(): def find_serial_port():
"""List available serial ports and let the user choose.""" """List available serial ports and let the user choose."""
system = platform.system() system = platform.system()
@@ -750,7 +711,7 @@ def check_partition_table(port, esptool_cmd, baud=None):
Returns: Returns:
True — partition table matches (or no expected table to compare against) True — partition table matches (or no expected table to compare against)
False — partition table mismatch or unreadable state (device needs full flash) False — partition table mismatch (device needs full flash)
""" """
expected_path = find_partitions() expected_path = find_partitions()
if not expected_path: if not expected_path:
@@ -764,7 +725,8 @@ def check_partition_table(port, esptool_cmd, baud=None):
device_data = read_device_partitions(port, esptool_cmd, baud) device_data = read_device_partitions(port, esptool_cmd, baud)
if device_data is None: if device_data is None:
print(" Could not read partition table from device") print(" Could not read partition table from device")
return False # Can't verify — assume OK (user can always use --full)
return True
# Compare only the meaningful portion (both should be PARTITION_TABLE_SIZE) # Compare only the meaningful portion (both should be PARTITION_TABLE_SIZE)
if device_data[:len(expected)] == expected: if device_data[:len(expected)] == expected:
@@ -786,7 +748,7 @@ def check_app_on_device(port, esptool_cmd, baud=None):
Reads a small chunk from APP_ADDR (0x10000). If the region is all 0xFF Reads a small chunk from APP_ADDR (0x10000). If the region is all 0xFF
(erased flash), no app is present and the device needs a full flash. (erased flash), no app is present and the device needs a full flash.
Returns True if app firmware is detected, False if blank/absent or unreadable. Returns True if app firmware is detected, False if blank/absent.
""" """
import tempfile import tempfile
if baud is None: if baud is None:
@@ -808,7 +770,7 @@ def check_app_on_device(port, esptool_cmd, baud=None):
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0: if result.returncode != 0:
print(" Warning: Could not read app region from device") print(" Warning: Could not read app region from device")
return False return True # assume app exists if we can't check
with open(tmp.name, "rb") as f: with open(tmp.name, "rb") as f:
data = f.read() data = f.read()
# All 0xFF means flash is blank — no app present # All 0xFF means flash is blank — no app present
@@ -817,7 +779,7 @@ def check_app_on_device(port, esptool_cmd, baud=None):
return True return True
except Exception as e: except Exception as e:
print(f" Warning: App check failed: {e}") print(f" Warning: App check failed: {e}")
return False return True # assume app exists if we can't check
finally: finally:
try: try:
os.unlink(tmp.name) os.unlink(tmp.name)
@@ -858,37 +820,6 @@ def reset_to_bootloader(port):
return True return True
def verify_firmware(firmware_path, port, esptool_cmd, baud=None,
flash_mode=None, no_hard_reset=False):
"""Verify flashed firmware using esptool's dedicated verify command."""
if baud is None:
baud = BAUD_RATE()
flash_size = FLASH_SIZE()
mode = flash_mode or BOARD_FLASH_MODE()
is_merged = is_merged_binary(firmware_path)
flash_addr = f"0x{BOOTLOADER_ADDR:x}" if is_merged else f"0x{APP_ADDR:x}"
after_arg = "no_reset" if no_hard_reset else "hard_reset"
print("\nVerifying flashed firmware...")
cmd = esptool_cmd + [
"--chip", CHIP,
"--port", port,
"--baud", baud,
"--before", "no_reset",
"--after", after_arg,
"verify_flash",
"--flash_mode", mode,
"--flash_freq", FLASH_FREQ,
"--flash_size", flash_size,
flash_addr, firmware_path,
]
print("Running: " + " ".join(cmd[-8:]))
result = subprocess.run(cmd)
return result.returncode == 0
def flash_firmware(firmware_path, port, esptool_cmd, baud=None, def flash_firmware(firmware_path, port, esptool_cmd, baud=None,
no_reset_before=False, verify=False, no_reset_before=False, verify=False,
flash_mode=None, no_hard_reset=False): flash_mode=None, no_hard_reset=False):
@@ -918,10 +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}")
inline_verify = verify and esptool_supports_write_verify(esptool_cmd) before_arg = "no_reset" if no_reset_before else "default-reset"
post_write_verify = verify and not inline_verify after_arg = "no_reset" if no_hard_reset else "hard-reset"
before_arg = "no_reset" if no_reset_before else "default_reset"
after_arg = "no_reset" if (no_hard_reset or post_write_verify) else "hard_reset"
cmd = esptool_cmd + [ cmd = esptool_cmd + [
"--chip", CHIP, "--chip", CHIP,
@@ -929,32 +858,19 @@ 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 inline_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:]))
result = subprocess.run(cmd) result = subprocess.run(cmd)
if result.returncode != 0: return result.returncode == 0
return False
if post_write_verify:
return verify_firmware(
firmware_path,
port,
esptool_cmd,
baud=baud,
flash_mode=mode,
no_hard_reset=no_hard_reset,
)
return True
def _monitor_boot(port, timeout=8): def _monitor_boot(port, timeout=8):
@@ -1019,28 +935,15 @@ def main():
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=""" epilog="""
Examples: Examples:
python flash.py python flash.py # Download latest & app-only update (V4)
Download latest firmware and flash default board. python flash.py --board v3 # Download latest & app-only update (V3)
python flash.py --update python flash.py --release v1.0.12 # Flash a specific release version
Legacy alias for an app-only update. python flash.py --full # Full flash with merged binary
python flash.py --use-system-esptool python flash.py --offline # Use cached/local firmware only
Prefer a host-installed esptool over the bundled Release copy. python flash.py --file firmware.bin # Flash a specific file
python flash.py --board v3 python flash.py --merge-only # Build merged binary for release
Download latest firmware and flash a V3 board. python flash.py --port /dev/ttyACM0 # Specify serial port
python flash.py --release v1.0.12 python flash.py --erase # Erase flash, then full flash (auto-verify)
Flash a specific release tag.
python flash.py --full
Do a full flash with the merged binary.
python flash.py --offline
Use only cached or local firmware.
python flash.py --file firmware.bin
Flash a specific local binary.
python flash.py --merge-only
Build the merged release binary without flashing.
python flash.py --port /dev/ttyACM0
Use a specific serial port.
python flash.py --erase
Erase flash first, then do a full flash.
""", """,
) )
parser.add_argument("--board", choices=["v3", "v4"], default=None, parser.add_argument("--board", choices=["v3", "v4"], default=None,
@@ -1051,8 +954,6 @@ Examples:
parser.add_argument("--baud", "-b", default=None, help="Baud rate (board-specific default)") parser.add_argument("--baud", "-b", default=None, help="Baud rate (board-specific default)")
parser.add_argument("--release", "-r", default=None, metavar="TAG", parser.add_argument("--release", "-r", default=None, metavar="TAG",
help="Flash a specific release version (e.g. v1.0.12)") help="Flash a specific release version (e.g. v1.0.12)")
parser.add_argument("--update", action="store_true",
help="Legacy alias for an app-only firmware update")
parser.add_argument("--offline", action="store_true", parser.add_argument("--offline", action="store_true",
help="Skip online check — use cached or local firmware only") help="Skip online check — use cached or local firmware only")
parser.add_argument("--merge-only", action="store_true", parser.add_argument("--merge-only", action="store_true",
@@ -1061,28 +962,17 @@ Examples:
help="Flash merged binary (bootloader + partitions + app) — overwrites everything") help="Flash merged binary (bootloader + partitions + app) — overwrites everything")
parser.add_argument("--erase", action="store_true", parser.add_argument("--erase", action="store_true",
help="Erase entire flash before writing (implies --full)") help="Erase entire flash before writing (implies --full)")
parser.add_argument("--use-system-esptool", action="store_true",
help="Use a host-installed esptool instead of the bundled Release copy")
# Power-user override (not shown in --help) # Power-user override (not shown in --help)
parser.add_argument("--flash-mode", default=None, parser.add_argument("--flash-mode", default=None,
help=argparse.SUPPRESS) help=argparse.SUPPRESS)
args = parser.parse_args() args = parser.parse_args()
if args.update and args.offline:
parser.error("--update cannot be combined with --offline")
if args.update:
print("Using legacy compatibility flag; default behavior already downloads and flashes the latest firmware unless --offline is set.")
# Find esptool early — needed for both auto-detect and flashing # Find esptool early — needed for both auto-detect and flashing
esptool_cmd = find_esptool(prefer_system=args.use_system_esptool) esptool_cmd = find_esptool()
if not esptool_cmd: if not esptool_cmd:
print("Error: esptool not found!") print("Error: esptool not found!")
print("Expected one of:") print("Install it with: pip install esptool")
print(" 1. Bundled Release/esptool/esptool.py with pyserial available")
print(" 2. PlatformIO's packaged esptool")
print(" 3. A host-installed esptool (pip install esptool)")
sys.exit(1) sys.exit(1)
# ── Board detection ───────────────────────────────────────────────── # ── Board detection ─────────────────────────────────────────────────

0
lib/microReticulum/library.properties Normal file → Executable file
View File

View File

@@ -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,37 +18,23 @@ 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
[env:rnode-ng-20] [env:rnode-ng-20]
platform = espressif32 platform = espressif32@6.12.0
board = ttgo-lora32-v2 board = ttgo-lora32-v2
custom_variant = ng20 custom_variant = ng20
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -60,10 +45,10 @@ 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@6.12.0
board = ttgo-lora32-v21 board = ttgo-lora32-v21
custom_variant = ng21 custom_variant = ng21
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -74,10 +59,10 @@ 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@6.12.0
board = ttgo-t-beam board = ttgo-t-beam
custom_variant = tbeam custom_variant = tbeam
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -88,9 +73,10 @@ 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@6.12.0
board = ttgo-t-beam board = ttgo-t-beam
custom_variant = tbeam_sx1262 custom_variant = tbeam_sx1262
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -102,9 +88,10 @@ 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@6.12.0
board = ttgo-t-beam board = ttgo-t-beam
custom_variant = tbeam_supreme custom_variant = tbeam_supreme
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -118,9 +105,10 @@ 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@6.12.0
board = lilygo-t3-s3 board = lilygo-t3-s3
custom_variant = t3s3 custom_variant = t3s3
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -132,9 +120,10 @@ 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@6.12.0
board = lilygo-t3-s3 board = lilygo-t3-s3
custom_variant = t3s3_sx127x custom_variant = t3s3_sx127x
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -146,9 +135,10 @@ 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@6.12.0
board = lilygo-t3-s3 board = lilygo-t3-s3
custom_variant = t3s3_sx1280_pa custom_variant = t3s3_sx1280_pa
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -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@6.12.0
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,16 +169,14 @@ 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@6.12.0
board = ttgo-lora32-v1 board = ttgo-lora32-v1
custom_variant = lora32v10 custom_variant = lora32v10
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -200,9 +187,10 @@ 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@6.12.0
board = ttgo-lora32-v2 board = ttgo-lora32-v2
custom_variant = lora32v20 custom_variant = lora32v20
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -213,9 +201,10 @@ 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@6.12.0
board = ttgo-lora32-v2 board = ttgo-lora32-v2
custom_variant = lora32v20_extled custom_variant = lora32v20_extled
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -227,9 +216,10 @@ 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@6.12.0
board = ttgo-lora32-v21 board = ttgo-lora32-v21
custom_variant = lora32v21 custom_variant = lora32v21
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -240,9 +230,10 @@ 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@6.12.0
board = ttgo-lora32-v21 board = ttgo-lora32-v21
custom_variant = lora32v21_extled custom_variant = lora32v21_extled
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -254,9 +245,10 @@ 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@6.12.0
board = ttgo-lora32-v21 board = ttgo-lora32-v21
custom_variant = lora32v21_extled custom_variant = lora32v21_extled
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -268,9 +260,10 @@ 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@6.12.0
board = heltec_wifi_lora_32_V2 board = heltec_wifi_lora_32_V2
custom_variant = heltec32v2 custom_variant = heltec32v2
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -281,9 +274,10 @@ 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@6.12.0
board = heltec_wifi_lora_32_V2 board = heltec_wifi_lora_32_V2
custom_variant = heltec32v2_extled custom_variant = heltec32v2_extled
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -295,9 +289,10 @@ 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@6.12.0
board = heltec_wifi_lora_32_V3 board = heltec_wifi_lora_32_V3
custom_variant = heltec32v3 custom_variant = heltec32v3
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -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@6.12.0
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,21 +322,18 @@ 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]
platform = espressif32 platform = espressif32@6.12.0
board = esp32-s3-devkitc-1 board = esp32-s3-devkitc-1
custom_variant = heltec32v4 custom_variant = heltec32v4
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -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@6.12.0
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@6.12.0
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,24 +393,18 @@ 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]
platform = espressif32 platform = espressif32@6.12.0
board = esp32-s3-devkitc-1 board = esp32-s3-devkitc-1
custom_variant = heltec32v4_boundary_local custom_variant = heltec32v4_boundary_local
board_build.filesystem = littlefs board_build.filesystem = littlefs
@@ -414,10 +425,11 @@ 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]
platform = espressif32 platform = espressif32@6.12.0
board = featheresp32 board = featheresp32
custom_variant = featheresp32 custom_variant = featheresp32
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -428,9 +440,10 @@ 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@6.12.0
board = seeed_xiao_esp32s3 board = seeed_xiao_esp32s3
custom_variant = xiao_esp32s3 custom_variant = xiao_esp32s3
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -441,9 +454,10 @@ 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@6.12.0
board = esp32dev board = esp32dev
custom_variant = esp32_generic custom_variant = esp32_generic
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -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,11 +486,10 @@ 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@6.12.0
board = ttgo-t-beam board = ttgo-t-beam
upload_speed = 460800 upload_speed = 460800
custom_variant = tbeam_local custom_variant = tbeam_local
@@ -485,16 +499,15 @@ 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]
platform = espressif32 platform = espressif32@6.12.0
board = ttgo-lora32-v21 board = ttgo-lora32-v21
upload_speed = 460800 upload_speed = 460800
custom_variant = lora32v21_local custom_variant = lora32v21_local
@@ -506,10 +519,11 @@ 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]
platform = espressif32 platform = espressif32@6.12.0
board = esp32-s3-devkitc-1 board = esp32-s3-devkitc-1
custom_variant = heltec32v4_local custom_variant = heltec32v4_local
board_build.partitions = no_ota.csv board_build.partitions = no_ota.csv
@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -96,13 +96,21 @@
#define SPI spiModem #define SPI spiModem
#endif #endif
#if HAS_LORA_PA
uint8_t lora_pa_model = LORA_PA_MODEL;
#endif
#if HAS_LORA_LNA
int lora_lna_gain = LORA_LNA_GAIN;
#endif
extern SPIClass SPI; extern SPIClass SPI;
#define MAX_PKT_LENGTH 255 #define MAX_PKT_LENGTH 255
sx126x::sx126x() : sx126x::sx126x() :
_spiSettings(16E6, MSBFIRST, SPI_MODE0), _spiSettings(16E6, MSBFIRST, SPI_MODE0),
_ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _busy(LORA_DEFAULT_BUSY_PIN), _rxen(LORA_DEFAULT_RXEN_PIN), _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _busy(LORA_DEFAULT_BUSY_PIN), _rxen(LORA_DEFAULT_RXEN_PIN), _txen(LORA_DEFAULT_TXEN_PIN),
_frequency(0), _frequency(0),
_txp(0), _txp(0),
_sf(0x07), _sf(0x07),
@@ -126,7 +134,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);
@@ -184,6 +192,7 @@ uint8_t ISR_VECT sx126x::singleTransfer(uint8_t opcode, uint16_t address, uint8_
void sx126x::rxAntEnable() { void sx126x::rxAntEnable() {
if (_rxen != -1) { digitalWrite(_rxen, HIGH); } if (_rxen != -1) { digitalWrite(_rxen, HIGH); }
if (_txen != -1) { digitalWrite(_txen, LOW); }
} }
void sx126x::loraMode() { void sx126x::loraMode() {
@@ -274,6 +283,21 @@ void sx126x::setPacketParams(long preamble_symbols, uint8_t headermode, uint8_t
buf[7] = 0x00; buf[7] = 0x00;
buf[8] = 0x00; buf[8] = 0x00;
executeOpcode(OP_PACKET_PARAMS_6X, buf, 9); executeOpcode(OP_PACKET_PARAMS_6X, buf, 9);
// SX1262 errata section 15.4: IQ polarity is inverted compared to
// SX1276. The SetPacketParams command resets register 0x0736 to an
// incorrect default. For standard IQ (no inversion), bit 2 must be
// SET after every SetPacketParams call. For inverted IQ, bit 2 must
// be CLEARED. Without this fix, LoRa RX demodulation fails silently
// while TX continues to work.
uint8_t iqreg = readRegister(0x0736);
if (buf[5] == 0x00) {
// Standard IQ: set bit 2
writeRegister(0x0736, iqreg | 0x04);
} else {
// Inverted IQ: clear bit 2
writeRegister(0x0736, iqreg & ~0x04);
}
} }
void sx126x::reset(void) { void sx126x::reset(void) {
@@ -286,6 +310,22 @@ void sx126x::reset(void) {
} }
} }
void sx126x::setDCDCRegulator(void) {
// Documentation
// 5. Power Distribution -> 5.1 Selecting DC-DC Converter or LDO Regulation
// 13.1.11 SetRegulatorMode
uint8_t mode_byte = MODE_STDBY_RC_6X;
executeOpcode(OP_STANDBY_6X, &mode_byte, 1);
// Enable DC-DC regulator for high power operation
uint8_t reg_mode = 0x01; // 0x00 = LDO, 0x01 = DC-DC
executeOpcode(OP_REGULATOR_MODE_6X, &reg_mode, 1);
delay(5);
waitOnBusy();
}
void sx126x::calibrate(void) { void sx126x::calibrate(void) {
// Put in STDBY_RC mode before calibration // Put in STDBY_RC mode before calibration
uint8_t mode_byte = MODE_STDBY_RC_6X; uint8_t mode_byte = MODE_STDBY_RC_6X;
@@ -316,10 +356,21 @@ int sx126x::begin(long frequency) {
if (_busy != -1) { pinMode(_busy, INPUT); } if (_busy != -1) { pinMode(_busy, INPUT); }
if (!_preinit_done) { if (!preInit()) { return false; } } if (!_preinit_done) { if (!preInit()) { return false; } }
if (_rxen != -1) { pinMode(_rxen, OUTPUT); } if (_rxen != -1) { pinMode(_rxen, OUTPUT); }
if (_txen != -1) { pinMode(_txen, OUTPUT); }
//TODO: if it works, make it optional
//#ifdef SX1262_USE_DCDC_REGULATOR
setDCDCRegulator();
//#endif
calibrate(); calibrate();
calibrate_image(frequency); calibrate_image(frequency);
#if HAS_TCXO
enableTCXO(); enableTCXO();
//13.1.15 SetRxTxFallbackMode to STDBY_XOSC
uint8_t fallback_mode = 0x30; // STDBY_XOSC after TX/RX
executeOpcode(OP_RX_TX_FALLBACK_MODE_6X, &fallback_mode, 1);
#endif
loraMode(); loraMode();
standby(); standby();
@@ -336,7 +387,9 @@ int sx126x::begin(long frequency) {
setFrequency(frequency); setFrequency(frequency);
setTxPower(2); setTxPower(2);
enableCrc(); enableCrc();
writeRegister(REG_LNA_6X, 0x96); // Set LNA boost writeRegister(REG_LNA_6X, 0x96); // Set LNA boosted gain mode
// Undocumented SX1262 register patch recommended by Heltec/Semtech for improved RX sensitivity.
writeRegister(0x08B5, readRegister(0x08B5) | 0x01);
uint8_t basebuf[2] = {0}; // Set base addresses uint8_t basebuf[2] = {0}; // Set base addresses
executeOpcode(OP_BUFFER_BASE_ADDR_6X, basebuf, 2); executeOpcode(OP_BUFFER_BASE_ADDR_6X, basebuf, 2);
@@ -344,7 +397,22 @@ int sx126x::begin(long frequency) {
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
#if HAS_LORA_PA #if HAS_LORA_PA
#if LORA_PA_GC1109 if (lora_pa_model == LORA_PA_UNKNOWN) {
#if BOARD_MODEL == BOARD_HELTEC32_V4
pinMode(LORA_PA_PWR_EN, OUTPUT);
pinMode(LORA_PA_CSD, INPUT);
digitalWrite(LORA_PA_PWR_EN, HIGH); delay(5);
if (digitalRead(LORA_PA_CSD) == HIGH) {
lora_pa_model = LORA_PA_KCT8103L;
lora_lna_gain = LORA_LNA_KCT8103L_GAIN;
} else {
lora_pa_model = LORA_PA_GC1109;
}
#endif
}
if (lora_pa_model == LORA_PA_GC1109) {
// Enable Vfem_ctl for supply to // Enable Vfem_ctl for supply to
// PA power net. // PA power net.
pinMode(LORA_PA_PWR_EN, OUTPUT); pinMode(LORA_PA_PWR_EN, OUTPUT);
@@ -369,7 +437,26 @@ int sx126x::begin(long frequency) {
// is driven by the SX1262 DIO2 // is driven by the SX1262 DIO2
// pin directly, so we do not // pin directly, so we do not
// need to manually raise this. // need to manually raise this.
#endif
} else if (lora_pa_model == LORA_PA_KCT8103L) {
// Enable Vfem_ctl for supply to
// PA power net.
pinMode(LORA_PA_PWR_EN, OUTPUT);
digitalWrite(LORA_PA_PWR_EN, HIGH);
// Enable KCT8103L chip
pinMode(LORA_PA_CSD, OUTPUT);
digitalWrite(LORA_PA_CSD, HIGH);
// Enable receive LNA
pinMode(LORA_PA_CTX, OUTPUT);
digitalWrite(LORA_PA_CTX, LOW);
// On Heltec V4.3, the PA CPS pin
// is driven by the SX1262 DIO2
// pin directly, so we do not
// need to manually raise this.
}
#endif #endif
return 1; return 1;
@@ -379,14 +466,18 @@ void sx126x::end() { sleep(); SPI.end(); _preinit_done = false; }
int sx126x::beginPacket(int implicitHeader) { int sx126x::beginPacket(int implicitHeader) {
#if HAS_LORA_PA #if HAS_LORA_PA
#if LORA_PA_GC1109 if (lora_pa_model == LORA_PA_GC1109) {
// Enable PA CPS for transmit // Enable PA CPS for transmit
// digitalWrite(LORA_PA_CPS, HIGH); // digitalWrite(LORA_PA_CPS, HIGH);
// Disabled since we're keeping it // Disabled since we're keeping it
// on permanently as long as the // on permanently as long as the
// radio is powered up. // radio is powered up.
} else if (lora_pa_model == LORA_PA_KCT8103L) {
digitalWrite(LORA_PA_CTX, HIGH);
}
#endif #endif
#endif
if (_txen != -1) { digitalWrite(_txen, HIGH); } //Set TXen high when transmitting
standby(); standby();
if (implicitHeader) { implicitHeaderMode(); } if (implicitHeader) { implicitHeaderMode(); }
@@ -401,6 +492,9 @@ int sx126x::beginPacket(int implicitHeader) {
int sx126x::endPacket() { int sx126x::endPacket() {
setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
if (_rxen != -1) { digitalWrite(_rxen, LOW); } //Set RXen low when transmitting
uint8_t timeout[3] = {0}; // Put in single TX mode uint8_t timeout[3] = {0}; // Put in single TX mode
executeOpcode(OP_TX_6X, timeout, 3); executeOpcode(OP_TX_6X, timeout, 3);
@@ -473,7 +567,7 @@ int ISR_VECT sx126x::currentRssi() {
executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1);
int rssi = -(int(byte)) / 2; int rssi = -(int(byte)) / 2;
#if HAS_LORA_LNA #if HAS_LORA_LNA
rssi -= LORA_LNA_GAIN; rssi -= lora_lna_gain;
#endif #endif
return rssi; return rssi;
} }
@@ -489,7 +583,7 @@ int ISR_VECT sx126x::packetRssi() {
executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
int pkt_rssi = -buf[0] / 2; int pkt_rssi = -buf[0] / 2;
#if HAS_LORA_LNA #if HAS_LORA_LNA
pkt_rssi -= LORA_LNA_GAIN; pkt_rssi -= lora_lna_gain;
#endif #endif
return pkt_rssi; return pkt_rssi;
} }
@@ -596,7 +690,7 @@ void sx126x::onReceive(void(*callback)(int)){
void sx126x::receive(int size) { void sx126x::receive(int size) {
#if HAS_LORA_PA #if HAS_LORA_PA
#if LORA_PA_GC1109 if (lora_pa_model == LORA_PA_GC1109) {
// Disable PA CPS for receive // Disable PA CPS for receive
// digitalWrite(LORA_PA_CPS, LOW); // digitalWrite(LORA_PA_CPS, LOW);
// That turned out to be a bad idea. // That turned out to be a bad idea.
@@ -604,7 +698,9 @@ void sx126x::receive(int size) {
// on and off too quickly. We'll keep // on and off too quickly. We'll keep
// it on permanently, as long as the // it on permanently, as long as the
// radio is powered up. // radio is powered up.
#endif } else if (lora_pa_model == LORA_PA_KCT8103L) {
digitalWrite(LORA_PA_CTX, LOW);
}
#endif #endif
if (size > 0) { if (size > 0) {
@@ -643,6 +739,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
@@ -770,12 +868,13 @@ void sx126x::setSyncWord(uint16_t sw) {
writeRegister(REG_SYNC_WORD_LSB_6X, 0x24); writeRegister(REG_SYNC_WORD_LSB_6X, 0x24);
} }
void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen) { void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen, int txen) {
_ss = ss; _ss = ss;
_reset = reset; _reset = reset;
_dio0 = dio0; _dio0 = dio0;
_busy = busy; _busy = busy;
_rxen = rxen; _rxen = rxen;
_txen = txen;
} }
void sx126x::dumpRegisters(Stream& out) { void sx126x::dumpRegisters(Stream& out) {

View File

@@ -74,6 +74,7 @@ public:
void disableCrc(); void disableCrc();
void enableTCXO(); void enableTCXO();
void disableTCXO(); void disableTCXO();
void setDCDCRegulator();
void rxAntEnable(); void rxAntEnable();
void loraMode(); void loraMode();
@@ -92,11 +93,13 @@ public:
byte random(); byte random();
void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int busy = LORA_DEFAULT_BUSY_PIN, int rxen = LORA_DEFAULT_RXEN_PIN); void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int busy = LORA_DEFAULT_BUSY_PIN, int rxen = LORA_DEFAULT_RXEN_PIN, int txen = LORA_DEFAULT_TXEN_PIN);
void setSPIFrequency(uint32_t frequency); void setSPIFrequency(uint32_t frequency);
void dumpRegisters(Stream& out); void dumpRegisters(Stream& out);
bool isKCT8103L() { return _kct8103l; }
private: private:
void explicitHeaderMode(); void explicitHeaderMode();
void implicitHeaderMode(); void implicitHeaderMode();
@@ -107,7 +110,8 @@ public:
// Poll for deferred DIO0 interrupt (call from main loop) // Poll for deferred DIO0 interrupt (call from main loop)
void pollDio0(); void pollDio0();
private: uint8_t readRegister(uint16_t address); private:
uint8_t readRegister(uint16_t address);
void writeRegister(uint16_t address, uint8_t value); void writeRegister(uint16_t address, uint8_t value);
uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value); uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
@@ -125,6 +129,7 @@ private:
int _reset; int _reset;
int _dio0; int _dio0;
int _rxen; int _rxen;
int _txen;
int _busy; int _busy;
long _frequency; long _frequency;
int _txp; int _txp;
@@ -141,6 +146,7 @@ private:
int _fifo_rx_addr_ptr; int _fifo_rx_addr_ptr;
uint8_t _packet[255]; uint8_t _packet[255];
bool _preinit_done; bool _preinit_done;
bool _kct8103l;
volatile bool _dio0_risen; volatile bool _dio0_risen;
void (*_onReceive)(int); void (*_onReceive)(int);
}; };