From b890cc8104240f5c3ca2e1b466f267608c9517a6 Mon Sep 17 00:00:00 2001 From: "Enot (ded) Skelly" Date: Thu, 23 Apr 2026 13:46:25 -0700 Subject: [PATCH] add ikoka sticks --- build.sh | 3 + zephcore/CMakeLists.txt | 2 +- .../Kconfig.ikoka_stick_22dbm | 5 + .../nrf52840/ikoka_stick_22dbm/board.conf | 37 +++ .../nrf52840/ikoka_stick_22dbm/board.yml | 6 + .../ikoka_stick_22dbm-pinctrl.dtsi | 99 +++++++ .../ikoka_stick_22dbm/ikoka_stick_22dbm.dts | 258 ++++++++++++++++++ .../ikoka_stick_22dbm_defconfig | 29 ++ .../Kconfig.ikoka_stick_30dbm | 5 + .../nrf52840/ikoka_stick_30dbm/board.conf | 36 +++ .../nrf52840/ikoka_stick_30dbm/board.yml | 6 + .../ikoka_stick_30dbm-pinctrl.dtsi | 99 +++++++ .../ikoka_stick_30dbm/ikoka_stick_30dbm.dts | 257 +++++++++++++++++ .../ikoka_stick_30dbm_defconfig | 29 ++ .../Kconfig.ikoka_stick_33dbm | 5 + .../nrf52840/ikoka_stick_33dbm/board.conf | 36 +++ .../nrf52840/ikoka_stick_33dbm/board.yml | 6 + .../ikoka_stick_33dbm-pinctrl.dtsi | 99 +++++++ .../ikoka_stick_33dbm/ikoka_stick_33dbm.dts | 258 ++++++++++++++++++ .../ikoka_stick_33dbm_defconfig | 29 ++ zephcore/boards/supported_boards.md | 3 + 21 files changed, 1306 insertions(+), 1 deletion(-) create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/Kconfig.ikoka_stick_22dbm create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/board.conf create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/board.yml create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm-pinctrl.dtsi create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm.dts create mode 100644 zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm_defconfig create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/Kconfig.ikoka_stick_30dbm create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/board.conf create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/board.yml create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm-pinctrl.dtsi create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm.dts create mode 100644 zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm_defconfig create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/Kconfig.ikoka_stick_33dbm create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/board.conf create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/board.yml create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm-pinctrl.dtsi create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm.dts create mode 100644 zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm_defconfig diff --git a/build.sh b/build.sh index 6fbe551..0e3637b 100644 --- a/build.sh +++ b/build.sh @@ -15,6 +15,9 @@ nRF_boards=( thinknode_m6 rak_wismesh_tag ikoka_nano_30dbm + ikoka_stick_22dbm + ikoka_stick_30dbm + ikoka_stick_33dbm sensecap_solar xiao_nrf52840 ) diff --git a/zephcore/CMakeLists.txt b/zephcore/CMakeLists.txt index e3deecd..6494325 100644 --- a/zephcore/CMakeLists.txt +++ b/zephcore/CMakeLists.txt @@ -222,7 +222,7 @@ set(ZEPHCORE_COMMON_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/zephcore_com # Detect platform from board name and add platform-specific common config # For boards with qualifiers like "wio_tracker_l1/nrf52840", check both the full BOARD # string and the BOARD_QUALIFIERS which contains just the qualifier (e.g., "nrf52840") -if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "rak3401_1watt" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6" OR BOARD MATCHES "promicro_lr2021" OR BOARD MATCHES "sensecap_solar" OR BOARD MATCHES "xiao_nrf52840") +if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" OR BOARD MATCHES "rak3401_1watt" OR BOARD MATCHES "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "ikoka_stick" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1" OR BOARD MATCHES "thinknode_m3" OR BOARD MATCHES "thinknode_m6" OR BOARD MATCHES "promicro_lr2021" OR BOARD MATCHES "sensecap_solar" OR BOARD MATCHES "xiao_nrf52840") set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf") elseif(DEFINED BOARD_QUALIFIERS AND BOARD_QUALIFIERS MATCHES ".*nrf52.*") set(ZEPHCORE_PLATFORM_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/nrf52_common.conf") diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/Kconfig.ikoka_stick_22dbm b/zephcore/boards/nrf52840/ikoka_stick_22dbm/Kconfig.ikoka_stick_22dbm new file mode 100644 index 0000000..31d3bf8 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/Kconfig.ikoka_stick_22dbm @@ -0,0 +1,5 @@ +# Ikoka Stick 22dBm board configuration +# DC/DC converter enabled via DTS: ®1 { regulator-initial-mode = ; } + +config BOARD_IKOKA_STICK_22DBM + select SOC_NRF52840_QIAA diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.conf b/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.conf new file mode 100644 index 0000000..d2b93ed --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.conf @@ -0,0 +1,37 @@ +# Ikoka Stick 22dBm (XIAO nRF52840 + E22-900M22S) +# Board-specific configuration +# +# Hardware: +# - XIAO nRF52840 base board (socketed via pin headers) +# - E22-900M22S LoRa module (bare SX1262, no external PA, 22 dBm output) +# - User button on D0 (P0.02) +# - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected) +# - Battery ADC on AIN7 (P0.31), enable on P0.14 +# - LEDs: RED=P0.26, BLUE=P0.06, GREEN=P0.30 +# +# Pin Mapping (XIAO D-pins to nRF52840 GPIOs): +# D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) +# D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) +# D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) +# D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) +# +# LoRa Module E22-900M22S Notes: +# - Bare SX1262. No external PA stage; SX1262 drives the antenna directly +# up to +22 dBm. No input-power restriction beyond the SX1262's own spec. +# - DIO2 drives the internal TX/RX antenna switch (dio2-tx-enable). +# - RXEN (P0.05) is still wired on the PCB (shared trace across all three +# Stick variants) but has no external-PA function on this module — the +# line toggles are harmless. + +# Board identification (matches Arduino variant name) +CONFIG_ZEPHCORE_BOARD_NAME="Ikoka Stick-E22-22dBm (Xiao_nrf52)" + +# Device Information Service model name +CONFIG_BT_DIS_MODEL_NUMBER_STR="Ikoka Stick 22dBm" + +# SoftDevice firmware ID (XIAO nRF52840 uses S140 v7.3.0) +CONFIG_ZEPHCORE_SD_FWID=0x0123 + +# SX1262 TX power caps — full rated output (22 dBm) is safe on the bare module. +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=22 +CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=22 diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.yml b/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.yml new file mode 100644 index 0000000..9414865 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/board.yml @@ -0,0 +1,6 @@ +board: + name: ikoka_stick_22dbm + full_name: Ikoka Stick 22dBm (XIAO nRF52840 + E22-900M22S) + vendor: ikoka + socs: + - name: nrf52840 diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm-pinctrl.dtsi b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm-pinctrl.dtsi new file mode 100644 index 0000000..89bb3d0 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm-pinctrl.dtsi @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 22dBm pin control - based on XIAO nRF52840 + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * UART0 is NOT wired on this board (console is USB-CDC). The pinctrl + * nodes below are kept so that upstream nRF52840 SoC defaults that + * reference &uart0_default/&uart0_sleep still resolve. &uart0 itself + * is disabled in the .dts to prevent the driver from driving pins. + * Dummy pins P0.08 / P0.09 are not brought out to a connector on XIAO. + */ + +&pinctrl { + /* UART0 placeholder — driver is disabled, pins are not brought out */ + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors */ + i2c1_default: i2c1_default { + group1 { + psels = , /* D6 = P1.11 */ + ; /* D7 = P1.12 */ + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* SPI2 for LoRa on D8/D9/D10 */ + spi2_default: spi2_default { + group1 { + psels = , /* D8 = P1.13 */ + , /* D10 = P1.15 */ + ; /* D9 = P1.14 */ + }; + }; + + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /* QSPI for onboard flash (disabled on XIAO nRF52840 — kept for symmetry) */ + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; +}; diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm.dts b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm.dts new file mode 100644 index 0000000..99afa06 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm.dts @@ -0,0 +1,258 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 22dBm - XIAO nRF52840 + E22-900M22S LoRa module + * + * Reference: https://ndoo.sg/projects:amateur_radio:meshtastic:diy_devices:ikoka_stick + * + * E22-900M22S LoRa Module: + * - Bare SX1262 (no external PA) — up to 22 dBm directly from the chip. + * - RXEN (P0.05 / D5) is wired on the PCB (shared trace with the 30/33 dBm + * variants) but has no PA-switching function on this module; toggling + * it is harmless. + * - DIO2 as RF switch, TCXO 1.8V + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * Peripherals: + * - User button on D0 with long-press (deep sleep) + multi-tap actions + * - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected at boot) + * - Battery ADC on AIN7 (P0.31), enable on P0.14 + * - LEDs: RED=P0.26/D11, BLUE=P0.06/D12, GREEN=P0.30/D13 + */ + +/dts-v1/; +#include +#include "ikoka_stick_22dbm-pinctrl.dtsi" +#include +#include + +/ { + model = "Ikoka Stick 22dBm"; + compatible = "ikoka,stick-22dbm"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &code_partition; + zephyr,console = &cdc_acm_uart; + zephyr,shell-uart = &cdc_acm_uart; + zephyr,display = &ssd1306; + }; + + aliases { + lora0 = &lora; + led0 = &led_red; + led1 = &led_green; + led2 = &led_blue; + watchdog0 = &wdt0; + }; + + /* Status LEDs - active LOW on XIAO */ + leds { + compatible = "gpio-leds"; + led_red: led_0 { + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led_green: led_1 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + led_blue: led_2 { + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + /* User button on D0 (P0.02), active LOW with internal pull-up. + * Matches the pinout of the Seeed XIAO nRF52840 base board. */ + buttons: buttons { + compatible = "gpio-keys"; + + user_button: button_0 { + gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "User Button"; + }; + }; + + /* Long-press = deep sleep (≥1 s), short = feeds into multi-tap */ + user_btn_longpress { + compatible = "zephyr,input-longpress"; + input = <&buttons>; + input-codes = ; + short-codes = ; + long-codes = ; + long-delay-ms = <1000>; + }; + + /* Multi-tap — standard ZephCore mapping: + * 1 tap → page next 2 taps → flood advert + * 3 taps → buzzer mute 4 taps → GPS toggle + * 5 taps → LED heartbeat */ + user_btn_multitap { + compatible = "zephcore,input-multi-tap"; + input-codes = ; + tap-codes = ; + tap-delay-ms = <400>; + }; + + /* Battery ADC enable - P0.14 must be LOW to read battery */ + vbat_enable: vbat-enable { + compatible = "regulator-fixed"; + regulator-name = "vbat-enable"; + enable-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; + + /* Battery ADC channel */ + zephyr,user { + io-channels = <&adc 7>; + vbat-mv-multiplier = <10650>; /* 1M/510k divider (2.96x), 3.6V ref */ + }; +}; + +®0 { + status = "okay"; +}; + +®1 { + regulator-initial-mode = ; +}; + +&adc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <12>; + }; +}; + +&uicr { + gpio-as-nreset; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +/* UART0 is not wired on this board — console/shell use USB-CDC */ +&uart0 { + status = "disabled"; +}; + +/* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors. + * + * Uses TWIM (not TWI) so the driver can issue SSD1306 page writes + * (1 cmd + 128 data = 129 bytes) in a single transaction — the + * concat-buf-size of 256 covers the full page. + */ +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + + /* Optional SSD1306 0.96" OLED at 0x3C. + * + * The Stick's OLED is optional per the ndoo.sg design. If the + * physical part is absent, zephcore's display helper returns + * -ENODEV and the firmware continues without a display — + * leaving the node declared unconditionally is safe. */ + ssd1306: ssd1306@3c { + compatible = "solomon,ssd1306"; + reg = <0x3c>; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + segment-remap; + com-invdir; + inversion-on; + prechargep = <0x22>; + }; + + /* All supported environment & power sensors — auto-detected at runtime */ + #include "../../common/sensors-i2c.dtsi" +}; + +/* SPI2 for LoRa module */ +&spi2 { + compatible = "nordic,nrf-spi"; + status = "okay"; + pinctrl-0 = <&spi2_default>; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; /* D4 = P0.04 NSS */ + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + spi-max-frequency = <8000000>; + + /* LoRa control pins */ + reset-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; /* D2 = P0.28 */ + busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; /* D3 = P0.29 */ + dio1-gpios = <&gpio0 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* D1 = P0.03 */ + + /* RXEN trace (no PA on this module; line is harmless to toggle) */ + rx-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; /* D5 = P0.05 RXEN */ + + /* Use DIO2 to drive TX enable on the internal RF switch */ + dio2-tx-enable; + + /* TCXO voltage 1.8V */ + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <10>; + + /* Enable RX boosted mode for better sensitivity */ + rx-boosted; + }; +}; + +/* QSPI Flash - disabled, matching the 30 dBm sibling. XIAO nRF52840's + * onboard P25Q16H is not used in this firmware; the internal nRF52840 + * flash provides storage. Re-enable with status = "okay" if needed. */ +&qspi { + status = "disabled"; +}; + +/* 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"; + }; +}; + +/* Arduino MeshCore compatible partition layout (SoftDevice v7) */ +#include "../../common/nrf52_partitions_sdv7.dtsi" + +/* Mark the 'buttons' node as a System OFF wakeup source. + * Only valid when the board has a `buttons` label (i.e. a user button). */ +#include "../../common/nrf52_wakeup.dtsi" diff --git a/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm_defconfig b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm_defconfig new file mode 100644 index 0000000..c53d57b --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_22dbm/ikoka_stick_22dbm_defconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: Apache-2.0 +# Ikoka Stick 22dBm default configuration + +# Enable MPU +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable console on USB CDC (new stack) +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# Enable flash/NVS storage +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y + +# Pinctrl +CONFIG_PINCTRL=y + +# SPI for LoRa +CONFIG_SPI=y + +# ADC for battery +CONFIG_ADC=y diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/Kconfig.ikoka_stick_30dbm b/zephcore/boards/nrf52840/ikoka_stick_30dbm/Kconfig.ikoka_stick_30dbm new file mode 100644 index 0000000..51b72a4 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/Kconfig.ikoka_stick_30dbm @@ -0,0 +1,5 @@ +# Ikoka Stick 30dBm board configuration +# DC/DC converter enabled via DTS: ®1 { regulator-initial-mode = ; } + +config BOARD_IKOKA_STICK_30DBM + select SOC_NRF52840_QIAA diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.conf b/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.conf new file mode 100644 index 0000000..76f938c --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.conf @@ -0,0 +1,36 @@ +# Ikoka Stick 30dBm (XIAO nRF52840 + E22-900M30S) +# Board-specific configuration +# +# Hardware: +# - XIAO nRF52840 base board (socketed via pin headers) +# - E22-900M30S LoRa module (SX1262 + external PA, 30 dBm / 1 W output) +# - User button on D0 (P0.02) +# - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected) +# - Battery ADC on AIN7 (P0.31), enable on P0.14 +# - LEDs: RED=P0.26, BLUE=P0.06, GREEN=P0.30 +# +# Pin Mapping (XIAO D-pins to nRF52840 GPIOs): +# D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) +# D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) +# D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) +# D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) +# +# LoRa Module E22-900M30S Notes: +# - Built-in ~10 dB PA with external RXEN control on P0.05 (HIGH=RX, LOW=TX). +# - DIO2 drives the internal TX/RX antenna switch (dio2-tx-enable). +# - SX1262 input power should not exceed 20 dBm (datasheet-typical drive +# for 30 dBm output). The caps below enforce this in firmware. + +# Board identification (matches Arduino variant name) +CONFIG_ZEPHCORE_BOARD_NAME="Ikoka Stick-E22-30dBm (Xiao_nrf52)" + +# Device Information Service model name +CONFIG_BT_DIS_MODEL_NUMBER_STR="Ikoka Stick 30dBm" + +# SoftDevice firmware ID (XIAO nRF52840 uses S140 v7.3.0) +CONFIG_ZEPHCORE_SD_FWID=0x0123 + +# SX1262 TX power caps — 20 dBm input yields ~30 dBm output through the +# E22-900M30S PA. +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=20 +CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=20 diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.yml b/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.yml new file mode 100644 index 0000000..a81bd1d --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/board.yml @@ -0,0 +1,6 @@ +board: + name: ikoka_stick_30dbm + full_name: Ikoka Stick 30dBm (XIAO nRF52840 + E22-900M30S) + vendor: ikoka + socs: + - name: nrf52840 diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm-pinctrl.dtsi b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm-pinctrl.dtsi new file mode 100644 index 0000000..3abea95 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm-pinctrl.dtsi @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 30dBm pin control - based on XIAO nRF52840 + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * UART0 is NOT wired on this board (console is USB-CDC). The pinctrl + * nodes below are kept so that upstream nRF52840 SoC defaults that + * reference &uart0_default/&uart0_sleep still resolve. &uart0 itself + * is disabled in the .dts to prevent the driver from driving pins. + * Dummy pins P0.08 / P0.09 are not brought out to a connector on XIAO. + */ + +&pinctrl { + /* UART0 placeholder — driver is disabled, pins are not brought out */ + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors */ + i2c1_default: i2c1_default { + group1 { + psels = , /* D6 = P1.11 */ + ; /* D7 = P1.12 */ + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* SPI2 for LoRa on D8/D9/D10 */ + spi2_default: spi2_default { + group1 { + psels = , /* D8 = P1.13 */ + , /* D10 = P1.15 */ + ; /* D9 = P1.14 */ + }; + }; + + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /* QSPI for onboard flash (disabled on XIAO nRF52840 — kept for symmetry) */ + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; +}; diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm.dts b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm.dts new file mode 100644 index 0000000..476275d --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm.dts @@ -0,0 +1,257 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 30dBm - XIAO nRF52840 + E22-900M30S LoRa module + * + * Reference: https://ndoo.sg/projects:amateur_radio:meshtastic:diy_devices:ikoka_stick + * + * E22-900M30S LoRa Module: + * - SX1262 with external ~10 dB PA, 30 dBm (1 W) output + * - RXEN (P0.05 / D5) control: HIGH for RX, LOW for TX + * - SX1262 input limited to 20 dBm (datasheet-typical drive for 30 dBm out) + * - DIO2 as RF switch, TCXO 1.8V + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * Peripherals: + * - User button on D0 with long-press (deep sleep) + multi-tap actions + * - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected at boot) + * - Battery ADC on AIN7 (P0.31), enable on P0.14 + * - LEDs: RED=P0.26/D11, BLUE=P0.06/D12, GREEN=P0.30/D13 + */ + +/dts-v1/; +#include +#include "ikoka_stick_30dbm-pinctrl.dtsi" +#include +#include + +/ { + model = "Ikoka Stick 30dBm"; + compatible = "ikoka,stick-30dbm"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &code_partition; + zephyr,console = &cdc_acm_uart; + zephyr,shell-uart = &cdc_acm_uart; + zephyr,display = &ssd1306; + }; + + aliases { + lora0 = &lora; + led0 = &led_red; + led1 = &led_green; + led2 = &led_blue; + watchdog0 = &wdt0; + }; + + /* Status LEDs - active LOW on XIAO */ + leds { + compatible = "gpio-leds"; + led_red: led_0 { + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led_green: led_1 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + led_blue: led_2 { + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + /* User button on D0 (P0.02), active LOW with internal pull-up. + * Matches the pinout of the Seeed XIAO nRF52840 base board. */ + buttons: buttons { + compatible = "gpio-keys"; + + user_button: button_0 { + gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "User Button"; + }; + }; + + /* Long-press = deep sleep (≥1 s), short = feeds into multi-tap */ + user_btn_longpress { + compatible = "zephyr,input-longpress"; + input = <&buttons>; + input-codes = ; + short-codes = ; + long-codes = ; + long-delay-ms = <1000>; + }; + + /* Multi-tap — standard ZephCore mapping: + * 1 tap → page next 2 taps → flood advert + * 3 taps → buzzer mute 4 taps → GPS toggle + * 5 taps → LED heartbeat */ + user_btn_multitap { + compatible = "zephcore,input-multi-tap"; + input-codes = ; + tap-codes = ; + tap-delay-ms = <400>; + }; + + /* Battery ADC enable - P0.14 must be LOW to read battery */ + vbat_enable: vbat-enable { + compatible = "regulator-fixed"; + regulator-name = "vbat-enable"; + enable-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; + + /* Battery ADC channel */ + zephyr,user { + io-channels = <&adc 7>; + vbat-mv-multiplier = <10650>; /* 1M/510k divider (2.96x), 3.6V ref */ + }; +}; + +®0 { + status = "okay"; +}; + +®1 { + regulator-initial-mode = ; +}; + +&adc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <12>; + }; +}; + +&uicr { + gpio-as-nreset; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +/* UART0 is not wired on this board — console/shell use USB-CDC */ +&uart0 { + status = "disabled"; +}; + +/* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors. + * + * Uses TWIM (not TWI) so the driver can issue SSD1306 page writes + * (1 cmd + 128 data = 129 bytes) in a single transaction — the + * concat-buf-size of 256 covers the full page. + */ +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + + /* Optional SSD1306 0.96" OLED at 0x3C. + * + * The Stick's OLED is optional per the ndoo.sg design. If the + * physical part is absent, zephcore's display helper returns + * -ENODEV and the firmware continues without a display — + * leaving the node declared unconditionally is safe. */ + ssd1306: ssd1306@3c { + compatible = "solomon,ssd1306"; + reg = <0x3c>; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + segment-remap; + com-invdir; + inversion-on; + prechargep = <0x22>; + }; + + /* All supported environment & power sensors — auto-detected at runtime */ + #include "../../common/sensors-i2c.dtsi" +}; + +/* SPI2 for LoRa module */ +&spi2 { + compatible = "nordic,nrf-spi"; + status = "okay"; + pinctrl-0 = <&spi2_default>; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; /* D4 = P0.04 NSS */ + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + spi-max-frequency = <8000000>; + + /* LoRa control pins */ + reset-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; /* D2 = P0.28 */ + busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; /* D3 = P0.29 */ + dio1-gpios = <&gpio0 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* D1 = P0.03 */ + + /* E22-900M30S PA control: HIGH = RX, LOW = TX */ + rx-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; /* D5 = P0.05 RXEN */ + + /* Use DIO2 to drive TX enable on the internal RF switch */ + dio2-tx-enable; + + /* TCXO voltage 1.8V */ + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <10>; + + /* Enable RX boosted mode for better sensitivity */ + rx-boosted; + }; +}; + +/* QSPI Flash - disabled, matching the 30 dBm sibling. XIAO nRF52840's + * onboard P25Q16H is not used in this firmware; the internal nRF52840 + * flash provides storage. Re-enable with status = "okay" if needed. */ +&qspi { + status = "disabled"; +}; + +/* 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"; + }; +}; + +/* Arduino MeshCore compatible partition layout (SoftDevice v7) */ +#include "../../common/nrf52_partitions_sdv7.dtsi" + +/* Mark the 'buttons' node as a System OFF wakeup source. + * Only valid when the board has a `buttons` label (i.e. a user button). */ +#include "../../common/nrf52_wakeup.dtsi" diff --git a/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm_defconfig b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm_defconfig new file mode 100644 index 0000000..bc2215f --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_30dbm/ikoka_stick_30dbm_defconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: Apache-2.0 +# Ikoka Stick 30dBm default configuration + +# Enable MPU +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable console on USB CDC (new stack) +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# Enable flash/NVS storage +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y + +# Pinctrl +CONFIG_PINCTRL=y + +# SPI for LoRa +CONFIG_SPI=y + +# ADC for battery +CONFIG_ADC=y diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/Kconfig.ikoka_stick_33dbm b/zephcore/boards/nrf52840/ikoka_stick_33dbm/Kconfig.ikoka_stick_33dbm new file mode 100644 index 0000000..b0d5421 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/Kconfig.ikoka_stick_33dbm @@ -0,0 +1,5 @@ +# Ikoka Stick 33dBm board configuration +# DC/DC converter enabled via DTS: ®1 { regulator-initial-mode = ; } + +config BOARD_IKOKA_STICK_33DBM + select SOC_NRF52840_QIAA diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.conf b/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.conf new file mode 100644 index 0000000..8f159ad --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.conf @@ -0,0 +1,36 @@ +# Ikoka Stick 33dBm (XIAO nRF52840 + E22-900M33S) +# Board-specific configuration +# +# Hardware: +# - XIAO nRF52840 base board (socketed via pin headers) +# - E22-900M33S LoRa module (SX1262 + PA, 33 dBm / 2 W output) +# - User button on D0 (P0.02) +# - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected) +# - Battery ADC on AIN7 (P0.31), enable on P0.14 +# - LEDs: RED=P0.26, BLUE=P0.06, GREEN=P0.30 +# +# Pin Mapping (XIAO D-pins to nRF52840 GPIOs): +# D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) +# D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) +# D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) +# D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) +# +# LoRa Module E22-900M33S Notes: +# - Built-in 33 dBm PA with external RXEN control on P0.05 (HIGH=RX, LOW=TX). +# - DIO2 drives the internal TX/RX antenna switch (dio2-tx-enable). +# - SX1262 input power MUST NEVER exceed 9 dBm — higher values will damage +# the module's RF frontend. The caps below enforce this in firmware. + +# Board identification (matches Arduino variant name) +CONFIG_ZEPHCORE_BOARD_NAME="Ikoka Stick-E22-33dBm (Xiao_nrf52)" + +# Device Information Service model name +CONFIG_BT_DIS_MODEL_NUMBER_STR="Ikoka Stick 33dBm" + +# SoftDevice firmware ID (XIAO nRF52840 uses S140 v7.3.0) +CONFIG_ZEPHCORE_SD_FWID=0x0123 + +# SX1262 TX power caps — 9 dBm input yields ~33 dBm output through the +# E22-900M33S PA. Exceeding 9 dBm risks permanent damage to the module. +CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=9 +CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=9 diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.yml b/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.yml new file mode 100644 index 0000000..6f95473 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/board.yml @@ -0,0 +1,6 @@ +board: + name: ikoka_stick_33dbm + full_name: Ikoka Stick 33dBm (XIAO nRF52840 + E22-900M33S) + vendor: ikoka + socs: + - name: nrf52840 diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm-pinctrl.dtsi b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm-pinctrl.dtsi new file mode 100644 index 0000000..9abaaca --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm-pinctrl.dtsi @@ -0,0 +1,99 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 33dBm pin control - based on XIAO nRF52840 + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * UART0 is NOT wired on this board (console is USB-CDC). The pinctrl + * nodes below are kept so that upstream nRF52840 SoC defaults that + * reference &uart0_default/&uart0_sleep still resolve. &uart0 itself + * is disabled in the .dts to prevent the driver from driving pins. + * Dummy pins P0.08 / P0.09 are not brought out to a connector on XIAO. + */ + +&pinctrl { + /* UART0 placeholder — driver is disabled, pins are not brought out */ + uart0_default: uart0_default { + group1 { + psels = ; + }; + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors */ + i2c1_default: i2c1_default { + group1 { + psels = , /* D6 = P1.11 */ + ; /* D7 = P1.12 */ + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* SPI2 for LoRa on D8/D9/D10 */ + spi2_default: spi2_default { + group1 { + psels = , /* D8 = P1.13 */ + , /* D10 = P1.15 */ + ; /* D9 = P1.14 */ + }; + }; + + spi2_sleep: spi2_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /* QSPI for onboard flash (disabled on XIAO nRF52840 — kept for symmetry) */ + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; +}; diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm.dts b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm.dts new file mode 100644 index 0000000..30a73b5 --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm.dts @@ -0,0 +1,258 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Ikoka Stick 33dBm - XIAO nRF52840 + E22-900M33S LoRa module + * + * Reference: https://ndoo.sg/projects:amateur_radio:meshtastic:diy_devices:ikoka_stick + * + * E22-900M33S LoRa Module: + * - SX1262 with integrated 33 dBm (2 W) PA + * - RXEN (P0.05 / D5) control: HIGH for RX, LOW for TX + * - SX1262 input power limited to 9 dBm (33 dBm output) — higher values + * will permanently damage the module's RF frontend. + * - DIO2 as RF switch, TCXO 1.8V + * + * Pin Mapping (XIAO D-pins to nRF52840 GPIOs): + * D0 = P0.02 (User button) D4 = P0.04 (SX1262 NSS) D8 = P1.13 (SCK) + * D1 = P0.03 (SX1262 DIO1) D5 = P0.05 (PA RXEN) D9 = P1.14 (MISO) + * D2 = P0.28 (SX1262 RESET) D6 = P1.11 (I2C SDA) D10 = P1.15 (MOSI) + * D3 = P0.29 (SX1262 BUSY) D7 = P1.12 (I2C SCL) + * + * Peripherals: + * - User button on D0 with long-press (deep sleep) + multi-tap actions + * - Optional SSD1306 0.96" OLED @ 0x3C on I2C1 (auto-detected at boot) + * - Battery ADC on AIN7 (P0.31), enable on P0.14 + * - LEDs: RED=P0.26/D11, BLUE=P0.06/D12, GREEN=P0.30/D13 + */ + +/dts-v1/; +#include +#include "ikoka_stick_33dbm-pinctrl.dtsi" +#include +#include + +/ { + model = "Ikoka Stick 33dBm"; + compatible = "ikoka,stick-33dbm"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &code_partition; + zephyr,console = &cdc_acm_uart; + zephyr,shell-uart = &cdc_acm_uart; + zephyr,display = &ssd1306; + }; + + aliases { + lora0 = &lora; + led0 = &led_red; + led1 = &led_green; + led2 = &led_blue; + watchdog0 = &wdt0; + }; + + /* Status LEDs - active LOW on XIAO */ + leds { + compatible = "gpio-leds"; + led_red: led_0 { + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led_green: led_1 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + led_blue: led_2 { + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + /* User button on D0 (P0.02), active LOW with internal pull-up. + * Matches the pinout of the Seeed XIAO nRF52840 base board. */ + buttons: buttons { + compatible = "gpio-keys"; + + user_button: button_0 { + gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + label = "User Button"; + }; + }; + + /* Long-press = deep sleep (≥1 s), short = feeds into multi-tap */ + user_btn_longpress { + compatible = "zephyr,input-longpress"; + input = <&buttons>; + input-codes = ; + short-codes = ; + long-codes = ; + long-delay-ms = <1000>; + }; + + /* Multi-tap — standard ZephCore mapping: + * 1 tap → page next 2 taps → flood advert + * 3 taps → buzzer mute 4 taps → GPS toggle + * 5 taps → LED heartbeat */ + user_btn_multitap { + compatible = "zephcore,input-multi-tap"; + input-codes = ; + tap-codes = ; + tap-delay-ms = <400>; + }; + + /* Battery ADC enable - P0.14 must be LOW to read battery */ + vbat_enable: vbat-enable { + compatible = "regulator-fixed"; + regulator-name = "vbat-enable"; + enable-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + regulator-boot-on; + }; + + /* Battery ADC channel */ + zephyr,user { + io-channels = <&adc 7>; + vbat-mv-multiplier = <10650>; /* 1M/510k divider (2.96x), 3.6V ref */ + }; +}; + +®0 { + status = "okay"; +}; + +®1 { + regulator-initial-mode = ; +}; + +&adc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_6"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <12>; + }; +}; + +&uicr { + gpio-as-nreset; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +/* UART0 is not wired on this board — console/shell use USB-CDC */ +&uart0 { + status = "disabled"; +}; + +/* I2C1 on D6/D7 for optional SSD1306 OLED and any external sensors. + * + * Uses TWIM (not TWI) so the driver can issue SSD1306 page writes + * (1 cmd + 128 data = 129 bytes) in a single transaction — the + * concat-buf-size of 256 covers the full page. + */ +&i2c1 { + compatible = "nordic,nrf-twim"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + + /* Optional SSD1306 0.96" OLED at 0x3C. + * + * The Stick's OLED is optional per the ndoo.sg design. If the + * physical part is absent, zephcore's display helper returns + * -ENODEV and the firmware continues without a display — + * leaving the node declared unconditionally is safe. */ + ssd1306: ssd1306@3c { + compatible = "solomon,ssd1306"; + reg = <0x3c>; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + segment-remap; + com-invdir; + inversion-on; + prechargep = <0x22>; + }; + + /* All supported environment & power sensors — auto-detected at runtime */ + #include "../../common/sensors-i2c.dtsi" +}; + +/* SPI2 for LoRa module */ +&spi2 { + compatible = "nordic,nrf-spi"; + status = "okay"; + pinctrl-0 = <&spi2_default>; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; /* D4 = P0.04 NSS */ + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + spi-max-frequency = <8000000>; + + /* LoRa control pins */ + reset-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; /* D2 = P0.28 */ + busy-gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; /* D3 = P0.29 */ + dio1-gpios = <&gpio0 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* D1 = P0.03 */ + + /* E22-900M33S PA control: HIGH = RX, LOW = TX */ + rx-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; /* D5 = P0.05 RXEN */ + + /* Use DIO2 to drive TX enable on the internal RF switch */ + dio2-tx-enable; + + /* TCXO voltage 1.8V */ + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <10>; + + /* Enable RX boosted mode for better sensitivity */ + rx-boosted; + }; +}; + +/* QSPI Flash - disabled, matching the 30 dBm sibling. XIAO nRF52840's + * onboard P25Q16H is not used in this firmware; the internal nRF52840 + * flash provides storage. Re-enable with status = "okay" if needed. */ +&qspi { + status = "disabled"; +}; + +/* 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"; + }; +}; + +/* Arduino MeshCore compatible partition layout (SoftDevice v7) */ +#include "../../common/nrf52_partitions_sdv7.dtsi" + +/* Mark the 'buttons' node as a System OFF wakeup source. + * Only valid when the board has a `buttons` label (i.e. a user button). */ +#include "../../common/nrf52_wakeup.dtsi" diff --git a/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm_defconfig b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm_defconfig new file mode 100644 index 0000000..61a69ff --- /dev/null +++ b/zephcore/boards/nrf52840/ikoka_stick_33dbm/ikoka_stick_33dbm_defconfig @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: Apache-2.0 +# Ikoka Stick 33dBm default configuration + +# Enable MPU +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable console on USB CDC (new stack) +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +# Enable flash/NVS storage +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y + +# Pinctrl +CONFIG_PINCTRL=y + +# SPI for LoRa +CONFIG_SPI=y + +# ADC for battery +CONFIG_ADC=y diff --git a/zephcore/boards/supported_boards.md b/zephcore/boards/supported_boards.md index 30781ab..c0e0aac 100644 --- a/zephcore/boards/supported_boards.md +++ b/zephcore/boards/supported_boards.md @@ -14,6 +14,9 @@ thinknode_m3 thinknode_m6 rak_wismesh_tag ikoka_nano_30dbm +ikoka_stick_22dbm +ikoka_stick_30dbm +ikoka_stick_33dbm sensecap_solar xiao_nrf52840 ```