docs: write LiquidCore15 telemetry interface reference

Replaces the stale JSON error with accurate documentation derived
from telemetry.h / telemetry.c — frame layout, payload field table,
FSM/fault enums, UART/UDP transmission details, and integration checklist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Andreas Johannsen 2026-04-27 16:06:42 +02:00
parent 48eb895f19
commit 2f1b63aeb5

View file

@ -1 +1,92 @@
{"errors":null,"message":"The target couldn't be found.","url":"https://git.daelon.cloud/api/swagger"} # Telemetry Interface
The LiquidCore15 firmware streams a continuous binary telemetry frame over **UART** and **UDP** at **100 Hz**, giving a host controller or operator GUI a real-time view of all monitored control variables.
---
## Frame Format
Every frame is exactly **63 bytes**:
| Byte(s) | Field | Value |
|---------|-------|-------|
| `[0]` | Sync low | `0x55` |
| `[1]` | Sync high | `0xAA` |
| `[2]` | Length | `0x3A` (58 decimal = payload size) |
| `[3..60]` | Payload | `TelemetryPayload_t` — 58 bytes, packed |
| `[61]` | CRC low | CRC16-CCITT low byte |
| `[62]` | CRC high | CRC16-CCITT high byte |
Sync bytes form the little-endian word `0xA55A` — check both bytes before decoding.
**CRC:** CRC16-CCITT (polynomial `0x1021`, init `0xFFFF`) computed over bytes `[2..60]` (59 bytes: length byte + full payload). No output inversion.
---
## Payload Fields
`TelemetryPayload_t` is `__attribute__((packed))`, 58 bytes. Field order is stable — the host decoder assumes this exact layout.
| Offset | Type | Field | Description |
|--------|------|-------|-------------|
| 0 | `float` | `Vdc` | DC bus voltage (V) |
| 4 | `float` | `Ia` | Phase A current (A) |
| 8 | `float` | `Ib` | Phase B current (A) |
| 12 | `float` | `Ic` | Phase C current (A) |
| 16 | `float` | `Va` | Phase A grid voltage (V) |
| 20 | `float` | `Vb` | Phase B grid voltage (V) |
| 24 | `float` | `Vc` | Phase C grid voltage (V) |
| 28 | `float` | `Id` | d-axis current feedback (A) |
| 32 | `float` | `Iq` | q-axis current feedback (A) |
| 36 | `float` | `Id_ref` | d-axis current reference (A) |
| 40 | `float` | `Iq_ref` | q-axis current reference (A) |
| 44 | `float` | `theta` | PLL grid angle (rad, 0 .. 2π) |
| 48 | `float` | `omega` | PLL angular frequency (rad/s) |
| 52 | `uint8_t` | `pll_locked` | `1` = locked, `0` = searching |
| 53 | `uint8_t` | `mode` | FSM state (see below) |
| 54 | `uint32_t` | `fault_flags` | Active fault bitmask (see below) |
All floats are IEEE 754 single-precision, little-endian (Cortex-M native byte order).
### `mode` — FSM State
| Value | State |
|-------|-------|
| `0x00` | `FSM_INIT` |
| `0x01` | `READY` |
| `0x02` | `RUNNING` |
| `0x03` | `FAULT` |
### `fault_flags` — Fault Bitmask
| Bit | Fault |
|-----|-------|
| 0 | Over-voltage (OV) |
| 1 | Under-voltage (UV) |
| 2 | Over-current (OC) |
| 3 | Frequency high |
| 4 | Frequency low |
---
## Transmission
**UART:** USART3 (`hcom_uart[COM1]`), 115200 baud, GPDMA1 Channel 0 (DMA mode).
- Cadence: every 160th control tick → **100 Hz**.
- If UART DMA is busy when a frame is ready, the frame is **dropped silently**. At 100 Hz × 63 bytes = 6 300 bytes/s versus 11 520 bytes/s line capacity, collision probability is low.
- Double-buffering: two 63-byte buffers swap between fill and DMA-in-flight roles.
**UDP:** The same 63-byte frame is forwarded to `eth_send_telem()` (implemented in `eth.c`) on every tick, independent of UART DMA state.
---
## Integration Checklist
- [ ] Open a 115200-baud serial connection to USART3 (or listen on the UDP socket).
- [ ] Scan the byte stream for the two-byte sync sequence `0x55 0xAA`.
- [ ] Read the next 61 bytes (length + payload + CRC).
- [ ] Verify CRC16-CCITT over bytes `[2..60]`; discard frame on mismatch.
- [ ] Deserialize `TelemetryPayload_t` in the field order above (little-endian floats).
- [ ] Check `pll_locked` before using `theta` / `omega` for phase-sensitive calculations.
- [ ] Check `fault_flags != 0` and handle `mode == 0x03` (FAULT) before commanding.