diff --git a/Boards.h b/Boards.h index 22bb28d..462eefd 100755 --- a/Boards.h +++ b/Boards.h @@ -122,6 +122,8 @@ #define MODEL_FE 0xFE // Homebrew board, max 17dBm output power #define MODEL_FF 0xFF // Homebrew board, max 14dBm output power + #define BOARD_MESHADVENTURER_S3 0xF2 + #if defined(__AVR_ATmega1284P__) #define PLATFORM PLATFORM_AVR #define MCU_VARIANT MCU_1284P @@ -449,6 +451,50 @@ const int pin_miso = 11; 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 #define HAS_DISPLAY true #define HAS_BLUETOOTH true diff --git a/BoundaryConfig.h b/BoundaryConfig.h index 2b0bca4..19cd4f8 100755 --- a/BoundaryConfig.h +++ b/BoundaryConfig.h @@ -100,10 +100,10 @@ static void config_send_html() { if (cur_txp == 0xFF) cur_txp = PA_MAX_OUTPUT; // Default to board max // 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_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 String html = F( diff --git a/Config.h b/Config.h index 29ff2a0..1d4bd5f 100755 --- a/Config.h +++ b/Config.h @@ -114,7 +114,14 @@ #define CSMA_CW_PER_BAND_WINDOWS 15 #define CSMA_BAND_1_MAX_AIRTIME 7 #define CSMA_BAND_N_MIN_AIRTIME 85 - #define CSMA_INFR_THRESHOLD_DB 11 + + // Increase threshold for specific boards + #if BOARD_MODEL == BOARD_MESHADVENTURER_S3 + #define CSMA_INFR_THRESHOLD_DB 14 + #else + #define CSMA_INFR_THRESHOLD_DB 11 + #endif + #define CSMA_RFENV_RECAL_MS 2500 #define CSMA_RFENV_RECAL_LIMIT_DB -83 bool interference_detected = false; diff --git a/Display.h b/Display.h index 729876e..61e368a 100755 --- a/Display.h +++ b/Display.h @@ -97,6 +97,11 @@ extern BoundaryState boundary_state; #define DISP_ADDR 0x3C #define SCL_OLED 18 #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 // RAK1921/SSD1306 #define DISP_RST -1 @@ -334,6 +339,8 @@ bool display_init() { digitalWrite(pin_display_en, HIGH); delay(50); 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 int pin_display_en = 16; digitalWrite(pin_display_en, LOW); @@ -455,6 +462,9 @@ bool display_init() { #elif BOARD_MODEL == BOARD_HELTEC32_V4 disp_mode = DISP_MODE_PORTRAIT; display.setRotation(1); + #elif BOARD_MODEL == BOARD_MESHADVENTURER_S3 + disp_mode = DISP_MODE_LANDSCAPE; + display.setRotation(0); #elif BOARD_MODEL == BOARD_HELTEC_T114 disp_mode = DISP_MODE_PORTRAIT; display.setRotation(1); diff --git a/Power.h b/Power.h index 7ce6d8a..f4f463d 100755 --- a/Power.h +++ b/Power.h @@ -147,6 +147,23 @@ float pmu_temperature = PMU_TEMP_MIN-1; bool bat_voltage_dropping = false; float bat_delay_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 #define BAT_V_MIN 3.15 #define BAT_V_MAX 4.165 diff --git a/RNode_Firmware.ino b/RNode_Firmware.ino index 00ec5f4..42bbd43 100755 --- a/RNode_Firmware.ino +++ b/RNode_Firmware.ino @@ -356,7 +356,7 @@ void setup() { boot_seq(); #endif - #if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && 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 // 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 diff --git a/Release/boot_app0.bin b/Release/boot_app0.bin deleted file mode 100755 index 13562ca..0000000 Binary files a/Release/boot_app0.bin and /dev/null differ diff --git a/Release/bootloader.bin b/Release/bootloader.bin deleted file mode 100755 index 247411e..0000000 Binary files a/Release/bootloader.bin and /dev/null differ diff --git a/Release/console_image.bin b/Release/console_image.bin deleted file mode 100755 index 32aa935..0000000 Binary files a/Release/console_image.bin and /dev/null differ diff --git a/Release/partitions.bin b/Release/partitions.bin deleted file mode 100755 index 71dc012..0000000 Binary files a/Release/partitions.bin and /dev/null differ diff --git a/Release/rnode_firmware_heltec32v4_boundary.bin b/Release/rnode_firmware_heltec32v4_boundary.bin deleted file mode 100755 index 8dd627b..0000000 Binary files a/Release/rnode_firmware_heltec32v4_boundary.bin and /dev/null differ diff --git a/Utilities.h b/Utilities.h index f141f08..6db06b9 100755 --- a/Utilities.h +++ b/Utilities.h @@ -324,6 +324,13 @@ extern RNS::Reticulum reticulum; void led_tx_off() { digitalWrite(pin_led_tx, LOW); } void led_id_on() { } 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 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } 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) ───────────────── // 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 bool headless_led_pwm_attached = false; @@ -1773,10 +1780,12 @@ bool eeprom_model_valid() { if (model == MODEL_C5 || model == MODEL_CA) { #elif BOARD_MODEL == BOARD_HELTEC32_V4 if (model == MODEL_C8) { - #elif BOARD_MODEL == BOARD_HELTEC_T114 - if (model == MODEL_C6 || model == MODEL_C7) { - #elif BOARD_MODEL == BOARD_RAK4631 - if (model == MODEL_11 || model == MODEL_12) { + #elif BOARD_MODEL == BOARD_MESHADVENTURER_S3 + if (model == MODEL_C8) { + #elif BOARD_MODEL == BOARD_HELTEC_T114 + if (model == MODEL_C6 || model == MODEL_C7) { + #elif BOARD_MODEL == BOARD_RAK4631 + if (model == MODEL_11 || model == MODEL_12) { #elif BOARD_MODEL == BOARD_HUZZAH32 if (model == MODEL_FF) { #elif BOARD_MODEL == BOARD_GENERIC_ESP32 diff --git a/extra_script.py b/extra_script.py index 0ebcec2..a659d49 100755 --- a/extra_script.py +++ b/extra_script.py @@ -121,6 +121,8 @@ def device_provision(env): 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"): 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"): env.Execute("rnodeconf --product 10 --model 12 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) elif variant in ("heltec_t114", "heltec_t114_local"): diff --git a/flash.py b/flash.py index 05062c0..e1bf5f8 100755 --- a/flash.py +++ b/flash.py @@ -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 the local cache) and flashes the app partition only, preserving bootloader, -partition table, NVS, and EEPROM settings. For reproducible flashing, the -script prefers the bundled esptool in Release/ over any host-installed copy. +partition table, NVS, and EEPROM settings. Usage: # Update firmware — V4 (default) 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 python flash.py --board v3 @@ -62,7 +55,6 @@ GITHUB_REPO = "jrl290/RTNode-HeltecV4" # Runtime state (set automatically during main()) _flash_mode_override = None # CLI --flash-mode sets this; otherwise board profile wins -_esptool_write_verify_support = {} # Flash addresses for ESP32-S3 Arduino framework BOOTLOADER_ADDR = 0x0000 @@ -324,13 +316,25 @@ def detect_board(port, esptool_cmd): # ── Helpers ──────────────────────────────────────────────────────────────────── -def find_esptool(prefer_system=False): - """Find esptool, preferring repo-managed copies for reproducible flashing. +def find_esptool(): + """Find esptool — pip-installed, user-local, bundled, or PlatformIO's copy. - Default order is bundled Release/ copy, then PlatformIO's packaged copy, - then any host-installed esptool. Pass ``prefer_system=True`` to invert that - preference when a user explicitly wants their machine-wide installation. + Prefer pip/pipx-installed esptool first (handles its own deps and is + usually the newest version), then fall back to the bundled script. """ + # 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 try: import serial # noqa: F401 @@ -338,36 +342,20 @@ def find_esptool(prefer_system=False): except ImportError: has_pyserial = False + # 2. Bundled in Release/ 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( "~/.platformio/packages/tool-esptoolpy/esptool.py" ) + if os.path.isfile(pio_esptool) and has_pyserial: + return [sys.executable, pio_esptool] - repo_candidates = [] - if 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: + # 4. Bundled exists but pyserial is missing — tell the user + if os.path.isfile(bundled) and not has_pyserial: print("Found bundled esptool but pyserial is not installed.") print("Install it with: pip install pyserial") print("Or install the standalone esptool: pip install esptool") @@ -376,33 +364,6 @@ def find_esptool(prefer_system=False): 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(): """List available serial ports and let the user choose.""" system = platform.system() @@ -749,8 +710,8 @@ def check_partition_table(port, esptool_cmd, baud=None): """Compare the device's partition table against the expected one. Returns: - True — partition table matches (or no expected table to compare against) - False — partition table mismatch or unreadable state (device needs full flash) + True — partition table matches (or no expected table to compare against) + False — partition table mismatch (device needs full flash) """ expected_path = find_partitions() 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) if device_data is None: 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) 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 (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 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) if result.returncode != 0: 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: data = f.read() # 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 except Exception as e: print(f" Warning: App check failed: {e}") - return False + return True # assume app exists if we can't check finally: try: os.unlink(tmp.name) @@ -858,37 +820,6 @@ def reset_to_bootloader(port): 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, no_reset_before=False, verify=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}" print(f" Detected: app-only binary -> flash at {flash_addr}") - inline_verify = verify and esptool_supports_write_verify(esptool_cmd) - post_write_verify = verify and not inline_verify - 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" + before_arg = "no_reset" if no_reset_before else "default-reset" + after_arg = "no_reset" if no_hard_reset else "hard-reset" cmd = esptool_cmd + [ "--chip", CHIP, @@ -929,32 +858,19 @@ def flash_firmware(firmware_path, port, esptool_cmd, baud=None, "--baud", baud, "--before", before_arg, "--after", after_arg, - "write_flash", + "write-flash", "-z", - "--flash_mode", mode, - "--flash_freq", FLASH_FREQ, - "--flash_size", flash_size, + "--flash-mode", mode, + "--flash-freq", FLASH_FREQ, + "--flash-size", flash_size, ] - if inline_verify: - cmd.append("--verify") + if verify: + cmd.append("--no-diff-verify") cmd += [flash_addr, firmware_path] print("Running: " + " ".join(cmd[-8:])) result = subprocess.run(cmd) - if 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 + return result.returncode == 0 def _monitor_boot(port, timeout=8): @@ -1019,28 +935,15 @@ def main(): formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: - python flash.py - Download latest firmware and flash default board. - python flash.py --update - Legacy alias for an app-only update. - python flash.py --use-system-esptool - Prefer a host-installed esptool over the bundled Release copy. - python flash.py --board v3 - Download latest firmware and flash a V3 board. - python flash.py --release v1.0.12 - 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. + python flash.py # Download latest & app-only update (V4) + python flash.py --board v3 # Download latest & app-only update (V3) + python flash.py --release v1.0.12 # Flash a specific release version + python flash.py --full # Full flash with merged binary + python flash.py --offline # Use cached/local firmware only + python flash.py --file firmware.bin # Flash a specific file + python flash.py --merge-only # Build merged binary for release + python flash.py --port /dev/ttyACM0 # Specify serial port + python flash.py --erase # Erase flash, then full flash (auto-verify) """, ) 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("--release", "-r", default=None, metavar="TAG", 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", help="Skip online check — use cached or local firmware only") parser.add_argument("--merge-only", action="store_true", @@ -1061,28 +962,17 @@ Examples: help="Flash merged binary (bootloader + partitions + app) — overwrites everything") parser.add_argument("--erase", action="store_true", 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) parser.add_argument("--flash-mode", default=None, help=argparse.SUPPRESS) 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 - esptool_cmd = find_esptool(prefer_system=args.use_system_esptool) + esptool_cmd = find_esptool() if not esptool_cmd: print("Error: esptool not found!") - print("Expected one of:") - 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)") + print("Install it with: pip install esptool") sys.exit(1) # ── Board detection ───────────────────────────────────────────────── diff --git a/platformio.ini b/platformio.ini index b42b09c..9fe28ad 100755 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,6 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -; Change source and include directories to root of project since RNode places them here include_dir = . src_dir = . @@ -19,32 +18,18 @@ monitor_speed = 115200 upload_speed = 460800 build_flags = -Wall - ;-Wextra -Wno-missing-field-initializers -Wno-format -I. - ; CBA Define following to disable DEBUG build - ;-DNDEBUG - ; CBA Define following to include RNS stack -DHAS_RNS -DRNS_USE_FS -DRNS_PERSIST_PATHS -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 = ArduinoJson@^7.4.2 MsgPack@^0.4.2 adafruit/Adafruit SSD1306@^2.5.9 https://github.com/attermann/Crypto.git -; Exclude directories in root from sources build_src_filter = +<*> - extra_scripts = pre:extra_script.py @@ -57,10 +42,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_RNODE_NG_20 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 - adafruit/Adafruit NeoPixel@^1.12.0 + adafruit/Adafruit NeoPixel@^1.15.4 [env:rnode-ng-21] platform = espressif32 @@ -71,10 +56,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_RNODE_NG_21 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 - adafruit/Adafruit NeoPixel@^1.12.0 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-t-beam] platform = espressif32 @@ -85,9 +70,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_TBEAM -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-t-beam-sx1262] platform = espressif32 @@ -99,9 +85,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_TBEAM -DMODEM=SX1262 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-t-beam-supreme] platform = espressif32 @@ -113,11 +100,12 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_TBEAM_S_V1 -DMODEM=SX1262 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 Adafruit_SH110X adafruit/Adafruit SH110X@^2.1.14 + adafruit/Adafruit NeoPixel@^1.15.4 [env:lilygo-t3-s3] platform = espressif32 @@ -129,9 +117,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_T3S3 -DMODEM=SX1262 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:lilygo-t3-s3-sx127x] platform = espressif32 @@ -143,9 +132,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_T3S3 -DMODEM=SX1276 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:lilygo-t3-s3-sx1280-pa] platform = espressif32 @@ -157,36 +147,33 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_T3S3 -DMODEM=SX1280 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:lilygo-t-deck] platform = espressif32 board = esp32-s3-devkitc-1 custom_variant = tdeck board_build.filesystem = littlefs -; Flash / memory layout board_upload.flash_size = 16MB board_upload.maximum_size = 16777216 board_build.partitions = default_16MB.csv -; Enable PSRAM + correct flash mode board_build.flash_mode = qio board_build.psram_type = opi board_build.arduino.memory_type = qio_opi build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_TDECK - -DBOARD_HAS_PSRAM=1 + -DBOARD_HAS_PSRAM=1 -DARDUINO_USB_MODE=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 - ; 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 = + -DCORE_DEBUG_LEVEL=1 + -DARDUINO_USB_CDC_ON_BOOT=1 +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v1] platform = espressif32 @@ -197,9 +184,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V1_0 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v2] platform = espressif32 @@ -210,9 +198,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_0 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v2-extled] platform = espressif32 @@ -224,9 +213,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V1_0 -DEXTERNAL_LEDS=true -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v21] platform = espressif32 @@ -237,9 +227,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v21-extled] platform = espressif32 @@ -251,9 +242,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -DEXTERNAL_LEDS=true -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-lora32-v21-tcxo] platform = espressif32 @@ -265,9 +257,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -DENABLE_TCXO=true -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:heltec_wifi_lora_32_V2] platform = espressif32 @@ -278,9 +271,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:heltec_wifi_lora_32_V2-extled] platform = espressif32 @@ -292,9 +286,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -DEXTERNAL_LEDS=true -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:heltec_wifi_lora_32_V3] platform = espressif32 @@ -305,19 +300,16 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_HELTEC32_V3 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:heltec_V3_boundary] platform = espressif32 board = heltec_wifi_lora_32_V3 custom_variant = heltec32v3 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.maximum_size = 8388608 board_build.partitions = default_8MB.csv @@ -330,17 +322,14 @@ build_flags = -DBOARD_MODEL=BOARD_HELTEC32_V3 -DBOARD_HAS_PSRAM=1 -DBOUNDARY_MODE - ;-DNDEBUG -DRNS_USE_TLSF=1 -DRNS_USE_ALLOCATOR=1 - ; --- Boundary mode defaults (override via EEPROM at runtime) --- - ; TCP server mode (0=server, 1=client) -DBOUNDARY_TCP_MODE=0 - ; TCP listen/connect port -DBOUNDARY_TCP_PORT=4242 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:heltec_wifi_lora_32_V4] @@ -353,16 +342,44 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_HELTEC32_V4 -DARDUINO_USB_CDC_ON_BOOT=1 -lib_deps = +lib_deps = ${env.lib_deps} 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] platform = espressif32 board = esp32-s3-devkitc-1 custom_variant = heltec32v4_boundary board_build.filesystem = littlefs -; Flash / memory layout for 16MB flash + 2MB PSRAM board_upload.flash_size = 16MB board_upload.maximum_size = 16777216 board_build.partitions = default_16MB.csv @@ -376,20 +393,14 @@ build_flags = -DARDUINO_USB_CDC_ON_BOOT=1 -DBOARD_HAS_PSRAM=1 -DBOUNDARY_MODE - ;-DNDEBUG -DRNS_USE_TLSF=1 -DRNS_USE_ALLOCATOR=1 - ; --- Boundary mode defaults (override via EEPROM at runtime) --- - ; TCP server mode (0=server, 1=client) -DBOUNDARY_TCP_MODE=0 - ; TCP listen/connect port -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} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:heltec_V4_boundary-local] @@ -411,9 +422,10 @@ build_flags = -DBOUNDARY_MODE -DBOUNDARY_TCP_MODE=0 -DBOUNDARY_TCP_PORT=4242 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:featheresp32] @@ -425,9 +437,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_HUZZAH32 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:seeed_xiao_esp32s3] platform = espressif32 @@ -438,9 +451,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_XIAO_S3 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:generic-esp32] platform = espressif32 @@ -451,9 +465,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_GENERIC_ESP32 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 [env:wiscore_rak4631] platform = nordicnrf52 @@ -469,10 +484,9 @@ build_flags = -DBOARD_MODEL=BOARD_RAK4631 -DRNS_USE_TLSF=1 -DRNS_USE_ALLOCATOR=1 -lib_deps = +lib_deps = ${env.lib_deps} - - + adafruit/Adafruit NeoPixel@^1.15.4 [env:ttgo-t-beam-local] platform = espressif32 @@ -481,16 +495,15 @@ upload_speed = 460800 custom_variant = tbeam_local board_build.partitions = no_ota.csv board_build.filesystem = littlefs -build_flags = +build_flags = ${env.build_flags} -fexceptions -DBOARD_MODEL=BOARD_TBEAM - ; CBA TEST - ;-DUSE_FLASHFS=1 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:ttgo-lora32-v21-local] @@ -503,9 +516,10 @@ board_build.filesystem = littlefs build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_LORA32_V2_1 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:heltec_wifi_lora_32_V4-local] @@ -518,9 +532,10 @@ build_flags = ${env.build_flags} -DBOARD_MODEL=BOARD_HELTEC32_V4 -DARDUINO_USB_CDC_ON_BOOT=1 -lib_deps = +lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 + adafruit/Adafruit NeoPixel@^1.15.4 monitor_filters = esp32_exception_decoder [env:wiscore_rak4631-local] @@ -535,17 +550,15 @@ build_flags = -I variants/rak4630 -fexceptions -DBOARD_MODEL=BOARD_RAK4631 - ; CBA TEST -DRNS_USE_TLSF=1 -DRNS_USE_ALLOCATOR=1 - ;-DUSE_FLASHFS=1 build_unflags = -fno-exceptions -lib_deps = +lib_deps = ${env.lib_deps} Adafruit_SPIFlash=symlink://../Adafruit_SPIFlash + adafruit/Adafruit NeoPixel@^1.15.4 [env:heltec_t114_local] -;upload_port = /dev/cu.usbmodem1101 platform = nordicnrf52 board = nrf52840_dk_adafruit custom_variant = heltec_t114_local @@ -555,11 +568,10 @@ build_flags = ${env.build_flags} -fexceptions -DBOARD_MODEL=BOARD_HELTEC_T114 - ; CBA TEST -DRNS_USE_TLSF=1 -DRNS_USE_ALLOCATOR=1 build_unflags = -fno-exceptions -lib_deps = +lib_deps = ${env.lib_deps} https://github.com/liamcottle/esp8266-oled-ssd1306#e16cee124fe26490cb14880c679321ad8ac89c95 - adafruit/Adafruit NeoPixel@^1.12.0 + adafruit/Adafruit NeoPixel@^1.15.4 diff --git a/sx126x.cpp b/sx126x.cpp index 651f52f..7e85055 100755 --- a/sx126x.cpp +++ b/sx126x.cpp @@ -126,7 +126,7 @@ bool sx126x::preInit() { pinMode(_ss, OUTPUT); 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); #elif BOARD_MODEL == BOARD_TECHO 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}; #elif BOARD_MODEL == BOARD_HELTEC32_V4 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 executeOpcode(OP_DIO3_TCXO_CTRL_6X, buf, 4); #endif