Avionics
Core avionics package for CURE flight computers
Loading...
Searching...
No Matches
Telemetry.h
Go to the documentation of this file.
1#ifndef TELEMETRY_H
2#define TELEMETRY_H
3
4#include <array>
5#include <cstddef>
6#include <cstdint>
7#include <cstring>
8
9#include "ArduinoHAL.h"
10#include "UARTCommandHandler.h"
12
28
29namespace TelemetryFmt {
30
32constexpr std::size_t kPacketCapacity_bytes = 120;
33
35constexpr std::size_t kSyncZeroCount_bytes = 3;
36
38constexpr std::size_t kBytesInU32_bytes = 4;
39
41constexpr std::size_t kStartByteIndex = kSyncZeroCount_bytes; // 3
42constexpr std::size_t kTimestampIndex = kStartByteIndex + 1; // 4
44constexpr std::size_t kHeaderSize_bytes = kSyncZeroCount_bytes + 1 + kBytesInU32_bytes + kBytesInU32_bytes; // 12 (CHANGED from 8 to 12)
45
47constexpr std::size_t kEndMarkerSize_bytes = kSyncZeroCount_bytes + 1;
48
50constexpr std::uint8_t kStartByteValue = 51;
51
53constexpr std::uint8_t kEndByteValue = 52;
54
56constexpr unsigned kBitsPerByte_bits = 8;
57constexpr std::uint32_t kCommandModeInactivityTimeout_ms = 10000;
58constexpr std::size_t kCommandEntrySequenceLength = 3;
59constexpr char kCommandEntryChar = 'c';
60
62static_assert(sizeof(std::uint32_t) == 4, "Expected 32-bit uint32_t");
63static_assert(sizeof(float) == 4, "Expected 32-bit float");
64
68inline void writeU32Be(std::uint8_t* dst, std::uint32_t v) {
69
70 for (std::size_t i = 0; i < kBytesInU32_bytes; ++i) {
71 const unsigned shift = static_cast<unsigned>((kBytesInU32_bytes - 1 - i) * kBitsPerByte_bits);
72 dst[i] = static_cast<std::uint8_t>(v >> shift);
73 }
74}
75
76
82inline std::uint16_t hzToPeriod_ms(std::uint16_t frequency_hz) {
83 return (frequency_hz == 0) ? static_cast<std::uint16_t>(1000u)
84 : static_cast<std::uint16_t>((1000u + frequency_hz - 1u) / frequency_hz);
85}
86
87} // namespace TelemetryFmt
88
104 // --- Payload configuration ---
105
108
111
113 // Shall not be changed after construction
114 // Used to iterate over multiSDH
115 const std::size_t multiSDHLength;
116
118 std::uint8_t multiSDHDataLabel;
119
120 // --- Scheduling state ---
121
123 std::uint16_t period_ms;
124
126 std::uint32_t lastSentTimestamp_ms;
127
133 SendableSensorData(SensorDataHandler* sdh, std::uint16_t sendFrequency_hz)
134 : singleSDH(sdh),
135 multiSDH(0),
138 period_ms(TelemetryFmt::hzToPeriod_ms(sendFrequency_hz)),
140
147 template <std::size_t M>
148 SendableSensorData(const std::array<SensorDataHandler*, M>& sdhList,
149 std::uint8_t label,
150 std::uint16_t sendFrequency_hz)
151 : singleSDH(0),
152 multiSDH(sdhList.data()),
154 multiSDHDataLabel(label),
155 period_ms(TelemetryFmt::hzToPeriod_ms(sendFrequency_hz)),
157
161 bool shouldBeSent(std::uint32_t now_ms) const {
162 return (now_ms - lastSentTimestamp_ms) >= period_ms;
163 }
164
168 void markWasSent(std::uint32_t now_ms) {
169 lastSentTimestamp_ms = now_ms;
170 }
171
173 bool isSingle() const { return singleSDH != 0; }
174
176 bool isMulti() const { return (multiSDH != 0) && (multiSDHLength != 0); }
177};
178
191public:
192
197 template <std::size_t N>
198 Telemetry(const std::array<SendableSensorData*, N>& streams,
199 Stream& rfdSerialConnection,
200 CommandLine* commandLine = nullptr)
201 : streams_(streams.data()),
202 streamCount_(N),
203 rfdSerialConnection_(rfdSerialConnection),
204 commandLine_(commandLine),
205 nextEmptyPacketIndex_(0),
206 packet_{} {}
207
212 bool tick(std::uint32_t currentTime_ms);
213
217 bool isInCommandMode() const { return inCommandMode_; }
218
222 void setCommandLine(CommandLine* newCommandLine) { commandLine_ = newCommandLine; }
223
228 void lockCommandModeTimeout(std::uint32_t lockDuration_ms);
229
234
239
240private:
241 // Packet building helpers
242 void preparePacket(std::uint32_t timestamp_ms);
243 void addSingleSDHToPacket(SensorDataHandler* sdh);
244 void addSSDToPacket(SendableSensorData* ssd);
245 void setPacketToZero();
246 void addEndMarker();
247 void checkForRadioCommandSequence(std::uint32_t currentTime_ms);
248 void enterCommandMode(std::uint32_t currentTime_ms);
249 void exitCommandMode();
250 bool shouldPauseTelemetryForCommandMode(std::uint32_t currentTime_ms);
251 bool canFitStreamWithEndMarker(const SendableSensorData* ssd) const;
252 void tryAppendStream(SendableSensorData* stream, std::uint32_t currentTime_ms, bool& payloadAdded);
253 bool finalizeAndSendPacket();
254
255 // Non-owning view of the stream list
256 SendableSensorData* const* streams_;
257
258 // Number of streams in the list
259 // Shall not be changed after construction
260 // Used to iterate over streams
261 const std::size_t streamCount_;
262
263 // Output
264 Stream& rfdSerialConnection_;
265 CommandLine* commandLine_;
266
267 // Packet state
268 std::uint32_t packetCounter_ = 0;
269 std::size_t nextEmptyPacketIndex_;
270 std::array<std::uint8_t, TelemetryFmt::kPacketCapacity_bytes> packet_;
271
272 // Command mode handling
273 bool inCommandMode_ = false;
274 std::uint32_t commandModeEnteredTimestamp_ms_ = 0;
275 std::uint32_t commandModeLastInputTimestamp_ms_ = 0;
276 std::size_t commandEntryProgress_ = 0;
277 bool commandModeTimeoutLocked_ = false;
278 std::uint32_t commandModeTimeoutLockDeadline_ms_ = 0;
279};
280
281#endif
Lightweight UART command-line interface with history and parsing.
Buffers sensor samples and forwards them to an IDataSaver at a controlled rate.
void forceExitCommandMode()
Immediately exit command mode if currently active.
void setCommandLine(CommandLine *newCommandLine)
Optional command line interface to drive while telemetry manages command mode.
Definition Telemetry.h:222
void lockCommandModeTimeout(std::uint32_t lockDuration_ms)
Temporarily disable command-mode inactivity timeout.
Definition Telemetry.cpp:80
void unlockCommandModeTimeout()
Re-enable command-mode inactivity timeout immediately.
Definition Telemetry.cpp:91
bool isInCommandMode() const
True if telemetry is currently paused for radio command mode.
Definition Telemetry.h:217
bool tick(std::uint32_t currentTime_ms)
Call every loop to send due telemetry streams.
Telemetry(const std::array< SendableSensorData *, N > &streams, Stream &rfdSerialConnection, CommandLine *commandLine=nullptr)
Construct from std::array (convenient and compile-time sized). The std::array must outlive the Teleme...
Definition Telemetry.h:198
void writeU32Be(std::uint8_t *dst, std::uint32_t v)
Write a 32-bit value in big-endian order to dst[0..3].
Definition Telemetry.h:68
constexpr std::size_t kPacketCapacity_bytes
Definition Telemetry.h:32
constexpr std::size_t kStartByteIndex
Definition Telemetry.h:41
std::uint16_t hzToPeriod_ms(std::uint16_t frequency_hz)
Convert frequency (Hz) to period (ms), using integer math.
Definition Telemetry.h:82
constexpr char kCommandEntryChar
Definition Telemetry.h:59
constexpr std::size_t kHeaderSize_bytes
Definition Telemetry.h:44
constexpr std::size_t kBytesInU32_bytes
Definition Telemetry.h:38
constexpr std::size_t kCommandEntrySequenceLength
Definition Telemetry.h:58
constexpr std::uint8_t kStartByteValue
Definition Telemetry.h:50
constexpr std::size_t kPacketCounterIndex
Definition Telemetry.h:43
constexpr std::size_t kEndMarkerSize_bytes
Definition Telemetry.h:47
constexpr std::uint32_t kCommandModeInactivityTimeout_ms
Definition Telemetry.h:57
constexpr std::size_t kSyncZeroCount_bytes
Definition Telemetry.h:35
constexpr std::uint8_t kEndByteValue
Definition Telemetry.h:53
constexpr std::size_t kTimestampIndex
Definition Telemetry.h:42
constexpr unsigned kBitsPerByte_bits
Definition Telemetry.h:56
Declares one telemetry "stream" to include in packets.
Definition Telemetry.h:103
const std::size_t multiSDHLength
Definition Telemetry.h:115
bool isMulti() const
Convenience: true if configured as a multi SDH stream.
Definition Telemetry.h:176
bool isSingle() const
Convenience: true if configured as a single SDH stream.
Definition Telemetry.h:173
std::uint16_t period_ms
Definition Telemetry.h:123
SendableSensorData(SensorDataHandler *sdh, std::uint16_t sendFrequency_hz)
Create a single SDH stream.
Definition Telemetry.h:133
SendableSensorData(const std::array< SensorDataHandler *, M > &sdhList, std::uint8_t label, std::uint16_t sendFrequency_hz)
Create a multi SDH stream from a std::array.
Definition Telemetry.h:148
void markWasSent(std::uint32_t now_ms)
Update internal state after sending.
Definition Telemetry.h:168
std::uint8_t multiSDHDataLabel
Definition Telemetry.h:118
std::uint32_t lastSentTimestamp_ms
Definition Telemetry.h:126
bool shouldBeSent(std::uint32_t now_ms) const
Return true if enough time has elapsed such that this stream wants to be sent again.
Definition Telemetry.h:161
SensorDataHandler *const * multiSDH
Definition Telemetry.h:110
SensorDataHandler * singleSDH
Definition Telemetry.h:107