Files
nRF52840_PTT/README.md
Krzysztof Cieślik a3464e05bd Add README
2026-05-21 19:59:55 +02:00

124 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ptt-fhss
Bare-metal PTT (Push-to-Talk) firmware for the **Seeed XIAO BLE (nRF52840)** with
frequency-hopping spread spectrum (FHSS) on the 2.4 GHz band.
Designed to be low-power, hard to detect, and built with a fully open toolchain —
no Zephyr, no Nordic SDK, no SoftDevice.
## Hardware
| Component | Part |
|-----------|------|
| Target | Seeed XIAO BLE (nRF52840) |
| Programmer | RP2040 running DAPLink |
## How it works
### FHSS
The radio hops across 40 channels (24022480 MHz, 2 MHz steps) every 2 ms.
The hopping sequence is generated by AES-128-ECB keyed with a shared secret —
both devices derive identical sequences independently without any synchronisation
traffic. To an observer with an SDR the transmissions appear as short, scattered
impulses with no identifiable pattern.
### Low power
The nRF52840 stays in SYSTEM_ON sleep (`WFI`) with the DC/DC converter active
(~1.5 µA quiescent). A GPIOTE edge event on the PTT button wakes the CPU;
the radio is active only during the burst.
### Register access
All hardware register writes use typed bitfield unions defined in `include/regs.h`
rather than raw bit-shift expressions. The union layout is guaranteed correct with
`arm-none-eabi-gcc` (LSB-first bitfields on Cortex-M).
## Toolchain
Everything that produces the binary runs inside a container. The host only needs
tools that talk to hardware (pyocd) or manage the build (just).
| Tool | Purpose | Install |
|------|---------|---------|
| podman or docker | Container runtime | distro package |
| just | Task runner | `cargo install just` or distro package |
| pyocd | Flash / debug via DAPLink | `pip install pyocd` |
| git | Source control + submodules | distro package |
Inside the container: `debian:bookworm-slim` + `gcc-arm-none-eabi` from apt +
`cmake` + `ninja`.
## Quick start
```sh
git clone <repo-url> ptt
cd ptt
git submodule update --init --depth=1
just build # build firmware.hex inside container
just flash # flash via DAPLink (host pyocd)
```
On first run `just build` pulls the container image and compiles. Subsequent
builds reuse the cached image and only recompile changed files.
## Tasks
```
just build compile firmware inside the container
just flash build + flash via DAPLink
just gdbserver start pyocd GDB server on port 3333
just clean remove build/
just clean-all remove build/ and the container image
```
## Project structure
```
.
├── Dockerfile container image (debian + arm-gcc from apt)
├── justfile build / flash / debug tasks
├── CMakeLists.txt
├── cmake/
│ └── arm-none-eabi.cmake CMake toolchain file
├── link/
│ └── nrf52840.ld linker script (no SoftDevice, Flash @ 0x00000000)
├── include/
│ ├── regs.h hardware register bitfield unions
│ ├── radio.h
│ ├── fhss.h
│ └── power.h
├── src/
│ ├── startup.c vector table (64 entries) + Reset_Handler
│ ├── main.c
│ ├── radio.c RADIO peripheral driver (stub)
│ ├── fhss.c AES-ECB hopping sequence generator
│ └── power.c DC/DC, GPIOTE wakeup, WFI sleep
└── vendor/
├── nrfx/ Nordic HAL headers, pinned to v2.9.0 (includes mdk/)
├── CMSIS_5/ ARM core headers (core_cm4.h etc.)
└── tiny-aes-c/ Public domain AES-128 implementation
```
## Before first flash
The XIAO BLE ships with a SoftDevice which occupies the start of Flash.
Erase it before flashing bare-metal firmware:
```sh
pyocd erase --target nrf52840 --chip
```
## Status
| Module | State |
|--------|-------|
| Startup / vector table | done |
| Linker script | done |
| Power management (sleep + wakeup) | done |
| FHSS sequence generator | done |
| RADIO driver | stub — TX loop not yet implemented |
| Sync protocol | not started |