STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
DiabloPackets.h
Go to the documentation of this file.
1#pragma once
2
3#include "DiabloEnums.h"
4#include <stdint.h>
5#include <vector>
6
7namespace daq {
8
9/**
10 * @brief The standard 6-byte header preceding every packet.
11 */
12struct __attribute__((packed)) PacketHeader {
13 PacketType packet_type; // 1 byte
14 uint8_t version; // 1 byte
15 uint32_t timestamp; // 4 bytes
16};
17
18//==============================================================================
19// Board Heartbeat
20//==============================================================================
21
22/**
23 * @brief Body of a Board Heartbeat packet. Sent from a board to the server.
24 */
25struct __attribute__((packed)) BoardHeartbeatPacket {
26 uint8_t firmware_hash[32]; // SHA-256 hash of the firmware binary
27 uint8_t board_id;
28 EngineState engine_state;
29 BoardState board_state;
30};
31
32//==============================================================================
33// Server Heartbeat
34//==============================================================================
35
36/**
37 * @brief Body of a Server Heartbeat packet. Sent from the server to all boards.
38 */
39struct __attribute__((packed)) ServerHeartbeatPacket {
40 EngineState engine_state;
41};
42
43//==============================================================================
44// Sensor Data
45//
46// Variable length, but having structs separate is so we can read them from
47// buffer in parts
48//
49//==============================================================================
50
51/**
52 * @brief Body of a Sensor Data packet. Contains the fixed-size fields.
53 * @note The actual packet sent over Ethernet will have this struct followed
54 * by a variable number of Chunks and SensorDatapoints.
55 */
56struct __attribute__((packed)) SensorDataPacket {
57 uint8_t num_chunks;
58 uint8_t num_sensors;
59 // Followed by N Chunks in the data payload
60};
61
62/**
63 * @brief Chunk of a Sensor Data packet.
64 * @note In the actual packet sent over Ethernet, each chunk will be followed by
65 * num_sensors defined in the data packet
66 */
67
68struct __attribute__((packed)) SensorDataChunk {
69 uint32_t timestamp;
70};
71
72/**
73 * @brief Represents a single sensor reading. Used in the SensorDataPacket.
74 */
75struct __attribute__((packed)) SensorDatapoint {
76 uint8_t sensor_id; // Which sensor on the board this data is from
77 uint32_t data; // The sensor value
78};
79
80//-----------------------------------------------------------------------------
81// High-Level Data Collection Structures
82//-----------------------------------------------------------------------------
83// This structure is used for collecting and managing sensor data before
84// serializing into network packets. It provides a higher-level interface
85// for data collection compared to the packed network structures above.
86
87/**
88 * @brief Represents a single data chunk with timestamp and sensor datapoints.
89 *
90 * This struct represents one data chunk containing a timestamp and a vector with
91 * num_sensors datapoints. It's used for collecting sensor data before serializing
92 * into network packets.
93 *
94 * @note This is NOT a packed struct as it's used for data collection,
95 * not network transmission. Use the packed SensorDataChunk for network
96 * packets.
97 */
99 uint32_t timestamp; // Timestamp for this data chunk
100 std::vector<SensorDatapoint> datapoints;
101 uint8_t num_sensors;
102
103 /**
104 * @brief Constructor with timestamp
105 * @param ts The timestamp for this data chunk
106 * @param num_sensors The number of sensor datapoints for this chunk
107 */
109
110 /**
111 * @brief Add a sensor datapoint to this chunk
112 * @param sensor_id The ID of the sensor
113 * @param data The sensor reading value
114 * @return True if successfully added, false if array is full
115 */
116 bool add_datapoint(uint8_t sensor_id, uint32_t data) {
117 if (datapoints.size() >= num_sensors) {
118 return false; // Array is full
119 }
120 datapoints.push_back({sensor_id, data});
121 return true;
122 }
123
124 /**
125 * @brief Get the number of datapoints in this chunk
126 * @return The number of datapoints
127 */
128 size_t size() const { return datapoints.size(); }
129
130 /**
131 * @brief Check if the chunk is empty
132 * @return True if no datapoints, false otherwise
133 */
134 bool empty() const { return datapoints.empty(); }
135
136 /**
137 * @brief Check if the chunk is full
138 * @return True if at maximum capacity, false otherwise
139 */
140 bool full() const { return datapoints.size() >= num_sensors; }
141
142 /**
143 * @brief Clear all datapoints from this chunk
144 */
145 void clear() { datapoints.clear(); }
146};
147
148//==============================================================================
149// Sensor Config
150//==============================================================================
151
152/**
153 * @brief Fixed-size header of a Sensor Config packet.
154 *
155 * Full packet layout (after standard PacketHeader):
156 * - This struct (1 byte): num_sensors (N)
157 * - N x uint8_t sensor_id
158 * - uint8_t reference_voltage
159 * - uint8_t necessary_for_abort (0 or 1)
160 * - If necessary_for_abort: uint32_t controller_ip (4 bytes)
161 * - uint8_t enable_serial_printing
162 */
163struct __attribute__((packed)) SensorConfigPacket {
164 uint8_t num_sensors;
165};
166
167/**
168 * @brief High-level representation of a parsed Sensor Config payload.
169 *
170 * @note This is NOT a packed struct; it is used for collecting / returning
171 * sensor config fields in a convenient form (similar in spirit to
172 * SensorDataChunkCollection).
173 */
181
182//==============================================================================
183// Actuator Command
184//==============================================================================
185
186/**
187 * @brief Body of an Actuator Command packet.
188 * @note The actual packet will have this struct followed by N ActuatorCommands.
189 */
190struct __attribute__((packed)) ActuatorCommandPacket {
191 uint8_t num_commands;
192 // Followed by 'num_commands' instances of ActuatorCommand
193};
194
195/**
196 * @brief Represents a command for a single actuator.
197 */
198struct __attribute__((packed)) ActuatorCommand {
199 uint8_t actuator_id;
200 uint8_t actuator_state;
201};
202
203/**
204 * @brief Body of a PWM Actuator Command packet.
205 * @note The actual packet will have this struct followed by N PWMActuatorCommands.
206 */
207struct __attribute__((packed)) PWMActuatorCommandPacket {
208 uint8_t num_commands;
209 // Followed by 'num_commands' instances of PWMActuatorCommand
210};
211
212/**
213 * @brief Represents a PWM command for a single actuator.
214 */
215struct __attribute__((packed)) PWMActuatorCommand {
216 uint8_t actuator_id;
217 uint32_t duration; // Duration in milliseconds
218 float duty_cycle; // Duty cycle in percentage (0.0 - 1.0)
219 float frequency; // Frequency in Hz
220};
221
222//==============================================================================
223// Actuator Config (Abort)
224//==============================================================================
225
226/**
227 * @brief Fixed-size header of an Actuator Config packet for abort configuration.
228 *
229 * Full packet layout (after standard PacketHeader):
230 * - This struct (2 bytes): is_abort_controller, num_abort_actuators (N)
231 * - N x AbortActuatorLocation (7 bytes each)
232 * - 1 byte: num_abort_pts (X)
233 * - X x AbortPTLocation (9 bytes each)
234 * - 1 byte: enable_serial_printing
235 */
236struct __attribute__((packed)) ActuatorConfigPacket {
237 uint8_t is_abort_controller; // 1 if this board is the abort controller, 0 otherwise
238 uint8_t num_abort_actuators; // N = number of abort actuator entries following
239};
240
241/**
242 * @brief Defines one abort actuator: location (IP), ID, vent state, and abort state.
243 * 7 bytes on wire: 4B IP + 1B actuator_id + 1B vent_state + 1B abort_state.
244 */
245struct __attribute__((packed)) AbortActuatorLocation {
246 uint32_t ip_address; // IP address of the board where this actuator lives
247 uint8_t actuator_id;
248 uint8_t vent_state; // 1 = on, 0 = off
249 uint8_t abort_state; // 1 = on, 0 = off
250};
251
252/**
253 * @brief Single byte count of abort PT entries; appears after N actuator blocks.
254 */
255struct __attribute__((packed)) AbortPTSectionHeader {
256 uint8_t num_abort_pts; // X = number of AbortPTLocation entries following
257};
258
259/**
260 * @brief Defines the location of a pressure transducer needed for an abort
261 * sequence, and its pressure threshold as an ADC code.
262 * 9 bytes on wire: 4B IP + 1B sensor_id + 4B pressure_threshold_adc.
263 */
264struct __attribute__((packed)) AbortPTLocation {
265 uint32_t ip_address;
266 uint8_t sensor_id;
267 uint32_t pressure_threshold_adc; // Pressure threshold as ADC code
268};
269
270//==============================================================================
271// Self Test
272//==============================================================================
273
274/**
275 * @brief Body of a Self Test packet.
276 * @note The actual packet will have this struct followed by N SelfTestResults.
277 *
278 * On-wire layout (after PacketHeader):
279 * adc_good (1 byte) – 1 if TDAC self-test passed, 0 if failed
280 * num_sensors (1 byte) – number of SelfTestResult entries that follow
281 * N x SelfTestResult
282 */
283struct __attribute__((packed)) SelfTestPacket {
284 uint8_t adc_good; // 1 = ADC passed TDAC self-test, 0 = failed
285 uint8_t num_sensors;
286 // Followed by 'num_sensors' instances of SelfTestResult
287};
288
289/**
290 * @brief Represents a self test result for a single sensor.
291 */
292struct __attribute__((packed)) SelfTestResult {
293 uint8_t sensor_id;
294 uint8_t result; // boolean, 1 = good, 0 = bad
295};
296
297//==============================================================================
298// Environmental Data
299//==============================================================================
300
301/**
302 * @brief Body of an Environmental Data packet (after PacketHeader).
303 * Temperature in degrees Celsius, absolute pressure in Pa, relative humidity in %RH.
304 */
305struct __attribute__((packed)) EnvironmentalDataPacket {
306 float temperature_c;
307 uint32_t pressure_pa;
308 float humidity_rh;
309};
310
311//==============================================================================
312// Stacklight Command
313//==============================================================================
314
315/**
316 * @brief Body of a stacklight command packet (after PacketHeader).
317 * Order: red, yellow, green, buzzer. Each byte is 1 = on, 0 = off.
318 */
319struct __attribute__((packed)) StacklightCommandPacket {
320 uint8_t red;
321 uint8_t yellow;
322 uint8_t green;
323 uint8_t buzzer;
324};
325
326} // namespace daq
static bool is_abort_controller
Definition main.cpp:63
static uint8_t board_id
Definition main.cpp:30
json_pointer result
Definition json.hpp:14064
struct __attribute__((packed)) PacketHeader
The standard 6-byte header preceding every packet.
EngineState
Defines the overall state of the engine system.
Definition DiabloEnums.h:48
BoardState
Defines the operational state of a board.
Definition DiabloEnums.h:31
PacketType
Defines the type of data contained in a packet.
Definition DiabloEnums.h:10
High-level representation of a parsed Sensor Config payload.
std::vector< uint8_t > sensor_ids
size_t size() const
Get the number of datapoints in this chunk.
bool full() const
Check if the chunk is full.
bool empty() const
Check if the chunk is empty.
void clear()
Clear all datapoints from this chunk.
SensorDataChunkCollection(uint32_t ts, uint8_t num_sensors)
Constructor with timestamp.
std::vector< SensorDatapoint > datapoints
bool add_datapoint(uint8_t sensor_id, uint32_t data)
Add a sensor datapoint to this chunk.
__attribute__((weak))
Definition syscalls.c:67