From da22b127c33abc3d03ea09d323d2be75d2a24f7b Mon Sep 17 00:00:00 2001 From: Rastislav Vysoky Date: Tue, 7 Apr 2026 19:05:24 +0200 Subject: [PATCH] sx1276 --- zephcore/CMakeLists.txt | 5 + zephcore/Kconfig | 19 +- zephcore/adapters/radio/SX127xRadio.cpp | 98 +++++++++ zephcore/adapters/radio/SX127xRadio.h | 50 +++++ zephcore/app/main_observer.cpp | 2 + zephcore/boards/esp32/ttgo_lora32/board.conf | 37 ++++ .../boards/esp32/ttgo_lora32/board.overlay | 55 +++++ .../promicro_sx1262/Kconfig.promicro_sx1262 | 6 + .../nrf52840/promicro_sx1262/board.conf | 15 ++ .../boards/nrf52840/promicro_sx1262/board.yml | 8 + .../promicro_sx1262-pinctrl.dtsi | 58 ++++++ .../promicro_sx1262/promicro_sx1262.dts | 196 ++++++++++++++++++ .../promicro_sx1262/promicro_sx1262_defconfig | 14 ++ zephcore/include/mesh/RadioIncludes.h | 2 + zephcore/src/main_companion.cpp | 4 + zephcore/src/main_repeater.cpp | 4 + 16 files changed, 572 insertions(+), 1 deletion(-) create mode 100644 zephcore/adapters/radio/SX127xRadio.cpp create mode 100644 zephcore/adapters/radio/SX127xRadio.h create mode 100644 zephcore/boards/esp32/ttgo_lora32/board.conf create mode 100644 zephcore/boards/esp32/ttgo_lora32/board.overlay create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/Kconfig.promicro_sx1262 create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/board.conf create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/board.yml create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262-pinctrl.dtsi create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts create mode 100644 zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262_defconfig diff --git a/zephcore/CMakeLists.txt b/zephcore/CMakeLists.txt index 8e30ba3..9e76f66 100644 --- a/zephcore/CMakeLists.txt +++ b/zephcore/CMakeLists.txt @@ -375,6 +375,11 @@ elseif(CONFIG_ZEPHCORE_RADIO_LR2021) target_include_directories(app PRIVATE ${ZEPHYR_DIR_LR20}/drivers/lora/lr20xx ) +elseif(CONFIG_ZEPHCORE_RADIO_SX127X) + message(STATUS "ZephCore Radio: SX127x (Zephyr loramac-node driver)") + target_sources(app PRIVATE + adapters/radio/SX127xRadio.cpp + ) else() # Default: SX126x via native Zephyr LoRa driver message(STATUS "ZephCore Radio: SX126x (native Zephyr driver)") diff --git a/zephcore/Kconfig b/zephcore/Kconfig index 58754ca..0cdf5a7 100644 --- a/zephcore/Kconfig +++ b/zephcore/Kconfig @@ -268,6 +268,23 @@ config ZEPHCORE_RADIO_LR2021 Supports sub-GHz + 2.4 GHz ISM + NTN/SATCOM. TCXO, RF switch, and PA config are in the device tree. +config ZEPHCORE_RADIO_SX127X + bool "SX127x (SX1272/SX1276/SX1278) via Zephyr loramac-node driver" + help + Uses Zephyr's loramac-node-based LoRa driver for SX127x radios. + Supports SX1272, SX1276, and SX1278 chips via the standard Zephyr + LoRa API (lora_config, lora_send_async, lora_recv_async). + + Chip-specific features not available via standard API are stubbed: + - Instantaneous RSSI (hwGetCurrentRSSI returns -80 dBm sentinel) + - Preamble detection (always false — TX won't abort mid-preamble) + - RX boost (no-op — SX127x has no dedicated boost register) + - AGC reset (no-op — loramac-node manages AGC internally) + - BUSY pin (false — SX127x has no BUSY signal) + + Used by: TTGO LoRa32, Heltec LoRa32 V1/V2, and any board with + an SX1272/SX1276/SX1278 radio. + endchoice config ZEPHCORE_DEFAULT_TX_POWER_DBM @@ -357,7 +374,7 @@ menu "LoRa Power Saving" config ZEPHCORE_LORA_RX_DUTY_CYCLE bool "Enable LoRa RX duty cycle power saving" - default y if (ZEPHCORE_ROLE_COMPANION || ZEPHCORE_ROLE_REPEATER) && !ZEPHCORE_RADIO_LR1110 && !ZEPHCORE_RADIO_LR2021 + default y if (ZEPHCORE_ROLE_COMPANION || ZEPHCORE_ROLE_REPEATER) && !ZEPHCORE_RADIO_LR1110 && !ZEPHCORE_RADIO_LR2021 && !ZEPHCORE_RADIO_SX127X default n help Enable RX duty cycling for power saving on battery-powered devices. diff --git a/zephcore/adapters/radio/SX127xRadio.cpp b/zephcore/adapters/radio/SX127xRadio.cpp new file mode 100644 index 0000000..33ee35d --- /dev/null +++ b/zephcore/adapters/radio/SX127xRadio.cpp @@ -0,0 +1,98 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SX127x hardware hooks for LoRaRadioBase — Zephyr loramac-node driver. + * + * The SX127x driver (loramac-node/sx127x.c) exposes only the standard + * Zephyr LoRa API. Chip-specific features that the SX126x native driver + * provides via sx126x_ext.h are not available here: + * + * hwGetCurrentRSSI() — returns -80 dBm sentinel (no hardware path) + * hwIsPreambleDetected()— always false (no preamble-detect IRQ exposed) + * hwSetRxBoost() — no-op (SX127x has no RX boost register) + * hwResetAGC() — no-op (loramac-node manages AGC internally) + * hwIsChipBusy() — inherited false (no BUSY pin on SX127x) + * + * Everything else (configure, send, receive) uses the standard API. + */ + +#include "SX127xRadio.h" +#include +#include + +#include +LOG_MODULE_REGISTER(sx127x_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL); + +namespace mesh { + +K_THREAD_STACK_DEFINE(sx127x_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE); + +SX127xRadio::SX127xRadio(const struct device *lora_dev, MainBoard &board, + NodePrefs *prefs) + : LoRaRadioBase(lora_dev, board, prefs) +{ + /* SX127x has no RX boost feature — start with boost disabled */ + _rx_boost_enabled = false; +} + +void SX127xRadio::begin() +{ + startTxThread(sx127x_tx_wait_stack, + K_THREAD_STACK_SIZEOF(sx127x_tx_wait_stack)); + LoRaRadioBase::begin(); +} + +/* ── Hardware primitives ──────────────────────────────────────────────── */ + +void SX127xRadio::hwConfigure(const struct lora_modem_config &cfg) +{ + int ret = lora_config(_dev, const_cast(&cfg)); + if (ret < 0) { + LOG_ERR("lora_config failed: %d", ret); + } +} + +void SX127xRadio::hwCancelReceive() +{ + lora_recv_async(_dev, NULL, NULL); +} + +int SX127xRadio::hwSendAsync(uint8_t *buf, uint32_t len, + struct k_poll_signal *sig) +{ + return lora_send_async(_dev, buf, len, sig); +} + +int16_t SX127xRadio::hwGetCurrentRSSI() +{ + /* SX127x loramac-node driver does not expose an instantaneous RSSI + * function via the standard Zephyr API. Return a plausible noise-floor + * sentinel so LoRaRadioBase::triggerNoiseFloorCalibrate() converges + * to a reasonable value rather than being seeded with garbage. */ + return -80; +} + +bool SX127xRadio::hwIsPreambleDetected() +{ + /* No preamble-detect IRQ accessible through the standard Zephyr LoRa + * API for the loramac-node driver. Returning false means TX will + * not abort for an in-progress preamble — acceptable on SX127x. */ + return false; +} + +void SX127xRadio::hwSetRxBoost(bool enable) +{ + /* SX127x does not have a dedicated RX boost / high-sensitivity mode + * switch. Sensitivity is controlled via lora_config tx_power and + * the DTS power-amplifier-output property. Nothing to do here. */ + ARG_UNUSED(enable); +} + +void SX127xRadio::hwResetAGC() +{ + /* The loramac-node SX127x driver manages AGC recalibration internally + * (RadioSetRxConfig re-programs all gain registers on every RX config + * call). No explicit AGC reset is needed or possible via the + * standard API. The base class will restart RX after this call. */ +} + +} /* namespace mesh */ diff --git a/zephcore/adapters/radio/SX127xRadio.h b/zephcore/adapters/radio/SX127xRadio.h new file mode 100644 index 0000000..1d8e3eb --- /dev/null +++ b/zephcore/adapters/radio/SX127xRadio.h @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * ZephCore Radio adapter for SX127x (SX1272/SX1276/SX1278) using Zephyr loramac-node driver. + * + * The SX127x loramac-node driver supports the standard Zephyr LoRa API + * (lora_config, lora_send_async, lora_recv_async) but has no extension + * API for instantaneous RSSI, preamble detection, or RX boost. + * Those features are stubbed out below. + */ + +#pragma once + +#include "LoRaRadioBase.h" + +namespace mesh { + +class SX127xRadio : public LoRaRadioBase { +public: + SX127xRadio(const struct device *lora_dev, MainBoard &board, + NodePrefs *prefs = nullptr); + + void begin() override; + +protected: + /* Hardware primitives */ + void hwConfigure(const struct lora_modem_config &cfg) override; + void hwCancelReceive() override; + int hwSendAsync(uint8_t *buf, uint32_t len, + struct k_poll_signal *sig) override; + + /* SX127x via loramac-node has no instantaneous RSSI API. + * Returns a fixed sentinel (-80 dBm) — noise floor calibration + * will converge on this value rather than the real noise floor. */ + int16_t hwGetCurrentRSSI() override; + + /* SX127x has no preamble-detected IRQ accessible via standard API. + * Always returns false — TX will not abort for a detected preamble. */ + bool hwIsPreambleDetected() override; + + /* SX127x has no RX boost / LNA gain switch via standard API. No-op. */ + void hwSetRxBoost(bool enable) override; + + /* SX127x loramac-node driver manages AGC automatically. No-op. */ + void hwResetAGC() override; + + /* SX127x has no BUSY pin. Default (false) from base is correct. */ + /* bool hwIsChipBusy() — inherited, returns false */ +}; + +} /* namespace mesh */ diff --git a/zephcore/app/main_observer.cpp b/zephcore/app/main_observer.cpp index e193026..c7a749c 100644 --- a/zephcore/app/main_observer.cpp +++ b/zephcore/app/main_observer.cpp @@ -288,6 +288,8 @@ static NodePrefs s_radio_prefs; #if IS_ENABLED(CONFIG_ZEPHCORE_RADIO_LR1110) static mesh::LR1110Radio lora_radio(lora_dev, s_board, &s_radio_prefs); +#elif IS_ENABLED(CONFIG_ZEPHCORE_RADIO_SX127X) +static mesh::SX127xRadio lora_radio(lora_dev, s_board, &s_radio_prefs); #else static mesh::SX126xRadio lora_radio(lora_dev, s_board, &s_radio_prefs); #endif diff --git a/zephcore/boards/esp32/ttgo_lora32/board.conf b/zephcore/boards/esp32/ttgo_lora32/board.conf new file mode 100644 index 0000000..9f34566 --- /dev/null +++ b/zephcore/boards/esp32/ttgo_lora32/board.conf @@ -0,0 +1,37 @@ +# TTGO LoRa32 — ESP32 + SX1276 +# +# Hardware: +# ESP32 (4MB flash) +# SX1276 on SPI3 +# SSD1306 128x64 OLED on I2C0 +# +# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf + +# Board identification +CONFIG_ZEPHCORE_BOARD_NAME="TTGO LoRa32" +CONFIG_BT_DIS_MODEL_NUMBER_STR="TTGO LoRa32" + +# Radio: SX1276 via Zephyr loramac-node driver (not the native SX126x driver) +# zephcore_common.conf sets CONFIG_LORA_MODULE_BACKEND_NATIVE=y for SX126x boards. +# Override here: SX127x uses the loramac-node backend (classic LoRaMac-node library). +CONFIG_LORA_MODULE_BACKEND_NATIVE=n +CONFIG_LORA_MODULE_BACKEND_LORAMAC_NODE=y +CONFIG_ZEPHCORE_RADIO_SX127X=y + +# SX1276 PA_BOOST output: 17 dBm is the safe maximum without an external PA +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=17 +CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=17 + +# RX duty cycle is not supported by the loramac-node SX127x driver +# (lora_recv_duty_cycle returns -ENOSYS and gracefully falls back to +# lora_recv_async, but disable it to avoid the spurious attempt) +CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE=n + +# Flash mode: ESP32-PICO-D4 (rev 1.0) — use DIO, not QIO. +# esp32_common.conf enables QIO for the ESP32-S3/C3/C6 boards in this repo. +# Classic ESP32 PICO-D4 rev 1.0 has an issue where bootloader_enable_qio_mode() +# polls the SPI flash WIP bit indefinitely; this hangs with no output after the +# chip-revision "Proceeding" message, the RTCWDT fires, and the board bootloops. +# DIO avoids the QIO-enable SPI sequence entirely and works reliably on PICO-D4. +CONFIG_ESPTOOLPY_FLASHMODE_QIO=n +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y diff --git a/zephcore/boards/esp32/ttgo_lora32/board.overlay b/zephcore/boards/esp32/ttgo_lora32/board.overlay new file mode 100644 index 0000000..05c2a92 --- /dev/null +++ b/zephcore/boards/esp32/ttgo_lora32/board.overlay @@ -0,0 +1,55 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * TTGO LoRa32 — ZephCore overlay + * + * The upstream Zephyr DTS (ttgo_lora32_esp32_procpu.dts) already defines: + * SX1276 on SPI3 (NSS=GPIO18, SCK/MOSI/MISO via pinctrl) + * SSD1306 OLED on I2C0 (SDA=GPIO21, SCL=GPIO22) + * UART0 console (TX=GPIO1, RX=GPIO3) + * LED0 on GPIO25, WiFi + * + * LoRa SPI3 pins: NSS=18, DIO0=26, DIO1=35, DIO2=34 + * LoRa control: RESET=23 + * Display I2C0: SDA=21, SCL=22 (SSD1306 @ 0x3C) + * + * Flash layout (partitions_0x1000_amp_4M.dtsi): + * storage_partition @ 0x3B0000 (192KB) — repurposed as LittleFS + */ + +/ { + chosen { + /* UART0 console is correct for classic ESP32 (no native USB) */ + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; +}; + +/* + * Flash partitions — repurpose storage_partition as LittleFS. + * The 4MB layout has appcpu slots we don't use (procpu-only build), + * but we leave them to avoid changing the partition map. + */ +/delete-node/ &storage_partition; + +&flash0 { + partitions { + /* LittleFS 192KB for DataStore (identity, prefs, creds) */ + lfs_partition: partition@3b0000 { + label = "lfs"; + reg = <0x3B0000 0x30000>; + }; + }; +}; + +/* LittleFS auto-mount — standard /lfs mount point */ +#include "../../common/filesystem.dtsi" + +/* WiFi — required for observer MQTT connectivity */ +&wifi { + status = "okay"; +}; + +/* I2C sensors — auto-detected at runtime */ +&i2c0 { + #include "../../common/sensors-i2c.dtsi" +}; diff --git a/zephcore/boards/nrf52840/promicro_sx1262/Kconfig.promicro_sx1262 b/zephcore/boards/nrf52840/promicro_sx1262/Kconfig.promicro_sx1262 new file mode 100644 index 0000000..b22930f --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/Kconfig.promicro_sx1262 @@ -0,0 +1,6 @@ +# ProMicro SX1262 (Ebyte E22-900M30S) board configuration +# Copyright (c) 2025 ZephCore +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_PROMICRO_SX1262 + select SOC_NRF52840_QIAA diff --git a/zephcore/boards/nrf52840/promicro_sx1262/board.conf b/zephcore/boards/nrf52840/promicro_sx1262/board.conf new file mode 100644 index 0000000..acf4e77 --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/board.conf @@ -0,0 +1,15 @@ +# ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S +# SoftDevice v6 (S140 v6) — NiceNano/SuperMini bootloader uses S140 6.1.1 +# 0x00B6 = S140 v6 firmware ID; app partition starts at 0x26000 + +CONFIG_ZEPHCORE_BOARD_NAME="ProMicro SX1262" +CONFIG_BT_DIS_MODEL_NUMBER_STR="ProMicro SX1262 nRF52840-SX1262" +CONFIG_ZEPHCORE_SD_FWID=0x00B6 + +# Native Zephyr SX1262 driver (Ebyte E22-900M30S) +CONFIG_ZEPHCORE_RADIO_NATIVE=y + +# E22-900M30S has 30dB external PA — cap SX1262 output to 10 dBm +# to avoid PA damage on TX +CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=10 +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10 diff --git a/zephcore/boards/nrf52840/promicro_sx1262/board.yml b/zephcore/boards/nrf52840/promicro_sx1262/board.yml new file mode 100644 index 0000000..30a0bcb --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 ZephCore +# SPDX-License-Identifier: Apache-2.0 +board: + name: promicro_sx1262 + full_name: ProMicro sx1262 (nRF52840 SuperMini + sx1262) + vendor: zephcore + socs: + - name: nrf52840 diff --git a/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262-pinctrl.dtsi b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262-pinctrl.dtsi new file mode 100644 index 0000000..ca14740 --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262-pinctrl.dtsi @@ -0,0 +1,58 @@ +/* + * ProMicro SX1262 pin control definitions + * Copyright (c) 2025 ZephCore + * SPDX-License-Identifier: Apache-2.0 + * + * SPI2 (SX1262): SCK=P1.11, MOSI=P1.15, MISO=P0.02 + * I2C0 (sensors): SDA=P1.04, SCL=P0.11 + * UART0 (GPS): TX=P0.20→GPS RX, RX=P0.22←GPS TX + */ + +&pinctrl { + spi2_default: spi2_default { + group1 { + psels = , + , + ; + }; + }; + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; diff --git a/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts new file mode 100644 index 0000000..261ef98 --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262.dts @@ -0,0 +1,196 @@ +/* + * ProMicro SX1262 — nRF52840 SuperMini + Ebyte E22-900M30S + * Copyright (c) 2025 ZephCore + * + * SPDX-License-Identifier: Apache-2.0 + * + * Hardware: + * - nRF52840 (SuperMini/ProMicro form factor) with BLE 5 + * - Ebyte E22-900M30S (SX1262 + 30dB PA), TCXO, DIO2=TXEN, RXEN on P0.17 + * - GPS module on UART0 (9600 baud, P0.22 RX, P0.20 TX) + * - Battery ADC on AIN7 (P0.31), 150K+150K divider (2:1) + * - User button on P1.00, LED on P0.15 + * - 3V3 enable on P0.13 (must be HIGH for SX1262 to function) + */ + +/dts-v1/; +#include +#include "promicro_sx1262-pinctrl.dtsi" +#include +#include +#include + +/ { + model = "ProMicro SX1262"; + compatible = "zephcore,promicro-sx1262"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &code_partition; + zephyr,console = &cdc_acm_uart; + zephyr,shell-uart = &cdc_acm_uart; + }; + + aliases { + lora0 = &lora; + led0 = &led0; + sw0 = &user_button; + watchdog0 = &wdt0; + gps-enable = &gps_enable_pin; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + label = "LED"; + }; + }; + + buttons: buttons { + compatible = "gpio-keys"; + user_button: button_0 { + gpios = <&gpio1 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "User Button"; + }; + }; + + /* 3V3 enable — must be HIGH to power E22-900M30S module */ + vcc3v3_enable: vcc3v3-enable { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3-enable"; + enable-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + startup-delay-us = <5000>; + }; + + /* GPS power control */ + gps_en: gps-enable { + compatible = "gpio-leds"; + gps_enable_pin: gps_enable { + gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; + label = "GPS Enable"; + }; + }; + + /* Battery ADC: P0.31 (AIN7), 1M+1.5M voltage divider (5:3) */ + zephyr,user { + io-channels = <&adc 7>; + vbat-mv-multiplier = <6000>; + }; +}; + +®0 { + status = "okay"; +}; + +®1 { + regulator-initial-mode = ; +}; + +&uicr { + nfct-pins-as-gpios; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&adc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* Battery voltage on P0.31 (AIN7) */ + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <12>; + }; +}; + +/* ---- SPI2 for SX1262 (Ebyte E22-900M30S) ---- */ +&spi2 { + compatible = "nordic,nrf-spim"; + status = "okay"; + pinctrl-0 = <&spi2_default>; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; /* P1.13 SX1262_CS */ + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + spi-max-frequency = <8000000>; + + reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; + busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + dio1-gpios = <&gpio0 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + + /* RF switch: DIO2 drives TXEN, RXEN on P0.17 */ + dio2-tx-enable; + rx-enable-gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + + /* E22-900M30S TCXO, 1.8V supply via DIO3 */ + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <10>; + + /* RX boosted mode for better sensitivity */ + rx-boosted; + }; +}; + +/* ---- I2C0 for optional sensors ---- */ +&i2c0 { + compatible = "nordic,nrf-twim"; + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; + + /* All supported environment & power sensors — auto-detected at runtime */ + #include "../../common/sensors-i2c.dtsi" +}; + +/* ---- GPS on UART0 (9600 baud) ---- */ +&uart0 { + compatible = "nordic,nrf-uarte"; + status = "okay"; + current-speed = <9600>; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; + + gnss: gnss { + compatible = "luatos,air530z"; + on-off-gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; + }; +}; + +/* ---- USB CDC for console/CLI ---- */ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + cdc_acm_uart: cdc_acm_uart { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +/* ---- Flash partitions (SoftDevice v6, app@0x26000) ---- */ +#include "../../common/nrf52_partitions_sdv6.dtsi" +#include "../../common/nrf52_wakeup.dtsi" diff --git a/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262_defconfig b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262_defconfig new file mode 100644 index 0000000..1551170 --- /dev/null +++ b/zephcore/boards/nrf52840/promicro_sx1262/promicro_sx1262_defconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_GPIO=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_PINCTRL=y +CONFIG_SPI=y +CONFIG_ADC=y diff --git a/zephcore/include/mesh/RadioIncludes.h b/zephcore/include/mesh/RadioIncludes.h index 4ac26e0..041f719 100644 --- a/zephcore/include/mesh/RadioIncludes.h +++ b/zephcore/include/mesh/RadioIncludes.h @@ -23,6 +23,8 @@ #include #elif IS_ENABLED(CONFIG_ZEPHCORE_RADIO_LR2021) #include +#elif IS_ENABLED(CONFIG_ZEPHCORE_RADIO_SX127X) +#include #else #include #endif diff --git a/zephcore/src/main_companion.cpp b/zephcore/src/main_companion.cpp index aefa13b..bfb2d4b 100644 --- a/zephcore/src/main_companion.cpp +++ b/zephcore/src/main_companion.cpp @@ -368,6 +368,10 @@ static mesh::LR1110Radio lora_radio(lora_dev, zephyr_board, &temp_prefs); /* LR2021 via Zephyr LoRa driver */ static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); static mesh::LR2021Radio lora_radio(lora_dev, zephyr_board, &temp_prefs); +#elif IS_ENABLED(CONFIG_ZEPHCORE_RADIO_SX127X) +/* SX127x via Zephyr loramac-node driver */ +static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); +static mesh::SX127xRadio lora_radio(lora_dev, zephyr_board, &temp_prefs); #else /* SX126x via Zephyr LoRa driver */ static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); diff --git a/zephcore/src/main_repeater.cpp b/zephcore/src/main_repeater.cpp index f49f248..3dc483b 100644 --- a/zephcore/src/main_repeater.cpp +++ b/zephcore/src/main_repeater.cpp @@ -284,6 +284,10 @@ static NodePrefs radio_prefs; /* LR1110 via Zephyr LoRa driver */ static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); static mesh::LR1110Radio lora_radio(lora_dev, zephyr_board, &radio_prefs); +#elif IS_ENABLED(CONFIG_ZEPHCORE_RADIO_SX127X) +/* SX127x via Zephyr loramac-node driver */ +static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0)); +static mesh::SX127xRadio lora_radio(lora_dev, zephyr_board, &radio_prefs); #else /* SX126x via Zephyr LoRa driver */ static const struct device *const lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0));