mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-09 20:26:50 +00:00
initial port of heltec v4 and v4.3 boards
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
config HEAP_MEM_POOL_ADD_SIZE_BOARD
|
||||
int
|
||||
default 4096
|
||||
@@ -0,0 +1,3 @@
|
||||
config BOARD_HELTEC_WIFI_LORA32_V4
|
||||
select SOC_ESP32S3_WROOM_N16R2
|
||||
select SOC_ESP32S3_PROCPU if BOARD_HELTEC_WIFI_LORA32_V4_ESP32S3_PROCPU
|
||||
@@ -0,0 +1,7 @@
|
||||
if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*")
|
||||
set(OPENOCD OPENOCD-NOTFOUND)
|
||||
endif()
|
||||
find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH)
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake)
|
||||
@@ -0,0 +1,25 @@
|
||||
# Heltec WiFi LoRa 32 V4 — ESP32-S3, 16 MB flash, 2 MB QSPI PSRAM
|
||||
#
|
||||
# Hardware:
|
||||
# SX1262 + GC1109 external PA (10 dBm in → ~22 dBm out)
|
||||
# SSD1306 128x64 OLED on I2C0
|
||||
# User button on GPIO0
|
||||
#
|
||||
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf
|
||||
|
||||
# Board identification
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="Heltec V4"
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="Heltec WiFi LoRa 32 V4"
|
||||
|
||||
# Flash size — 16 MB (override esp32_common.conf 4 MB default)
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
|
||||
# Undocumented register 0x8B5 RX improvement (MeshCore PR#1398)
|
||||
# Described by Heltec engineer @Quency-D — improves RX on GC1109/KCT8103L PA boards.
|
||||
CONFIG_ZEPHCORE_SX126X_HELTEC_REG_PATCH=y
|
||||
|
||||
# TX power — SX1262 input to GC1109 PA.
|
||||
# 10 dBm → ~22 dBm radiated output (GC1109 ~12 dB gain).
|
||||
# Do not exceed 10 dBm into the PA to avoid compression.
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10
|
||||
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=10
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4 — ZephCore overlay
|
||||
*
|
||||
* The DTS already defines: SX1262 (lora0), SSD1306 OLED, button, LED, PWM,
|
||||
* vext_ctrl, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa ctrl: DIO1=14, BUSY=13, RESET=12
|
||||
* FEM: POWER=7, GC1109 CSD=2, CPS=46 (V4.2 — for V4.3/KCT8103L see heltec_wifi_lora32_v43)
|
||||
* Display I2C0: SDA=17, SCL=18, RST=21
|
||||
* Battery ADC: GPIO1 (ADC1 ch0), enable GPIO37, divider 100K/390K
|
||||
* Vext: GPIO36 (active-HIGH, powers OLED)
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
/* Native USB serial for ZephCore console/CLI */
|
||||
zephyr,console = &usb_serial;
|
||||
zephyr,shell-uart = &usb_serial;
|
||||
};
|
||||
|
||||
/* Battery ADC — ZephCore reads via zephyr,user { io-channels }.
|
||||
* Multiplier: 3300mV full-scale * 5.42x empirical divider = 17886 mV.
|
||||
* (Same as V3 — identical resistor divider topology.) */
|
||||
zephyr,user {
|
||||
io-channels = <&adc1 0>;
|
||||
vbat-mv-multiplier = <17886>;
|
||||
};
|
||||
|
||||
/* Battery ADC enable — ZephCore uses vbat_enable regulator alias.
|
||||
* GPIO37 (gpio1 pin 5) driven HIGH enables the ADC input path.
|
||||
* The DTS adc_ctrl node is power-domain-gpio which ZephCore doesn't use;
|
||||
* this regulator-fixed is the actual driver. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5 */
|
||||
};
|
||||
|
||||
/* ---- Button input filter chain ----
|
||||
* Button emits INPUT_KEY_0. Split into:
|
||||
* short press → KEY_A (consumed by multi-tap)
|
||||
* long press (1 s) → KEY_POWER (deep sleep) */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_POWER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap decodes short presses:
|
||||
* 1 tap (400 ms wait) → KEY_1 = page next
|
||||
* 2 taps (400 ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400 ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-device. */
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Enable native USB serial for console/CLI */
|
||||
&usb_serial {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Patch LoRa radio: add pull-down on DIO1 and enable RX boosted mode.
|
||||
* DTS defines antenna-enable, tx-enable, dio2-tx-enable, and TCXO already. */
|
||||
&lora0 {
|
||||
dio1-gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
rx-boosted;
|
||||
};
|
||||
|
||||
/* I2C sensors — auto-detected at runtime */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions — repartition 16 MB layout for ZephCore.
|
||||
* Delete lpcore slots, storage, scratch, and coredump to reclaim space.
|
||||
* Place LittleFS at 0xFA0000 - 0x1000000 (384 KB).
|
||||
*/
|
||||
/delete-node/ &slot0_lpcore_partition;
|
||||
/delete-node/ &slot1_lpcore_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
/delete-node/ &scratch_partition;
|
||||
/delete-node/ &coredump_partition;
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* LittleFS 384 KB for DataStore + file-based BLE settings */
|
||||
lfs_partition: partition@fa0000 {
|
||||
label = "lfs";
|
||||
reg = <0xFA0000 0x60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
@@ -0,0 +1,6 @@
|
||||
board:
|
||||
name: heltec_wifi_lora32_v4
|
||||
full_name: Heltec WiFi LoRa 32 V4
|
||||
vendor: heltec
|
||||
socs:
|
||||
- name: esp32s3
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4 — Pin Control Definitions
|
||||
*
|
||||
* Pin assignments (identical to V3):
|
||||
* UART0: TX=GPIO43, RX=GPIO44
|
||||
* I2C0: SDA=GPIO17, SCL=GPIO18 (SSD1306 OLED + sensors)
|
||||
* SPI2: SCLK=GPIO9, MOSI=GPIO10, MISO=GPIO11 (SX1262 LoRa)
|
||||
* LEDC0: CH0=GPIO35 (PWM LED)
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>
|
||||
|
||||
&pinctrl {
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
pinmux = <UART0_TX_GPIO43>;
|
||||
output-high;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART0_RX_GPIO44>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
pinmux = <I2C0_SDA_GPIO17>,
|
||||
<I2C0_SCL_GPIO18>;
|
||||
drive-open-drain;
|
||||
};
|
||||
};
|
||||
|
||||
spim2_default: spim2_default {
|
||||
group1 {
|
||||
pinmux = <SPIM2_MISO_GPIO11>,
|
||||
<SPIM2_SCLK_GPIO9>;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <SPIM2_MOSI_GPIO10>;
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
|
||||
ledc0_default: ledc0_default {
|
||||
group1 {
|
||||
pinmux = <LEDC_CH0_GPIO35>;
|
||||
output-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4 — ZephCore procpu DTS
|
||||
*
|
||||
* Hardware:
|
||||
* MCU: ESP32-S3 (16 MB flash, 2 MB QSPI PSRAM)
|
||||
* Radio: SX1262 on SPI2, GC1109 external PA/FEM (V4.2)
|
||||
* OLED: SSD1306 128x64 on I2C0
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35 (PWM via LEDC0)
|
||||
* Vext: GPIO36 active-HIGH (powers OLED and sensors)
|
||||
* BatADC: GPIO1 (ADC1 ch0), enable GPIO37 active-LOW
|
||||
*
|
||||
* V4.2 (this file) — GC1109 PA, TX_EN on GPIO46.
|
||||
* V4.3 (KCT8103L PA, CTX on GPIO5) → see heltec_wifi_lora32_v43.
|
||||
*
|
||||
* Key V4 differences vs V3:
|
||||
* - 16 MB flash + 2 MB QSPI PSRAM (was 8 MB, no PSRAM)
|
||||
* - External PA/FEM (GC1109):
|
||||
* GPIO7 = VFEM_Ctrl LDO power (active-HIGH, always-on)
|
||||
* GPIO2 = GC1109 CSD (chip enable, active-HIGH)
|
||||
* GPIO46 = GC1109 CPS (TX mode select, active-HIGH)
|
||||
* - Vext control is active-HIGH (was active-LOW on V3)
|
||||
* - DIO2 used as RF switch alongside external FEM TX control
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa ctrl: DIO1=14, BUSY=13, RESET=12
|
||||
* FEM: POWER=7, CSD=2, CPS=46
|
||||
* Display I2C0: SDA=17, SCL=18, RST=21
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <espressif/esp32s3/esp32s3_wroom_n16r2.dtsi>
|
||||
#include "heltec_wifi_lora32_v4-pinctrl.dtsi"
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/lora/sx126x.h>
|
||||
#include <espressif/partitions_0x0_amp_16M.dtsi>
|
||||
|
||||
/ {
|
||||
model = "Heltec WiFi LoRa 32 V4 PROCPU";
|
||||
compatible = "heltec,wifi-lora32-v4";
|
||||
|
||||
aliases {
|
||||
led0 = &led0;
|
||||
pwm-0 = &ledc0;
|
||||
pwm-led0 = &pwm_led_white;
|
||||
uart-0 = &uart0;
|
||||
i2c-0 = &i2c0;
|
||||
lora0 = &lora0;
|
||||
sw0 = &button0;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led0: led {
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; /* GPIO35 = gpio1 pin 3 */
|
||||
label = "White LED";
|
||||
};
|
||||
};
|
||||
|
||||
pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
pwm_led_white: pwm_led_gpio35 {
|
||||
label = "White PWM LED";
|
||||
pwms = <&ledc0 0 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
||||
};
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "USER Key";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
};
|
||||
|
||||
vbatt {
|
||||
compatible = "voltage-divider";
|
||||
io-channels = <&adc1 0>; /* GPIO1 = ADC1 ch0 */
|
||||
output-ohms = <100000>;
|
||||
full-ohms = <(100000 + 390000)>;
|
||||
};
|
||||
|
||||
/* Vext — powers OLED and external peripherals.
|
||||
* V4 DIFFERENCE: active-HIGH (GPIO36 HIGH = power on).
|
||||
* V3 was active-LOW on the same GPIO. */
|
||||
vext_ctrl: vext_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* GPIO36 = gpio1 pin 4 */
|
||||
#power-domain-cells = <0>;
|
||||
label = "Vext Control";
|
||||
};
|
||||
|
||||
/* ADC enable — GPIO37 (gpio1 pin 5) must be driven HIGH to read battery.
|
||||
* ZephCore uses the vbat_enable regulator alias for this. */
|
||||
adc_ctrl: adc_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5, active-LOW */
|
||||
#power-domain-cells = <0>;
|
||||
label = "ADC Control";
|
||||
};
|
||||
|
||||
/* FEM LDO power supply — GPIO7 powers the GC1109/KCT8103L LDO.
|
||||
* Must be HIGH before any radio operation. Keep always-on. */
|
||||
fem_power: fem-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fem-power";
|
||||
enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; /* VFEM_Ctrl = GPIO7 */
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram1;
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
zephyr,bt-hci = &esp32_bt_hci;
|
||||
zephyr,display = &ssd1306_128x64;
|
||||
};
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
current-speed = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Reduce CPU clock from 240 MHz to 160 MHz — saves power, HAL minimum */
|
||||
&cpu0 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&ledc0 {
|
||||
pinctrl-0 = <&ledc0_default>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel0@0 {
|
||||
reg = <0x0>;
|
||||
timer = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
ssd1306_128x64: display-controller@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>;
|
||||
reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; /* RST_OLED = GPIO21 */
|
||||
power-domains = <&vext_ctrl>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spim2_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; /* NSS = GPIO8 */
|
||||
|
||||
lora0: modem@0 {
|
||||
compatible = "semtech,sx1262";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio0 12 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW)>; /* RESET = GPIO12 */
|
||||
busy-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* BUSY = GPIO13 */
|
||||
dio1-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* DIO1 = GPIO14 */
|
||||
|
||||
/* External PA/FEM control (GC1109, V4.2):
|
||||
* GPIO2 = CSD (chip select/enable): driven HIGH during radio, LOW in sleep
|
||||
* GPIO46 = CPS (TX select): HIGH during TX, LOW during RX
|
||||
* V4.3 (KCT8103L) uses GPIO5 instead of GPIO46 — see heltec_wifi_lora32_v43. */
|
||||
antenna-enable-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; /* GC1109 CSD = GPIO2 */
|
||||
tx-enable-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; /* GC1109 CPS = GPIO46 = gpio1 pin 14 */
|
||||
|
||||
/* DIO2 drives the SX1262 internal RF switch (TX path select).
|
||||
* Combined with tx-enable-gpios, this keeps both the internal and
|
||||
* external PA switch in sync with no software intervention needed. */
|
||||
dio2-tx-enable;
|
||||
|
||||
/* TCXO 1.8V via DIO3 — same as V3 */
|
||||
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
||||
tcxo-power-startup-delay-ms = <5>;
|
||||
|
||||
spi-max-frequency = <4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&timer0 { status = "okay"; };
|
||||
&timer1 { status = "okay"; };
|
||||
&timer2 { status = "okay"; };
|
||||
&timer3 { status = "okay"; };
|
||||
|
||||
&wdt0 { status = "okay"; };
|
||||
&trng0 { status = "okay"; };
|
||||
|
||||
&esp32_bt_hci { status = "okay"; };
|
||||
&wifi { status = "okay"; };
|
||||
@@ -0,0 +1,12 @@
|
||||
# Heltec WiFi LoRa 32 V4 — minimal Zephyr defconfig (procpu)
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_CLOCK_CONTROL=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
@@ -0,0 +1,3 @@
|
||||
config HEAP_MEM_POOL_ADD_SIZE_BOARD
|
||||
int
|
||||
default 4096
|
||||
@@ -0,0 +1,3 @@
|
||||
config BOARD_HELTEC_WIFI_LORA32_V43
|
||||
select SOC_ESP32S3_WROOM_N16R2
|
||||
select SOC_ESP32S3_PROCPU if BOARD_HELTEC_WIFI_LORA32_V43_ESP32S3_PROCPU
|
||||
@@ -0,0 +1,7 @@
|
||||
if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*")
|
||||
set(OPENOCD OPENOCD-NOTFOUND)
|
||||
endif()
|
||||
find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH)
|
||||
|
||||
include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Heltec WiFi LoRa 32 V4.3 — ESP32-S3, 16 MB flash, 2 MB QSPI PSRAM
|
||||
#
|
||||
# Hardware:
|
||||
# SX1262 + KCT8103L external PA/FEM (GPIO5 CTX instead of GC1109 GPIO46 CPS)
|
||||
# SSD1306 128x64 OLED on I2C0
|
||||
# User button on GPIO0
|
||||
#
|
||||
# V4.3 vs V4.2: FEM chip changed GC1109 → KCT8103L, TX control pin GPIO46 → GPIO5.
|
||||
# Include order: prj.conf → zephcore_common.conf → esp32_common.conf → board.conf
|
||||
|
||||
# Board identification
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="Heltec V4.3"
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="Heltec WiFi LoRa 32 V4.3"
|
||||
|
||||
# Flash size — 16 MB (override esp32_common.conf 4 MB default)
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
|
||||
|
||||
# Undocumented register 0x8B5 RX improvement (MeshCore PR#1398)
|
||||
# Applies to both GC1109 and KCT8103L PA boards.
|
||||
CONFIG_ZEPHCORE_SX126X_HELTEC_REG_PATCH=y
|
||||
|
||||
# TX power — SX1262 input to KCT8103L PA.
|
||||
# 10 dBm → ~22 dBm radiated output (KCT8103L similar gain to GC1109).
|
||||
# Do not exceed 10 dBm into the PA to avoid compression.
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=10
|
||||
CONFIG_ZEPHCORE_MAX_TX_POWER_DBM=10
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4.3 — ZephCore overlay
|
||||
*
|
||||
* The DTS already defines: SX1262 (lora0), SSD1306 OLED, button, LED, PWM,
|
||||
* vext_ctrl, adc_ctrl, fem_power, I2C0, SPI2, BLE, WiFi.
|
||||
* This overlay adds ZephCore-specific integration on top.
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa ctrl: DIO1=14, BUSY=13, RESET=12
|
||||
* FEM: POWER=7, KCT8103L CSD=2, CTX=5
|
||||
* Display I2C0: SDA=17, SCL=18, RST=21
|
||||
* Battery ADC: GPIO1 (ADC1 ch0), enable GPIO37, divider 100K/390K
|
||||
* Vext: GPIO36 (active-HIGH, powers OLED)
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
/* Native USB serial for ZephCore console/CLI */
|
||||
zephyr,console = &usb_serial;
|
||||
zephyr,shell-uart = &usb_serial;
|
||||
};
|
||||
|
||||
/* Battery ADC — ZephCore reads via zephyr,user { io-channels }.
|
||||
* Multiplier: 3300mV full-scale * 5.42x empirical divider = 17886 mV.
|
||||
* (Same as V3 — identical resistor divider topology.) */
|
||||
zephyr,user {
|
||||
io-channels = <&adc1 0>;
|
||||
vbat-mv-multiplier = <17886>;
|
||||
};
|
||||
|
||||
/* Battery ADC enable — ZephCore uses vbat_enable regulator alias.
|
||||
* GPIO37 (gpio1 pin 5) driven HIGH enables the ADC input path.
|
||||
* The DTS adc_ctrl node is power-domain-gpio which ZephCore doesn't use;
|
||||
* this regulator-fixed is the actual driver. */
|
||||
vbat_enable: vbat-enable {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vbat-enable";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5 */
|
||||
};
|
||||
|
||||
/* ---- Button input filter chain ----
|
||||
* Button emits INPUT_KEY_0. Split into:
|
||||
* short press → KEY_A (consumed by multi-tap)
|
||||
* long press (1 s) → KEY_POWER (deep sleep) */
|
||||
user_btn_longpress {
|
||||
compatible = "zephyr,input-longpress";
|
||||
input = <&buttons>;
|
||||
input-codes = <INPUT_KEY_0>;
|
||||
short-codes = <INPUT_KEY_A>;
|
||||
long-codes = <INPUT_KEY_POWER>;
|
||||
long-delay-ms = <1000>;
|
||||
};
|
||||
|
||||
/* Multi-tap decodes short presses:
|
||||
* 1 tap (400 ms wait) → KEY_1 = page next
|
||||
* 2 taps (400 ms wait) → KEY_B = flood advert
|
||||
* 3 taps (400 ms wait) → KEY_D = buzzer mute toggle
|
||||
* 4 taps (immediate) → KEY_C = GPS on/off */
|
||||
user_btn_multitap {
|
||||
compatible = "zephcore,input-multi-tap";
|
||||
/* No 'input' phandle — listen to ALL devices.
|
||||
* KEY_A is emitted by the longpress pseudo-device. */
|
||||
input-codes = <INPUT_KEY_A>;
|
||||
tap-codes = <INPUT_KEY_1 INPUT_KEY_B INPUT_KEY_D INPUT_KEY_C>;
|
||||
tap-delay-ms = <400>;
|
||||
};
|
||||
};
|
||||
|
||||
/* Enable native USB serial for console/CLI */
|
||||
&usb_serial {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Patch LoRa radio: add pull-down on DIO1 and enable RX boosted mode.
|
||||
* DTS defines antenna-enable, tx-enable, dio2-tx-enable, and TCXO already. */
|
||||
&lora0 {
|
||||
dio1-gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
rx-boosted;
|
||||
};
|
||||
|
||||
/* I2C sensors — auto-detected at runtime */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions — repartition 16 MB layout for ZephCore.
|
||||
* Delete lpcore slots, storage, scratch, and coredump to reclaim space.
|
||||
* Place LittleFS at 0xFA0000 - 0x1000000 (384 KB).
|
||||
*/
|
||||
/delete-node/ &slot0_lpcore_partition;
|
||||
/delete-node/ &slot1_lpcore_partition;
|
||||
/delete-node/ &storage_partition;
|
||||
/delete-node/ &scratch_partition;
|
||||
/delete-node/ &coredump_partition;
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* LittleFS 384 KB for DataStore + file-based BLE settings */
|
||||
lfs_partition: partition@fa0000 {
|
||||
label = "lfs";
|
||||
reg = <0xFA0000 0x60000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
@@ -0,0 +1,6 @@
|
||||
board:
|
||||
name: heltec_wifi_lora32_v43
|
||||
full_name: Heltec WiFi LoRa 32 V4.3
|
||||
vendor: heltec
|
||||
socs:
|
||||
- name: esp32s3
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4.3 — Pin Control Definitions
|
||||
*
|
||||
* Pin assignments identical to V4.2 (GPIO5/CTX is plain GPIO, no pinctrl entry needed):
|
||||
* UART0: TX=GPIO43, RX=GPIO44
|
||||
* I2C0: SDA=GPIO17, SCL=GPIO18 (SSD1306 OLED + sensors)
|
||||
* SPI2: SCLK=GPIO9, MOSI=GPIO10, MISO=GPIO11 (SX1262 LoRa)
|
||||
* LEDC0: CH0=GPIO35 (PWM LED)
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-pinctrl.h>
|
||||
#include <zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h>
|
||||
|
||||
&pinctrl {
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
pinmux = <UART0_TX_GPIO43>;
|
||||
output-high;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART0_RX_GPIO44>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
pinmux = <I2C0_SDA_GPIO17>,
|
||||
<I2C0_SCL_GPIO18>;
|
||||
drive-open-drain;
|
||||
};
|
||||
};
|
||||
|
||||
spim2_default: spim2_default {
|
||||
group1 {
|
||||
pinmux = <SPIM2_MISO_GPIO11>,
|
||||
<SPIM2_SCLK_GPIO9>;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <SPIM2_MOSI_GPIO10>;
|
||||
output-low;
|
||||
};
|
||||
};
|
||||
|
||||
ledc0_default: ledc0_default {
|
||||
group1 {
|
||||
pinmux = <LEDC_CH0_GPIO35>;
|
||||
output-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Heltec WiFi LoRa 32 V4.3 — ZephCore procpu DTS
|
||||
*
|
||||
* Hardware:
|
||||
* MCU: ESP32-S3 (16 MB flash, 2 MB QSPI PSRAM)
|
||||
* Radio: SX1262 on SPI2, KCT8103L external PA/FEM
|
||||
* OLED: SSD1306 128x64 on I2C0
|
||||
* Button: GPIO0
|
||||
* LED: GPIO35 (PWM via LEDC0)
|
||||
* Vext: GPIO36 active-HIGH (powers OLED and sensors)
|
||||
* BatADC: GPIO1 (ADC1 ch0), enable GPIO37 active-LOW
|
||||
*
|
||||
* V4.3 vs V4.2 difference — FEM chip changed:
|
||||
* V4.2: GC1109 PA — TX_EN on GPIO46 (CPS)
|
||||
* V4.3: KCT8103L PA — CTX on GPIO5 (HIGH=TX, LOW=RX/LNA)
|
||||
* Detection: GPIO2 default pull differs (GC1109: pull-down, KCT8103L: pull-up)
|
||||
* (See MeshCore PR#1867, Heltec schematic HTIT-WB32LAF_V4.3)
|
||||
*
|
||||
* All other hardware is identical to V4.2:
|
||||
* GPIO7 = VFEM_Ctrl LDO power (active-HIGH, always-on)
|
||||
* GPIO2 = KCT8103L CSD (chip enable, active-HIGH)
|
||||
* GPIO5 = KCT8103L CTX (TX/RX select: HIGH=TX, LOW=RX/LNA) ← V4.3 change
|
||||
*
|
||||
* LoRa SPI2: SCLK=9, MOSI=10, MISO=11, NSS=8
|
||||
* LoRa ctrl: DIO1=14, BUSY=13, RESET=12
|
||||
* FEM: POWER=7, CSD=2, CTX=5
|
||||
* Display I2C0: SDA=17, SCL=18, RST=21
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <espressif/esp32s3/esp32s3_wroom_n16r2.dtsi>
|
||||
#include "heltec_wifi_lora32_v43-pinctrl.dtsi"
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zephyr/dt-bindings/lora/sx126x.h>
|
||||
#include <espressif/partitions_0x0_amp_16M.dtsi>
|
||||
|
||||
/ {
|
||||
model = "Heltec WiFi LoRa 32 V4.3 PROCPU";
|
||||
compatible = "heltec,wifi-lora32-v4_3";
|
||||
|
||||
aliases {
|
||||
led0 = &led0;
|
||||
pwm-0 = &ledc0;
|
||||
pwm-led0 = &pwm_led_white;
|
||||
uart-0 = &uart0;
|
||||
i2c-0 = &i2c0;
|
||||
lora0 = &lora0;
|
||||
sw0 = &button0;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led0: led {
|
||||
gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; /* GPIO35 = gpio1 pin 3 */
|
||||
label = "White LED";
|
||||
};
|
||||
};
|
||||
|
||||
pwmleds {
|
||||
compatible = "pwm-leds";
|
||||
pwm_led_white: pwm_led_gpio35 {
|
||||
label = "White PWM LED";
|
||||
pwms = <&ledc0 0 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
||||
};
|
||||
};
|
||||
|
||||
buttons: buttons {
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "USER Key";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
};
|
||||
|
||||
vbatt {
|
||||
compatible = "voltage-divider";
|
||||
io-channels = <&adc1 0>; /* GPIO1 = ADC1 ch0 */
|
||||
output-ohms = <100000>;
|
||||
full-ohms = <(100000 + 390000)>;
|
||||
};
|
||||
|
||||
/* Vext — powers OLED and external peripherals (active-HIGH, same as V4.2) */
|
||||
vext_ctrl: vext_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
enable-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; /* GPIO36 = gpio1 pin 4 */
|
||||
#power-domain-cells = <0>;
|
||||
label = "Vext Control";
|
||||
};
|
||||
|
||||
/* ADC enable — GPIO37 (gpio1 pin 5) must be driven HIGH to read battery */
|
||||
adc_ctrl: adc_ctrl {
|
||||
compatible = "power-domain-gpio";
|
||||
enable-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; /* GPIO37 = gpio1 pin 5, active-LOW */
|
||||
#power-domain-cells = <0>;
|
||||
label = "ADC Control";
|
||||
};
|
||||
|
||||
/* FEM LDO power supply — GPIO7 powers the KCT8103L LDO.
|
||||
* Must be HIGH before any radio operation. Keep always-on. */
|
||||
fem_power: fem-power {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fem-power";
|
||||
enable-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; /* VFEM_Ctrl = GPIO7 */
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram1;
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
zephyr,bt-hci = &esp32_bt_hci;
|
||||
zephyr,display = &ssd1306_128x64;
|
||||
};
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
current-speed = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Reduce CPU clock from 240 MHz to 160 MHz — saves power, HAL minimum */
|
||||
&cpu0 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
clock-frequency = <DT_FREQ_M(160)>;
|
||||
};
|
||||
|
||||
&ledc0 {
|
||||
pinctrl-0 = <&ledc0_default>;
|
||||
pinctrl-names = "default";
|
||||
status = "okay";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel0@0 {
|
||||
reg = <0x0>;
|
||||
timer = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
ssd1306_128x64: display-controller@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>;
|
||||
reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; /* RST_OLED = GPIO21 */
|
||||
power-domains = <&vext_ctrl>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spim2_default>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; /* NSS = GPIO8 */
|
||||
|
||||
lora0: modem@0 {
|
||||
compatible = "semtech,sx1262";
|
||||
reg = <0>;
|
||||
reset-gpios = <&gpio0 12 (GPIO_OPEN_DRAIN | GPIO_ACTIVE_LOW)>; /* RESET = GPIO12 */
|
||||
busy-gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* BUSY = GPIO13 */
|
||||
dio1-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* DIO1 = GPIO14 */
|
||||
|
||||
/* External PA/FEM control (KCT8103L, V4.3):
|
||||
* GPIO2 = CSD (chip enable): driven HIGH during radio, LOW in sleep
|
||||
* GPIO5 = CTX (TX/RX select): HIGH during TX, LOW during RX/LNA
|
||||
* V4.3 CHANGE: CTX moved from GPIO46 (GC1109 CPS) to GPIO5 (KCT8103L CTX). */
|
||||
antenna-enable-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; /* KCT8103L CSD = GPIO2 */
|
||||
tx-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; /* KCT8103L CTX = GPIO5 */
|
||||
|
||||
/* DIO2 drives the SX1262 internal RF switch (TX path select).
|
||||
* Combined with tx-enable-gpios, this keeps both the internal and
|
||||
* external PA switch in sync with no software intervention needed. */
|
||||
dio2-tx-enable;
|
||||
|
||||
/* TCXO 1.8V via DIO3 — same as V4.2 */
|
||||
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
||||
tcxo-power-startup-delay-ms = <5>;
|
||||
|
||||
spi-max-frequency = <4000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&timer0 { status = "okay"; };
|
||||
&timer1 { status = "okay"; };
|
||||
&timer2 { status = "okay"; };
|
||||
&timer3 { status = "okay"; };
|
||||
|
||||
&wdt0 { status = "okay"; };
|
||||
&trng0 { status = "okay"; };
|
||||
|
||||
&esp32_bt_hci { status = "okay"; };
|
||||
&wifi { status = "okay"; };
|
||||
@@ -0,0 +1,12 @@
|
||||
# Heltec WiFi LoRa 32 V4.3 — minimal Zephyr defconfig (procpu)
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_CLOCK_CONTROL=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
@@ -32,6 +32,13 @@ SWD flash: `west flash` (requires J-Link, pyocd, or nrfjprog connected).
|
||||
| XIAO ESP32-S3 | `west build -b xiao_esp32s3/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Station G2 | `west build -b station_g2/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Heltec V3 | `west build -b heltec_wifi_lora32_v3/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Heltec V4.2 (GC1109 PA) | `west build -b heltec_wifi_lora32_v4/esp32s3/procpu zephcore` | `west flash` |
|
||||
| Heltec V4.3 (KCT8103L PA) | `west build -b heltec_wifi_lora32_v43/esp32s3/procpu zephcore` | `west flash` |
|
||||
|
||||
**Heltec V4.2 vs V4.3:** The hardware revision is printed on the PCB silkscreen. If
|
||||
unclear, check GPIO2's default pull: the V4.2 GC1109 PA has an internal pull-down
|
||||
(GPIO2 reads LOW at boot), while the V4.3 KCT8103L PA has an internal pull-up
|
||||
(GPIO2 reads HIGH). Only difference in firmware: TX control pin GPIO46→GPIO5.
|
||||
|
||||
ESP32 flash uses esptool over USB. Hold BOOT button if device doesn't enter download mode.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user