Add README
This commit is contained in:
123
README.md
Normal file
123
README.md
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# 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 (2402–2480 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 |
|
||||||
Reference in New Issue
Block a user