STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
arm_gate.h
Go to the documentation of this file.
1/**
2 * @file arm_gate.h
3 * @brief Decides whether a valid frame is allowed to ARM or UN-ARM the rocket.
4 *
5 * Protects against accidents and noise, NOT a deliberate attacker (there is no
6 * secret). Rules for ARM:
7 * 1. key must equal kArmKey and the next field must equal ~kArmKey
8 * 2. target_id must match this rocket
9 * 3. sequence must be newer than the last ARM/UN_ARM seen (wrap-safe). The
10 * ground's counter must keep increasing across ground-station restarts;
11 * otherwise ARM is rejected until the rocket reboots (open decision,
12 * see README "Decisions for the lead").
13 * 4. a SECOND valid ARM with seq == first.seq + 1 must arrive within
14 * kArmConfirmWindowMs of the first; only then does on_frame() return Arm
15 * Any rejected ARM cancels a pending first ARM.
16 * UN_ARM is deliberately easy (disarming is the safe direction): always
17 * honored, cancels a pending ARM, and is not subject to the stale-sequence
18 * rule or the target id (any rocket in range disarms).
19 *
20 * The gate only says whether a command is valid. Whether arming is allowed
21 * right now (on the pad, in Idle, not in flight) is the state machine's call.
22 *
23 * Time is passed in (now_ms) so tests need no clock. Unsigned subtraction makes
24 * a wrapping 32-bit millisecond counter safe.
25 */
26#ifndef ARM_GATE_H
27#define ARM_GATE_H
28
29#include <stdint.h>
30
31#include "frame.h"
32
33namespace radio_link {
34
35/** PLACEHOLDER: lead to choose the real key before flight. */
36constexpr uint32_t kArmKey = 0xA5C3965Au;
37/** Max time between the two ARM frames. PLACEHOLDER pending review. */
38constexpr uint32_t kArmConfirmWindowMs = 2000;
39
40enum class ArmAction : uint8_t {
41 None = 0, // frame is not ARM/UN_ARM; gate ignores it
42 Pending, // valid first ARM; waiting for the confirm
43 Arm, // confirmed: arm now
44 Disarm, // UN_ARM honored
45 RejectKey, // key / inverse wrong
46 RejectTarget, // addressed to a different rocket
47 RejectStale, // sequence not newer than last seen
48};
49
50class ArmGate {
51public:
52 explicit ArmGate(uint8_t target_id) : target_id_(target_id) {
53 }
54
55 /** Feed one already-validated frame (decode_frame returned Ok). */
56 ArmAction on_frame(const Frame& f, uint32_t now_ms);
57
58 /** Call periodically so an unconfirmed ARM expires. */
59 void tick(uint32_t now_ms);
60
61 bool pending() const {
62 return pending_;
63 }
64
65private:
66 void note_seq(uint16_t seq);
67
68 uint8_t target_id_;
69 bool have_last_ = false; // any ARM/UN_ARM seen since boot?
70 uint16_t last_seq_ = 0; // newest ARM/UN_ARM sequence seen
71 bool pending_ = false; // first ARM accepted, awaiting confirm
72 uint16_t pending_seq_ = 0;
73 uint32_t pending_ms_ = 0;
74};
75
76} // namespace radio_link
77
78#endif // ARM_GATE_H
Over-the-air frame format for the LoRa command link.