Files
ZephCore/build.sh
T
rlwilliamson-dev 568d311ab0 boards: add GAT562 30S Mesh Kit (nRF52840, RAK4631 core)
The GAT562 30S Mesh Kit is an nRF52840 + SX1262 board built on the
RAK4631 WisBlock core module with a 30 dBm (1 W) external PA, so it
reuses the proven rak4631 LoRa path. Deltas vs rak4631: 1.8 V TCXO
(per the MeshCore variant), battery multiplier 6232, buzzer on P1.01,
an AT6558R UART GPS, active-high LEDs, and a 5-way joystick that
selects the joystick companion menu UI.

A single board serves both the full kit and the screenless solar
repeater pod; absent peripherals (OLED, GPS, joystick, buzzer) are
optional in devicetree and skipped at runtime.

Board-specific notes:
- GPS: AT6558R NMEA on UART0 @ 9600 (P0.15 RX / P0.16 TX), powered by a
  WB_IO2/P1.02 gpio-hog and parsed by gnss-nmea-generic. Uses
  CONFIG_UART_ASYNC_API (DMA receive); nRF UARTE interrupt-driven RX did
  not feed the modem backend.
- The 6 button/joystick inputs are routed to GPIO SENSE (sense-edge-mask
  on &gpio0) so they don't consume the GPIOTE channel the SX1262 DIO1
  "done" IRQ needs.

Registration: board definition, CMakeLists.txt platform-conf match,
build.sh (nRF_boards), supported_boards.md, the top-level README board
table, and the porting-guide board table.

Hardware-tested on the kit, companion and repeater: LoRa TX/RX with BLE
active (no CAD errors), BLE pairing (PIN 123456) and two-way messaging,
joystick menu UI, SSD1306 OLED, buzzer, battery %, UF2 + DFU-zip
flashing, and a 14-satellite GPS fix.
2026-06-02 11:28:44 -05:00

