mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 21:08:19 +00:00
Add Lilygo T-beam 1.2 (SX1262)
This commit is contained in:
@@ -40,6 +40,7 @@ ESP32_boards=(
|
||||
heltec_wifi_lora32_v3/esp32s3/procpu
|
||||
heltec_wifi_lora32_v4/esp32s3/procpu
|
||||
heltec_wifi_lora32_v43/esp32s3/procpu
|
||||
ttgo_tbeam/esp32/procpu
|
||||
)
|
||||
|
||||
if [[ $1 == "nrf" ]]; then
|
||||
@@ -127,13 +128,40 @@ if [[ $1 == "esp32" ]]; then
|
||||
for board in "${ESP32_boards[@]}"; do
|
||||
board_clean_for_path=$(echo "$board" | sed -e 's/\//-/g')
|
||||
|
||||
if [[ $board =~ (esp32[^/]+) ]]; then
|
||||
if [[ $board =~ (esp32[^/]*) ]]; then
|
||||
chip="${BASH_REMATCH[1]}"
|
||||
else
|
||||
echo "Unknown chip for: $board"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
# Classic ESP32 (e.g. T-Beam, PICO-D4) cannot fit the mesh stack
|
||||
# alongside MCUboot in DRAM, so it uses Zephyr's simple-boot path: a
|
||||
# self-contained zephyr.bin flashed at the 0x1000 ROM bootloader offset.
|
||||
# The S3/C-series have the DRAM headroom and use sysbuild + MCUboot
|
||||
# (handled in the blocks below).
|
||||
if [[ $chip == "esp32" ]]; then
|
||||
if [[ $2 == "companions" ]]; then
|
||||
role="companion"
|
||||
echo "Now building $board companion (simple boot)"
|
||||
west build -b "$board" zephcore --pristine
|
||||
elif [[ $2 == "repeaters" ]]; then
|
||||
role="repeater"
|
||||
echo "Now building $board repeater (simple boot)"
|
||||
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Simple-boot zephyr.bin is already the complete bootable image;
|
||||
# wrap it in a full-flash merged image at the 0x1000 offset.
|
||||
python -m esptool --chip "$chip" merge-bin \
|
||||
--output firmware/"$board_clean_for_path"-"$role"-"$COMMIT_HASH"-merged.bin \
|
||||
--flash-mode dio --flash-freq 40m --flash-size 4MB \
|
||||
0x1000 build/zephyr/zephyr.bin
|
||||
cp build/zephyr/zephyr.bin firmware/"$board_clean_for_path"-"$role"-"$COMMIT_HASH".bin
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $2 == "companions" ]]; then
|
||||
# build ESP32 companions (production is the default)
|
||||
echo "Now building $board companion"
|
||||
|
||||
@@ -323,7 +323,13 @@ endif()
|
||||
# Enables WiFi AP + HTTP server + MCUboot image management.
|
||||
# Requires --sysbuild to build MCUboot alongside the app.
|
||||
# Non-ESP32 builds and companion builds are unaffected.
|
||||
if(ZEPHCORE_PLATFORM_CONF MATCHES "esp32_common" AND EXTRA_CONF_FILE MATCHES "repeater")
|
||||
#
|
||||
# Excluded on the classic ESP32 (e.g. T-Beam, board qualifier ".../esp32/..."):
|
||||
# its DRAM cannot fit the mesh stack alongside WiFi + MCUboot, so it uses the
|
||||
# simple-boot path and a CLI-only repeater (no WiFi OTA). The ESP32-S3/C-series
|
||||
# (esp32s3/esp32c*) keep WiFi OTA.
|
||||
if(ZEPHCORE_PLATFORM_CONF MATCHES "esp32_common" AND EXTRA_CONF_FILE MATCHES "repeater"
|
||||
AND NOT BOARD MATCHES "/esp32/")
|
||||
set(ZEPHCORE_WIFI_OTA_CONF "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/wifi_ota.conf")
|
||||
if(EXISTS ${ZEPHCORE_WIFI_OTA_CONF})
|
||||
list(APPEND ZEPHCORE_CONF_FILES ${ZEPHCORE_WIFI_OTA_CONF})
|
||||
|
||||
@@ -66,6 +66,18 @@ static const struct device *vbat_enable_dev = NULL;
|
||||
#define VBAT_ADC_SAMPLES 8
|
||||
#endif
|
||||
|
||||
/* Battery fuel gauge (AXP2101 PMU etc.) — preferred over the ADC divider when
|
||||
* present. Reports battery voltage and state-of-charge over I2C, so boards with
|
||||
* a PMU and no battery ADC (e.g. LilyGo T-Beam) still get battery telemetry. */
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(x_powers_axp2101_fuel_gauge)
|
||||
#include <zephyr/drivers/fuel_gauge.h>
|
||||
#define HAS_FUEL_GAUGE 1
|
||||
static const struct device *const fuel_gauge_dev =
|
||||
DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(x_powers_axp2101_fuel_gauge));
|
||||
#else
|
||||
#define HAS_FUEL_GAUGE 0
|
||||
#endif
|
||||
|
||||
/* Initialize TX LED GPIO at boot */
|
||||
#if HAS_TX_LED
|
||||
static int tx_led_init(void)
|
||||
@@ -82,7 +94,17 @@ namespace mesh {
|
||||
|
||||
uint16_t ZephyrBoard::getBattMilliVolts()
|
||||
{
|
||||
#if DT_NODE_EXISTS(DT_PATH(zephyr_user)) && \
|
||||
#if HAS_FUEL_GAUGE
|
||||
if (device_is_ready(fuel_gauge_dev)) {
|
||||
union fuel_gauge_prop_val val;
|
||||
int ret = fuel_gauge_get_prop(fuel_gauge_dev, FUEL_GAUGE_VOLTAGE, &val);
|
||||
if (ret == 0) {
|
||||
return (uint16_t)(val.voltage / 1000); /* µV -> mV */
|
||||
}
|
||||
LOG_WRN("Fuel gauge voltage read failed: %d", ret);
|
||||
}
|
||||
return 0;
|
||||
#elif DT_NODE_EXISTS(DT_PATH(zephyr_user)) && \
|
||||
DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
|
||||
if (!adc_is_ready_dt(&vbat_adc)) {
|
||||
LOG_ERR("ADC not ready");
|
||||
@@ -149,6 +171,18 @@ uint16_t ZephyrBoard::getBattMilliVolts()
|
||||
|
||||
uint8_t ZephyrBoard::getBattPercent()
|
||||
{
|
||||
#if HAS_FUEL_GAUGE
|
||||
if (device_is_ready(fuel_gauge_dev)) {
|
||||
union fuel_gauge_prop_val val;
|
||||
int ret = fuel_gauge_get_prop(fuel_gauge_dev,
|
||||
FUEL_GAUGE_RELATIVE_STATE_OF_CHARGE, &val);
|
||||
if (ret == 0) {
|
||||
return val.relative_state_of_charge;
|
||||
}
|
||||
LOG_WRN("Fuel gauge SoC read failed: %d", ret);
|
||||
}
|
||||
/* Fall through to the voltage-curve estimate if the gauge read fails. */
|
||||
#endif
|
||||
return battery_curve_lookup(&battery_curve_default, getBattMilliVolts());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# LilyGo T-Beam v1.2 — ESP32 (PICO-D4) + SX1262
|
||||
#
|
||||
# Hardware:
|
||||
# ESP32-PICO-D4 (4MB flash)
|
||||
# SX1262 on SPI3 (DIO2 RF switch, 1.8V TCXO via DIO3)
|
||||
# SSD1306 128x64 OLED on I2C0
|
||||
# AXP2101 PMU — powers LoRa (ALDO2) and GPS (ALDO3) rails, battery fuel gauge
|
||||
# NEO-6M / NEO-M8N GNSS on UART1
|
||||
#
|
||||
# Upstream Zephyr board: lilygo/ttgo_tbeam — that DTS models the SX1276 radio
|
||||
# variant; board.overlay overrides the radio to a native SX1262 on the same
|
||||
# SPI3 wiring. The AXP2101 MFD + regulator + fuel-gauge drivers are stock
|
||||
# Zephyr and auto-enable from the upstream DTS PMU nodes.
|
||||
#
|
||||
# Include order: prj.conf -> zephcore_common.conf -> esp32_common.conf -> board.conf
|
||||
|
||||
# Board identification
|
||||
CONFIG_ZEPHCORE_BOARD_NAME="LilyGo T-Beam"
|
||||
CONFIG_BT_DIS_MODEL_NUMBER_STR="LilyGo T-Beam v1.2"
|
||||
|
||||
# SX1262 — 22 dBm default TX power (matches Arduino LORA_TX_POWER)
|
||||
CONFIG_ZEPHCORE_DEFAULT_TX_POWER_DBM=22
|
||||
|
||||
# Battery via the AXP2101 fuel-gauge subsystem (voltage + state-of-charge over
|
||||
# I2C). CONFIG_REGULATOR (zephcore_common.conf) plus the AXP2101 MFD/regulator
|
||||
# drivers default-enable from the devicetree PMU nodes and bring the LoRa/GPS
|
||||
# rails up at boot from their regulator-boot-on/always-on properties.
|
||||
CONFIG_FUEL_GAUGE=y
|
||||
|
||||
# Flash mode: ESP32-PICO-D4 — use DIO, not QIO. PICO-D4 rev 1.0 hangs in the
|
||||
# QIO-enable SPI sequence (RTCWDT bootloop), same as handled for ttgo_lora32.
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=n
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_DIO=y
|
||||
|
||||
# Companion RAM budget — the classic ESP32 has a much smaller contiguous DRAM
|
||||
# segment than the ESP32-S3 boards, and the default contact/queue arrays
|
||||
# (350/256) overflow it. Use the Arduino MeshCore T-Beam companion sizes.
|
||||
CONFIG_ZEPHCORE_MAX_CONTACTS=160
|
||||
CONFIG_ZEPHCORE_MAX_CHANNELS=8
|
||||
CONFIG_ZEPHCORE_OFFLINE_QUEUE_SIZE=128
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
* LilyGo T-Beam v1.2 (SX1262) — ZephCore overlay
|
||||
*
|
||||
* The upstream Zephyr DTS (lilygo/ttgo_tbeam) targets the SX1276 radio
|
||||
* variant. The v1.2 board carries an SX1262 instead, on the same SPI3
|
||||
* wiring, so this overlay swaps the radio over to the native SX126x driver
|
||||
* and adds the SX1262-specific control pins.
|
||||
*
|
||||
* Pin mapping (Arduino MeshCore variants/lilygo_tbeam_SX1262):
|
||||
* LoRa SPI3: SCLK=5, MOSI=27, MISO=19, NSS=18
|
||||
* LoRa ctrl: RESET=23, BUSY=32 (gpio1 0), DIO1=33 (gpio1 1)
|
||||
* DIO2 = antenna RF switch, DIO3 = 1.8V TCXO
|
||||
* Display I2C0: SDA=21, SCL=22, SSD1306 @ 0x3C [base DTS]
|
||||
* PMU I2C0: AXP2101 @ 0x34 [base DTS]
|
||||
* GPS UART1: TX=12, RX=34, NEO-6M/M8N [base DTS]
|
||||
*
|
||||
* Power (AXP2101, brought up by the stock Zephyr regulator driver from the
|
||||
* base DTS regulator-boot-on/always-on properties):
|
||||
* DCDC1 = ESP32 + OLED (always-on)
|
||||
* ALDO2 = LoRa -> raised to 3.3V below (upstream 2.9-3.0V)
|
||||
* ALDO3 = GPS -> raised to 3.3V below (upstream 2.7-2.8V)
|
||||
* 3.3V matches the Arduino/Meshtastic reference firmware for this board.
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/lora/sx126x.h>
|
||||
|
||||
/*
|
||||
* BT HCI controller. The upstream ttgo_tbeam DTS does not select the ESP32 BT
|
||||
* HCI controller, so forcing CONFIG_BT=y would otherwise leave the Espressif
|
||||
* controller/PHY Kconfig half-configured (BT_ESP32 stays off). Enabling the HCI
|
||||
* node selects BT_ESP32, which in turn pulls in the shared PHY.
|
||||
*
|
||||
* WiFi is intentionally left disabled: the classic ESP32 cannot fit the mesh
|
||||
* stack alongside both the WiFi and BLE controllers in DRAM, and the companion
|
||||
* transport is BLE. (A WiFi-observer build would need its own RAM-trimmed conf.)
|
||||
*/
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,bt-hci = &esp32_bt_hci;
|
||||
};
|
||||
|
||||
aliases {
|
||||
/* GPIO4 LED blinks on LoRa TX, matching Arduino P_LORA_TX_LED=4
|
||||
* and Meshtastic LED_POWER=4. */
|
||||
lora-tx-led = &red_led;
|
||||
};
|
||||
};
|
||||
|
||||
&esp32_bt_hci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO4 LED is active-LOW on the T-Beam (Meshtastic LED_STATE_ON=0; Arduino
|
||||
* drives the pin LOW to light it). The upstream DTS marks it active-high, so
|
||||
* correct the polarity here — otherwise the TX LED logic is inverted.
|
||||
*/
|
||||
&red_led {
|
||||
gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* Swap the upstream SX1276 node to a native SX1262. */
|
||||
&lora0 {
|
||||
compatible = "semtech,sx1262";
|
||||
spi-max-frequency = <8000000>;
|
||||
|
||||
/delete-property/ dio-gpios;
|
||||
/delete-property/ power-amplifier-output;
|
||||
|
||||
/* RESET=GPIO23 inherited from base DTS; NSS=GPIO18 via spi3 cs-gpios. */
|
||||
busy-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; /* BUSY = GPIO32 */
|
||||
dio1-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* DIO1 = GPIO33 */
|
||||
|
||||
/* DIO2 drives the antenna TX/RX switch. */
|
||||
dio2-tx-enable;
|
||||
|
||||
/* 1.8V TCXO via DIO3 (matches Arduino SX126X_DIO3_TCXO_VOLTAGE=1.8). */
|
||||
dio3-tcxo-voltage = <SX126X_DIO3_TCXO_1V8>;
|
||||
tcxo-power-startup-delay-ms = <5>;
|
||||
|
||||
rx-boosted;
|
||||
};
|
||||
|
||||
/* LoRa rail (ALDO2): upstream 2.9-3.0V; reference firmware runs it at 3.3V. */
|
||||
&vdd_lora {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
/* GPS rail (ALDO3): upstream 2.7-2.8V; reference firmware runs it at 3.3V. */
|
||||
&vdd_gnss {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
/* I2C sensors — auto-detected at runtime (OLED + AXP2101 already in base DTS). */
|
||||
&i2c0 {
|
||||
#include "../../common/sensors-i2c.dtsi"
|
||||
};
|
||||
|
||||
/*
|
||||
* Flash partitions — repurpose the 192KB storage_partition (0x3B0000) as
|
||||
* LittleFS, same as ttgo_lora32. The 4MB AMP layout keeps its MCUboot slots.
|
||||
*/
|
||||
/delete-node/ &storage_partition;
|
||||
|
||||
&flash0 {
|
||||
partitions {
|
||||
/* LittleFS 192KB for DataStore (identity, prefs, creds) */
|
||||
lfs_partition: partition@3b0000 {
|
||||
label = "lfs";
|
||||
reg = <0x3B0000 0x30000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LittleFS auto-mount — standard /lfs mount point */
|
||||
#include "../../common/filesystem.dtsi"
|
||||
@@ -37,11 +37,17 @@ station_g2/esp32s3/procpu
|
||||
heltec_wifi_lora32_v3/esp32s3/procpu
|
||||
heltec_wifi_lora32_v4/esp32s3/procpu
|
||||
heltec_wifi_lora32_v43/esp32s3/procpu
|
||||
ttgo_tbeam/esp32/procpu
|
||||
```
|
||||
|
||||
> ESP32 boards require `west blobs fetch hal_espressif` before first build.
|
||||
>
|
||||
> Heltec V3 console/shell use `uart0` (UART serial) in ZephCore.
|
||||
>
|
||||
> **LilyGo T-Beam** (`ttgo_tbeam/esp32/procpu`): classic ESP32 (PICO-D4) with
|
||||
> SX1262, AXP2101 PMU, and GNSS. Use this for the **v1.2 SX1262** variant — the
|
||||
> upstream Zephyr DTS models the SX1276 radio, which ZephCore overrides to
|
||||
> SX1262 in `board.overlay`. Console/CLI are on `uart0` (onboard USB-UART).
|
||||
|
||||
## MG24 (Silicon Labs)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user