mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-09 14:25:37 +00:00
thinknode m3 + wismesh tag ADC fix + fast advert for 1 min
This commit is contained in:
@@ -87,3 +87,4 @@ WEST_UPDATE.md
|
||||
|
||||
# Side projects (not part of main firmware)
|
||||
/doom/
|
||||
THINKNODE_M1_HANDOVER.md
|
||||
|
||||
@@ -210,7 +210,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 "wio_tracker" OR BOARD MATCHES "ikoka_nano" OR BOARD MATCHES "t1000_e" OR BOARD MATCHES "thinknode_m1")
|
||||
if(BOARD MATCHES ".*nrf52.*" OR BOARD MATCHES "rak4631" OR BOARD MATCHES "rak_wismesh_tag" 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")
|
||||
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")
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ config ZEPHCORE_BLE_ADV_SLOW_INTERVAL
|
||||
range 244 3200
|
||||
help
|
||||
Advertising interval in 0.625ms units.
|
||||
338 = 211.25ms (Apple-compliant, balanced discovery/battery).
|
||||
338 = 211.25ms (Apple-compliant, used after 60s fast window).
|
||||
|
||||
endmenu # BLE Configuration
|
||||
|
||||
|
||||
@@ -48,7 +48,9 @@ LOG_MODULE_REGISTER(zephcore_ble, CONFIG_ZEPHCORE_BLE_LOG_LEVEL);
|
||||
* BLE stack when the link is marginal, fast enough to recover quickly. */
|
||||
#define BLE_TX_OVERFLOW_RETRY_MS 250
|
||||
|
||||
/* Advertising interval (Apple Accessory Design Guidelines) */
|
||||
/* Advertising intervals (Apple Accessory Design Guidelines §5.5) */
|
||||
#define BT_ADV_FAST_INTERVAL 32 /* 20ms in 0.625ms units */
|
||||
#define BT_ADV_FAST_DURATION_MS (60 * 1000) /* fast window after boot/disconnect */
|
||||
#define BT_ADV_INTERVAL CONFIG_ZEPHCORE_BLE_ADV_SLOW_INTERVAL
|
||||
|
||||
/* ========== Frame type for queues ========== */
|
||||
@@ -116,6 +118,9 @@ static enum zephcore_iface active_iface = ZEPHCORE_IFACE_NONE;
|
||||
/* DLE tracking — set after successful DLE request to avoid double-request */
|
||||
static bool dle_requested;
|
||||
|
||||
/* Fast advertising — true for BT_ADV_FAST_DURATION_MS after boot or disconnect */
|
||||
static bool fast_adv_active;
|
||||
|
||||
|
||||
/* Runtime BLE passkey */
|
||||
static uint32_t ble_passkey = CONFIG_ZEPHCORE_BLE_PASSKEY;
|
||||
@@ -171,9 +176,11 @@ STRUCT_SECTION_ITERABLE(bt_nus_inst, secure_nus) = {
|
||||
|
||||
static void tx_drain_work_fn(struct k_work *work);
|
||||
static void overflow_retry_work_fn(struct k_work *work);
|
||||
static void adv_slow_work_fn(struct k_work *work);
|
||||
|
||||
K_WORK_DELAYABLE_DEFINE(tx_drain_work, tx_drain_work_fn);
|
||||
K_WORK_DELAYABLE_DEFINE(overflow_retry_work, overflow_retry_work_fn);
|
||||
K_WORK_DELAYABLE_DEFINE(adv_slow_work, adv_slow_work_fn);
|
||||
|
||||
/* ========== TX completion callback ========== */
|
||||
|
||||
@@ -262,6 +269,9 @@ static void connected(struct bt_conn *conn, uint8_t err)
|
||||
LOG_INF("connected: %s", addr);
|
||||
current_conn = bt_conn_ref(conn);
|
||||
|
||||
/* Cancel fast→slow transition — already connected, no need to switch */
|
||||
k_work_cancel_delayable(&adv_slow_work);
|
||||
|
||||
/* DLE is NOT requested here — the phone may start a PHY update LL
|
||||
* procedure immediately, and BLE allows only one at a time.
|
||||
* DLE is deferred to le_phy_updated() (after PHY negotiation completes)
|
||||
@@ -338,6 +348,8 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
static void recycled(void)
|
||||
{
|
||||
LOG_DBG("restart advertising");
|
||||
fast_adv_active = true;
|
||||
k_work_reschedule(&adv_slow_work, K_MSEC(BT_ADV_FAST_DURATION_MS));
|
||||
start_adv();
|
||||
}
|
||||
|
||||
@@ -750,20 +762,32 @@ static ssize_t secure_nus_rx_write(struct bt_conn *conn, const struct bt_gatt_at
|
||||
|
||||
/* ========== Advertising ========== */
|
||||
|
||||
static void adv_slow_work_fn(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
LOG_INF("fast adv window expired, switching to slow interval");
|
||||
bt_le_adv_stop();
|
||||
fast_adv_active = false;
|
||||
start_adv();
|
||||
}
|
||||
|
||||
static void start_adv(void)
|
||||
{
|
||||
uint16_t interval = fast_adv_active ? BT_ADV_FAST_INTERVAL : BT_ADV_INTERVAL;
|
||||
|
||||
struct bt_le_adv_param adv_param = {
|
||||
.id = BT_ID_DEFAULT,
|
||||
.options = BT_LE_ADV_OPT_CONN,
|
||||
.interval_min = BT_ADV_INTERVAL,
|
||||
.interval_max = BT_ADV_INTERVAL,
|
||||
.interval_min = interval,
|
||||
.interval_max = interval,
|
||||
};
|
||||
|
||||
int err = bt_le_adv_start(&adv_param, ad, ad_len, sd, sd_len);
|
||||
if (err && err != -EALREADY) {
|
||||
LOG_ERR("adv start failed: %d", err);
|
||||
} else {
|
||||
LOG_INF("BLE advertising: 211ms");
|
||||
LOG_INF("BLE advertising: %s",
|
||||
fast_adv_active ? "20ms fast (60s)" : "211ms slow");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -791,6 +815,8 @@ void zephcore_ble_start(const char *name)
|
||||
|
||||
build_device_name_and_adv(name);
|
||||
LOG_DBG("init complete, starting adv");
|
||||
fast_adv_active = true;
|
||||
k_work_reschedule(&adv_slow_work, K_MSEC(BT_ADV_FAST_DURATION_MS));
|
||||
start_adv();
|
||||
}
|
||||
|
||||
@@ -869,7 +895,9 @@ void zephcore_ble_set_enabled(bool enable)
|
||||
bt_le_adv_stop();
|
||||
LOG_INF("BLE disabled");
|
||||
} else {
|
||||
/* Re-enable advertising */
|
||||
/* Re-enable advertising — start fast window */
|
||||
fast_adv_active = true;
|
||||
k_work_reschedule(&adv_slow_work, K_MSEC(BT_ADV_FAST_DURATION_MS));
|
||||
start_adv();
|
||||
LOG_INF("BLE enabled");
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
/ {
|
||||
zephyr,user {
|
||||
io-channels = <&adc 3>;
|
||||
vbat-mv-multiplier = <4216>; /* RAK4631 voltage divider */
|
||||
vbat-mv-multiplier = <6161>; /* Arduino: (3 * 1.73 * 1.187 * 1000) ≈ 6161, GAIN_1_6 + 0.6V ref */
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -132,10 +132,12 @@
|
||||
};
|
||||
|
||||
/* ---- Battery ADC ---- */
|
||||
/* P0.05 (AIN3), same divider circuit as RAK4631 */
|
||||
/* P0.05 (AIN3), same divider circuit as RAK4631
|
||||
* Arduino ADC_MULTIPLIER = (3 * 1.73 * 1.187 * 1000) ≈ 6161,
|
||||
* applied to 12-bit average with default ref (GAIN_1_6 + 0.6V internal = 3.6V FS). */
|
||||
zephyr,user {
|
||||
io-channels = <&adc 3>;
|
||||
vbat-mv-multiplier = <4216>;
|
||||
vbat-mv-multiplier = <6161>;
|
||||
};
|
||||
|
||||
/* ---- Buzzer on PWM0 ---- */
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_THINKNODE_M3
|
||||
select SOC_NRF52840_QIAA
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
|
||||
|
||||
set(OPENOCD_NRF5_SUBFAMILY "nrf52")
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake)
|
||||
@@ -0,0 +1,35 @@
|
||||
# Elecrow ThinkNode M3 (nRF52840 + LR1110)
|
||||
# Board-specific configuration
|
||||
#
|
||||
# Hardware:
|
||||
# - nRF52840 SoC with BLE
|
||||
# - LR1110 LoRa radio (TCXO 3.3V, DIO5/DIO6 RF switch)
|
||||
# - GPS module on UART0 (9600 baud, 3-pin control)
|
||||
# - Battery ADC on AIN3 (P0.05), 2:1 voltage divider
|
||||
# - LEDs: GREEN=P1.03, RED=P1.01, POWER=P0.29
|
||||
# - Button on P0.12 (active-low, pull-up)
|
||||
# - Buzzer PWM on P0.23 with enable on P1.04
|
||||
|
||||
# Board identification (matches Arduino MeshCore variant name)
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="ThinkNode M3"
|
||||
|
||||
# Device Information Service model name
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="Elecrow ThinkNode-M3"
|
||||
|
||||
# SoftDevice firmware ID (ThinkNode M3 bootloader uses S140 v6, same as M1)
|
||||
CONFIG_ZEPHCORE_SD_FWID=0x00B6
|
||||
|
||||
# Radio type (TCXO, RF switch, PA config in DTS)
|
||||
CONFIG_ZEPHCORE_RADIO_LR1110=y
|
||||
|
||||
# SPI for LR1110
|
||||
CONFIG_SPI=y
|
||||
|
||||
# PWM for buzzer
|
||||
CONFIG_PWM=y
|
||||
|
||||
# ThinkNode M3 has no display — enable LED heartbeat
|
||||
CONFIG_ZEPHCORE_UI_DISPLAY=n
|
||||
|
||||
# RX duty cycle — note LR1110 guard is active, safe for battery-powered use
|
||||
CONFIG_ZEPHCORE_LORA_RX_DUTY_CYCLE=y
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* ThinkNode M3 board overlay - additional ZephCore-specific configuration
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* GPS control pins for the GPS module (chip TBD, generic NMEA at 9600 baud):
|
||||
* - GPS_POWER (P0.14) - Main power enable (always HIGH, gpio-hog)
|
||||
* - GPS_EN (P0.21) - Standby control (HIGH = awake, LOW = standby)
|
||||
* - GPS_RESET (P0.25) - Reset (GPS_RESET_ACTIVE = LOW, REINIT pin)
|
||||
*
|
||||
* Power enable pins (always HIGH):
|
||||
* - PIN_PWR_EN (P0.16) - Main power domain
|
||||
* - BAT_POWER (P0.17) - Battery power rail
|
||||
* - EEPROM_POWER (P0.07) - EEPROM power
|
||||
* - LED_POWER (P0.29) - Power LED (always on)
|
||||
*/
|
||||
|
||||
/ {
|
||||
/* GPS standby control - P0.21 (GPS_EN, HIGH = active/awake) */
|
||||
gps_en: gps-enable {
|
||||
compatible = "gpio-leds";
|
||||
gps_enable_pin: gps_enable {
|
||||
gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
|
||||
label = "GPS Enable";
|
||||
};
|
||||
};
|
||||
|
||||
aliases {
|
||||
gps-enable = &gps_enable_pin;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
/* GPS_POWER (P0.14) - always HIGH, main GPS power supply */
|
||||
gps-power-hog {
|
||||
gpio-hog;
|
||||
gpios = <14 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "GPS Power";
|
||||
};
|
||||
|
||||
/* PIN_PWR_EN (P0.16) - main power domain enable */
|
||||
pwr-en-hog {
|
||||
gpio-hog;
|
||||
gpios = <16 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "PWR Enable";
|
||||
};
|
||||
|
||||
/* BAT_POWER (P0.17) - battery power rail enable */
|
||||
bat-power-hog {
|
||||
gpio-hog;
|
||||
gpios = <17 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "BAT Power";
|
||||
};
|
||||
|
||||
/* EEPROM_POWER (P0.07) - EEPROM/sensor power */
|
||||
eeprom-power-hog {
|
||||
gpio-hog;
|
||||
gpios = <7 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "EEPROM Power";
|
||||
};
|
||||
|
||||
/* LED_POWER (P0.29) - power indicator LED, always on */
|
||||
led-power-hog {
|
||||
gpio-hog;
|
||||
gpios = <29 GPIO_ACTIVE_HIGH>;
|
||||
output-high;
|
||||
line-name = "LED Power";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board:
|
||||
name: thinknode_m3
|
||||
full_name: Elecrow ThinkNode M3 (nRF52840 + LR1110)
|
||||
vendor: elecrow
|
||||
socs:
|
||||
- name: nrf52840
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Elecrow ThinkNode M3 - Pin Control
|
||||
* Copyright (c) 2025 ZephCore
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Pin assignments from Arduino variant.h and platformio.ini:
|
||||
* - SPI: SCK=P1.13, MOSI=P1.14, MISO=P1.15, NSS=P1.12 (for LR1110)
|
||||
* - I2C: SDA=P0.26, SCL=P0.27
|
||||
* - UART0: TX=P0.22 (PIN_GPS_RX→GPS), RX=P0.20 (PIN_GPS_TX←GPS) at 9600 baud
|
||||
* - LR1110: DIO1=P1.08, BUSY=P1.11, RESET=P1.10
|
||||
* - PWM: P0.23 (buzzer, from PIN_BUZZER=23 in platformio.ini)
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
/* GPS UART0 - 9600 baud
|
||||
* Note: PIN_GPS_TX/RX naming is from GPS module's perspective in variant.h.
|
||||
* nRF UART TX → P0.22 (PIN_GPS_RX), nRF UART RX ← P0.20 (PIN_GPS_TX). */
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 22)>;
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(UART_RX, 0, 20)>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 22)>,
|
||||
<NRF_PSEL(UART_RX, 0, 20)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* I2C0 for on-board sensors */
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 27)>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_sleep: i2c0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 27)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* PWM0 for buzzer on P0.23 (PIN_BUZZER=23 from platformio.ini) */
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 23)>;
|
||||
};
|
||||
};
|
||||
|
||||
pwm0_sleep: pwm0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(PWM_OUT0, 0, 23)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
/* SPI1 for LR1110 - CS controlled manually (P1.12) */
|
||||
spi1_default: spi1_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
|
||||
<NRF_PSEL(SPIM_MISO, 1, 15)>;
|
||||
};
|
||||
};
|
||||
|
||||
spi1_sleep: spi1_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 1, 14)>,
|
||||
<NRF_PSEL(SPIM_MISO, 1, 15)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Elecrow ThinkNode M3 - nRF52840 + LR1110
|
||||
* Copyright (c) 2025 ZephCore
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Hardware (from Arduino variant.h / platformio.ini):
|
||||
* - nRF52840 SoC with BLE
|
||||
* - LR1110 LoRa radio on SPI1 (TCXO 3.3V, DIO5/DIO6 RF switch)
|
||||
* - GPS module on UART0 (9600 baud, generic NMEA; chip TBD)
|
||||
* Control: GPS_POWER=P0.14 (always on), GPS_EN=P0.21 (standby), GPS_RESET=P0.25
|
||||
* - Battery ADC on AIN3 (P0.05), 2:1 voltage divider
|
||||
* - LEDs: GREEN=P1.03, RED=P1.01 (active-low), POWER=P0.29 (always on via overlay)
|
||||
* - Button on P0.12 (active-low, pull-up), single button with multi-tap
|
||||
* - Buzzer PWM on P0.23 with enable on P1.04
|
||||
* - I2C on P0.26/P0.27 for on-board sensors
|
||||
* - Power enables: P0.16 (PWR_EN), P0.17 (BAT_POWER), P0.07 (EEPROM_POWER)
|
||||
* (all set HIGH via gpio-hogsn in board.overlay)
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
#include <nordic/nrf52840_partition.dtsi>
|
||||
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include "thinknode_m3-pinctrl.dtsi"
|
||||
|
||||
/* Delete default partitions from nrf52840_partition.dtsi */
|
||||
/delete-node/ &boot_partition;
|
||||
/delete-node/ &slot0_partition;
|
||||
/delete-node/ &slot1_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
|
||||
/ {
|
||||
model = "Elecrow ThinkNode M3";
|
||||
compatible = "elecrow,thinknode-m3";
|
||||
|
||||
chosen {
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
zephyr,shell-uart = &cdc_acm_uart;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led_green: led_0 {
|
||||
/* Active-low (LED_STATE_ON = LOW in Arduino variant.h) */
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
|
||||
label = "Green LED";
|
||||
};
|
||||
|
||||
led_red: led_1 {
|
||||
gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
|
||||
label = "Red LED";
|
||||
};
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
user_button: button_0 {
|
||||
/* Active-low (USER_BTN_PRESSED = LOW), internal pull-up */
|
||||
gpios = <&gpio0 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
label = "User Button";
|
||||
};
|
||||
};
|
||||
|
||||
/* Long-press detection (1000ms) */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_F>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap detection
|
||||
* 1 tap → KEY_1 = page next
|
||||
* 2 taps → KEY_B = flood advert
|
||||
* 3 taps → KEY_D = buzzer mute toggle
|
||||
* 4 taps → KEY_C = GPS on/off */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
|
||||
/* Battery ADC channel reference for ZephyrBoard
|
||||
* 2:1 voltage divider on AIN3 (P0.05).
|
||||
* With GAIN_1_6 + internal ref (3600mV full scale) × 2 = 7200 multiplier. */
|
||||
zephyr,user {
|
||||
io-channels = <&adc 3>;
|
||||
vbat-mv-multiplier = <7200>;
|
||||
};
|
||||
|
||||
/* Buzzer on PWM0 channel 0 (P0.23, PIN_BUZZER=23) */
|
||||
pwmbuzzer {
|
||||
compatible = "pwm-leds";
|
||||
buzzer: buzzer {
|
||||
pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Buzzer enable pin (P1.04, PIN_BUZZER_EN=36) */
|
||||
buzzer_enable: buzzer-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "buzzer-enable";
|
||||
enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
aliases {
|
||||
led0 = &led_green;
|
||||
led1 = &led_red;
|
||||
sw0 = &user_button;
|
||||
watchdog0 = &wdt0;
|
||||
buzzer = &buzzer;
|
||||
buzzer-enable = &buzzer_enable;
|
||||
lora0 = &lora;
|
||||
};
|
||||
};
|
||||
|
||||
®0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
®1 {
|
||||
regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Battery voltage on P0.05 (AIN3) - 2:1 voltage divider */
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
zephyr,gain = "ADC_GAIN_1_6";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
|
||||
zephyr,input-positive = <NRF_SAADC_AIN3>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
|
||||
&uicr {
|
||||
nfct-pins-as-gpios;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* PWM0 for buzzer on P0.23 */
|
||||
&pwm0 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&pwm0_default>;
|
||||
pinctrl-1 = <&pwm0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
/* GPS on UART0 (9600 baud)
|
||||
*
|
||||
* Using gnss-nmea-generic (passive NMEA listener) — the GPS chip is unknown
|
||||
* but the Arduino firmware uses MicroNMEA (generic NMEA parser only, no
|
||||
* proprietary commands). The module is controlled via 3 GPIOs in the overlay:
|
||||
* GPS_POWER=P0.14 (always on), GPS_EN=P0.21 (standby via gps-enable alias).
|
||||
*
|
||||
* zephyr,deferred-init: GPS module needs GPIO power-up (GPS_EN HIGH) before
|
||||
* NMEA output. ZephyrGPSManager handles power-up then calls device_init(). */
|
||||
&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 = "gnss-nmea-generic";
|
||||
zephyr,deferred-init;
|
||||
};
|
||||
};
|
||||
|
||||
/* I2C0 for on-board sensors */
|
||||
&i2c0 {
|
||||
compatible = "nordic,nrf-twim";
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
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"
|
||||
};
|
||||
|
||||
/* SPI1 for LR1110 */
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-0 = <&spi1_default>;
|
||||
pinctrl-1 = <&spi1_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
lora: lora@0 {
|
||||
compatible = "semtech,lr1110";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
busy-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
|
||||
dio1-gpios = <&gpio1 8 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
tcxo-voltage-mv = <1800>;
|
||||
tcxo-startup-delay-ms = <5>;
|
||||
rx-boosted;
|
||||
spi-max-frequency = <8000000>;
|
||||
/* RF switch: DIO5=bit0, DIO6=bit1
|
||||
* Table from Arduino target.cpp rfswitch_table:
|
||||
* STBY: DIO5=L, DIO6=L → 0x00
|
||||
* RX: DIO5=H, DIO6=L → 0x01
|
||||
* TX: DIO5=H, DIO6=H → 0x03
|
||||
* TX_HP: DIO5=L, DIO6=H → 0x02
|
||||
* GNSS: DIO5=L, DIO6=L → 0x00 */
|
||||
rfswitch-enable = <0x03>;
|
||||
rfswitch-standby = <0x00>;
|
||||
rfswitch-rx = <0x01>;
|
||||
rfswitch-tx = <0x03>;
|
||||
rfswitch-tx-hp = <0x02>;
|
||||
rfswitch-gnss = <0x00>;
|
||||
};
|
||||
};
|
||||
|
||||
zephyr_udc0: &usbd {
|
||||
compatible = "nordic,nrf-usbd";
|
||||
status = "okay";
|
||||
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
};
|
||||
};
|
||||
|
||||
/* SoftDevice v6 partition layout (S140 v6 — Adafruit nRF52 bootloader) */
|
||||
#include "../../common/nrf52_partitions_sdv6.dtsi"
|
||||
@@ -0,0 +1,20 @@
|
||||
identifier: thinknode_m3
|
||||
name: Elecrow ThinkNode M3 (nRF52840 + LR1110)
|
||||
type: mcu
|
||||
arch: arm
|
||||
ram: 256
|
||||
flash: 1024
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
supported:
|
||||
- adc
|
||||
- ble
|
||||
- gpio
|
||||
- i2c
|
||||
- nvs
|
||||
- spi
|
||||
- usb_device
|
||||
- watchdog
|
||||
vendor: elecrow
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2025 ZephCore
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable hardware stack protection
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
# Enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# Enable UART driver
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
# Enable console
|
||||
CONFIG_CONSOLE=y
|
||||
|
||||
# Build UF2 by default
|
||||
CONFIG_BUILD_OUTPUT_UF2=y
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
Reference in New Issue
Block a user