171 lines
6.1 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
mkdir -p firmware
COMMIT_HASH=$(git rev-parse --short HEAD)
nRF_boards=(
rak4631
rak3401_1watt
wio_tracker_l1
t1000_e
thinknode_m1
thinknode_m3
thinknode_m6
rak_wismesh_tag
ikoka_nano_30dbm
sensecap_solar
xiao_nrf52840
lilygo_techo
promicro_sx1262
heltec_t114
gat562_30s
)
ESP32_boards=(
xiao_esp32c3
xiao_esp32c6/esp32c6/hpcore
xiao_esp32s3/esp32s3/procpu
lilygo_tlora_c6/esp32c6/hpcore
station_g2/esp32s3/procpu
heltec_wifi_lora32_v3/esp32s3/procpu
heltec_wifi_lora32_v4/esp32s3/procpu
heltec_wifi_lora32_v43/esp32s3/procpu
)
if [[ $1 == "nrf" ]]; then
for board in "${nRF_boards[@]}"; do
board_clean_for_path=$(echo "$board" | sed -e 's/\//-/g')
# build nRF companions (production is the default — no extra conf needed)
echo "Now building $board companion"
if [[ $board == "wio_tracker_l1" ]]; then
west build -b "$board" zephcore --pristine -- -DCONFIG_ZEPHCORE_EASTER_EGG_DOOM=y
else
west build -b "$board" zephcore --pristine
fi
mv build/zephyr/zephyr.uf2 firmware/"$board"-companion-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-companion-"$COMMIT_HASH".zip
# build nRF repeaters
echo "Now building $board repeater"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-repeater-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-repeater-"$COMMIT_HASH".zip
# Heltec T114 is sold both with and without the TFT module.
# Build dedicated screenless variants matching upstream's
# Heltec_t114_without_display_* PIO envs.
if [[ $board == "heltec_t114" ]]; then
echo "Now building $board companion (noscreen)"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/nrf52840/heltec_t114/no_display.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-companion-noscreen-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-companion-noscreen-"$COMMIT_HASH".zip
echo "Now building $board repeater (noscreen)"
west build -b "$board" zephcore --pristine -- -DEXTRA_CONF_FILE="boards/common/repeater.conf;boards/nrf52840/heltec_t114/no_display.conf"
mv build/zephyr/zephyr.uf2 firmware/"$board"-repeater-noscreen-"$COMMIT_HASH".uf2
mv build/zephyr/zephyr.zip firmware/"$board"-repeater-noscreen-"$COMMIT_HASH".zip
fi
done
fi
if [[ $1 == "esp32" ]]; then
for board in "${ESP32_boards[@]}"; do
board_clean_for_path=$(echo "$board" | sed -e 's/\//-/g')
if [[ $board =~ (esp32[^/]+) ]]; then
chip="${BASH_REMATCH[1]}"
else
echo "Unknown chip for: $board"
exit 1;
fi
if [[ $2 == "companions" ]]; then
# build ESP32 companions (production is the default)
echo "Now building $board companion"
west build -b "$board" zephcore --pristine --sysbuild
FLASH_SIZE=$(
python3 -c '
import re
import sys
path = sys.argv[1] if len(sys.argv) > 1 else "build/zephcore/zephyr/zephyr.dts"
dts = open(path, encoding="utf-8", errors="replace").read()
def parse_cell(tok: str) -> int:
t = tok.strip()
return int(t, 16) if t.lower().startswith("0x") else int(t)
m = re.search(
r"flash0:\s*flash@[^{]*\{[^}]*?reg\s*=\s*<\s*(?:0x[0-9a-fA-F]+|[0-9]+)\s+"
r"((?:0x)?[0-9a-fA-F]+)\s*>",
dts,
re.DOTALL,
)
if not m:
m = re.search(
r"compatible\s*=\s*\"soc-nv-flash\"\s*;\s*[\s\S]*?"
r"reg\s*=\s*<\s*(?:0x[0-9a-fA-F]+|[0-9]+)\s+((?:0x)?[0-9a-fA-F]+)\s*>",
dts,
)
if not m:
raise SystemExit("flash reg not found in " + path)
size = parse_cell(m.group(1))
print(str(size // 1048576) + "MB")
' "${ZEPHYR_DTS:-build/zephcore/zephyr/zephyr.dts}"
)
python -m esptool --chip "$chip" merge-bin \
--output firmware/"$board_clean_for_path"-companion-"$COMMIT_HASH"-merged.bin \
--flash-mode dio --flash-freq 40m --flash-size "$FLASH_SIZE" \
0x00000 build/mcuboot/zephyr/zephyr.bin \
0x20000 build/zephcore/zephyr/zephyr.signed.bin
mv build/zephcore/zephyr/zephyr.signed.bin firmware/"$board_clean_for_path"-companion-"$COMMIT_HASH".bin
fi
if [[ $2 == "repeaters" ]]; then
# build ESP32 repeaters
echo "Now building $board repeater"
west build -b "$board" zephcore --pristine --sysbuild -- -DEXTRA_CONF_FILE="boards/common/repeater.conf"
FLASH_SIZE=$(
python3 -c '
import re
import sys
path = sys.argv[1] if len(sys.argv) > 1 else "build/zephcore/zephyr/zephyr.dts"
dts = open(path, encoding="utf-8", errors="replace").read()
def parse_cell(tok: str) -> int:
t = tok.strip()
return int(t, 16) if t.lower().startswith("0x") else int(t)
m = re.search(
r"flash0:\s*flash@[^{]*\{[^}]*?reg\s*=\s*<\s*(?:0x[0-9a-fA-F]+|[0-9]+)\s+"
r"((?:0x)?[0-9a-fA-F]+)\s*>",
dts,
re.DOTALL,
)
if not m:
m = re.search(
r"compatible\s*=\s*\"soc-nv-flash\"\s*;\s*[\s\S]*?"
r"reg\s*=\s*<\s*(?:0x[0-9a-fA-F]+|[0-9]+)\s+((?:0x)?[0-9a-fA-F]+)\s*>",
dts,
)
if not m:
raise SystemExit("flash reg not found in " + path)
size = parse_cell(m.group(1))
print(str(size // 1048576) + "MB")
' "${ZEPHYR_DTS:-build/zephcore/zephyr/zephyr.dts}"
)
python -m esptool --chip "$chip" merge-bin \
--output firmware/"$board_clean_for_path"-repeater-"$COMMIT_HASH"-merged.bin \
--flash-mode dio --flash-freq 40m --flash-size "$FLASH_SIZE" \
0x00000 build/mcuboot/zephyr/zephyr.bin \
0x20000 build/zephcore/zephyr/zephyr.signed.bin
mv build/zephcore/zephyr/zephyr.signed.bin firmware/"$board_clean_for_path"-repeater-"$COMMIT_HASH".bin
fi
done
fi