STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
frame.h
Go to the documentation of this file.
1/**
2 * @file frame.h
3 * @brief Over-the-air frame format for the LoRa command link.
4 *
5 * Layout (all multi-byte fields little-endian):
6 *
7 * byte 0 version (kFrameVersion)
8 * byte 1 type (FrameType)
9 * bytes 2-3 sequence (u16, +1 per frame sent, wraps)
10 * byte 4 length (payload bytes, 0..kFrameMaxPayload)
11 * bytes 5.. payload (layout depends on type)
12 * last 2 CRC-16/CCITT-FALSE over every byte before it
13 *
14 * The LoRa sync word is handled by the radio hardware and is not in the frame.
15 *
16 * Payloads:
17 * Heartbeat state u8, battery_mV u16, uptime_s u32 (7 bytes)
18 * SelfTest result_bits u16, battery_mV u16 (4 bytes)
19 * Arm key u32, ~key u32, target_id u8 (9 bytes)
20 * UnArm (empty) (0 bytes)
21 *
22 * Every number here is a proposal pending review (see README.md).
23 */
24#ifndef FRAME_H
25#define FRAME_H
26
27#include <stddef.h>
28#include <stdint.h>
29
30#include "radio.h"
31
32namespace radio_link {
33
34constexpr uint8_t kFrameVersion = 0x01;
35constexpr size_t kFrameHeaderLen = 5;
36constexpr size_t kFrameCrcLen = 2;
38// The biggest packet the radio can carry (the SX1262 buffer is 256 bytes).
39constexpr size_t kLoraMaxPacket = 255;
41constexpr size_t kFrameMaxLen = kFrameOverhead + kFrameMaxPayload; // 255
42
43static_assert(kFrameMaxLen <= kLoraMaxPacket,
44 "a frame must fit in one LoRa packet");
45
46enum class FrameType : uint8_t {
47 Heartbeat = 0x01, // rocket -> ground
48 SelfTest = 0x02, // rocket -> ground
49 Arm = 0x10, // ground -> rocket
50 UnArm = 0x11, // ground -> rocket
51};
52
53/** Required payload length per type. */
54constexpr uint8_t kHeartbeatLen = 7;
55constexpr uint8_t kSelfTestLen = 4;
56constexpr uint8_t kArmLen = 9;
57constexpr uint8_t kUnArmLen = 0;
58
59enum class FrameStatus : uint8_t {
60 Ok = 0,
61 ErrTooShort, // fewer than kFrameOverhead bytes
62 ErrVersion, // unknown version byte
63 ErrLength, // length field disagrees with bytes received
64 ErrCrc, // checksum mismatch
65 ErrType, // unknown type
66 ErrPayload, // payload size wrong for this type
67 ErrArgs, // bad pointer / capacity passed in
68};
69
70struct Frame {
72 uint16_t seq;
73 uint8_t payload_len;
75};
76
77/** CRC-16/CCITT-FALSE: poly 0x1021, init 0xFFFF, no reflection, no xorout.
78 * Check value: crc16("123456789") == 0x29B1. */
79uint16_t crc16(const uint8_t* data, size_t len);
80
81/**
82 * Parse and validate a received packet. On Ok, @p out is filled in.
83 * Checks, in order: size, version, length field, CRC, type, payload size.
84 * Nothing in @p out is valid unless Ok is returned.
85 */
86FrameStatus decode_frame(const uint8_t* buf, size_t len, Frame& out);
87
88/**
89 * Build a frame into out[0..out_cap). On Ok, @p out_len is the byte count.
90 * Payload size is checked against the type, so a malformed frame can't be sent.
91 */
92FrameStatus encode_frame(FrameType type, uint16_t seq, const uint8_t* payload,
93 uint8_t payload_len, uint8_t* out, size_t out_cap,
94 size_t& out_len);
95
96// Little-endian helpers (byte-wise: no alignment or struct-packing traps).
97void put_u16(uint8_t* p, uint16_t v);
98void put_u32(uint8_t* p, uint32_t v);
99uint16_t get_u16(const uint8_t* p);
100uint32_t get_u32(const uint8_t* p);
101
102} // namespace radio_link
103
104#endif // FRAME_H
int32_t p
Definition flight_e2e.c:78