SatNOGS-COMMS  4.1.0
A COMMS subsystem for CubeSats
Loading...
Searching...
No Matches
iface_ctrl.hpp
Go to the documentation of this file.
1/*
2 * SatNOGS-COMMS MCU software
3 *
4 * Copyright (C) 2025, Libre Space Foundation <http://libre.space>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * SPDX-License-Identifier: GNU General Public License v3.0 or later
20 */
21
22#pragma once
23
25#include <cstdint>
26#include <etl/fsm.h>
27#include <msg_arbiter.hpp>
29
31{
32
33class iface_ctrl : public etl::fsm
34{
35public:
40 static constexpr uint32_t MAX_TRX_MS = 5000U;
41
42 enum class state : uint8_t
43 {
49 };
50
55 class stats
56 {
57 public:
58 size_t tx_frames;
62 size_t rx_frames;
67 uint64_t last_rx_ts;
68 float last_rssi;
71
73 : tx_frames(0),
76 rx_frames(0),
79 last_rx_ts(0),
80 last_rssi(std::nanf("nan")),
82 last_valid_rssi(std::nanf("nan"))
83 {
84 }
85
86 void
88 {
89 tx_frames = 0;
92 rx_frames = 0;
95 last_rx_ts = 0;
96 last_rssi = std::nanf("nan");
98 last_valid_rssi = std::nanf("nan");
99 }
100 };
101
103
104 void
105 enable();
106
107 void
108 enable(bool yes);
109
110 void
111 disable();
112
113 void
114 restart();
115
116 void
117 reset_stats();
118
119 const stats &
120 get_stats() const;
121
122 void
124
125 void
126 frame_received(bool valid, float rssi);
127
128 void
129 tx(const msg_arbiter::msg &msg, bool more = false);
130
132 get_state() const;
133
135 {
136 public:
137 disabled_exception(string_type file_name, numeric_type line)
139 satnogs::comms::lib::exception::severity::MINOR, file_name, line,
140 error_msg{"Interface is disabled", "ifacedis", ERADIO})
141 {
142 }
143 };
144
146 {
147 public:
148 tx_inhibit_exception(string_type file_name, numeric_type line)
150 satnogs::comms::lib::exception::severity::MINOR, file_name, line,
151 error_msg{"Interface has TX inhibit configured", "ifacetxinh",
152 ERADIO})
153 {
154 }
155 };
156
157private:
159 bool m_pending;
160 k_mutex m_mtx;
161 struct k_condvar m_cond_var;
162 k_timer m_timer;
163 struct k_work m_work;
164 msg_arbiter::msg m_tx_msg;
165 bool m_tx_wait;
166
171 enum events : uint8_t
172 {
173 ENABLE,
174 DISABLE,
175 TX_FRAME,
176 RX_MODE,
177 IDLE_MODE,
178 FRAME_RECEIVED,
180 RECONFIGURE
181 };
182
183 // void
184 // operation_start();
185
186 // void
187 // operation_stop();
188
189 void
190 wait_pending_operation();
191
192 void
193 frame_sent(bool success);
194
195 void
196 tx_frame_dropped();
197
198 bool
199 duty_cycle_enabled();
200
201 static void
202 timer_handler(k_timer *t);
203
204 static void
205 timer_work_handler(k_work *item);
206
207 class disable_msg : public etl::message<events::DISABLE>
208 {
209 public:
210 disable_msg() = default;
211 };
212
213 class tx_frame_msg : public etl::message<events::TX_FRAME>
214 {
215 public:
216 tx_frame_msg() = default;
217 };
218
219 class rx_msg : public etl::message<events::RX_MODE>
220 {
221 public:
222 rx_msg() = default;
223 };
224
225 class idle_msg : public etl::message<events::IDLE_MODE>
226 {
227 public:
228 idle_msg() = default;
229 };
230
231 class frame_received_msg : public etl::message<events::FRAME_RECEIVED>
232 {
233 public:
234 frame_received_msg() = default;
235 };
236
237 class disabled_state
238 : public etl::fsm_state<iface_ctrl, disabled_state,
239 static_cast<etl::fsm_state_id_t>(state::DISABLED),
240 rx_msg, tx_frame_msg>
241 {
242 public:
243 etl::fsm_state_id_t
244 on_enter_state() override;
245
246 etl::fsm_state_id_t
247 on_event(const rx_msg &msg);
248
249 etl::fsm_state_id_t
250 on_event(const tx_frame_msg &msg);
251
252 etl::fsm_state_id_t
253 on_event_unknown(const etl::imessage &msg);
254 };
255
256 class tx_state
257 : public etl::fsm_state<iface_ctrl, tx_state,
258 static_cast<etl::fsm_state_id_t>(state::TX),
259 disable_msg, tx_frame_msg, rx_msg>
260 {
261 public:
262 etl::fsm_state_id_t
263 on_enter_state() override;
264
265 void
266 on_exit_state() override;
267
268 etl::fsm_state_id_t
269 on_event(const disable_msg &msg);
270
271 etl::fsm_state_id_t
272 on_event(const tx_frame_msg &msg);
273
274 etl::fsm_state_id_t
275 on_event(const rx_msg &msg);
276
277 etl::fsm_state_id_t
278 on_event_unknown(const etl::imessage &msg);
279 };
280
281 class rx_state
282 : public etl::fsm_state<
283 iface_ctrl, rx_state, static_cast<etl::fsm_state_id_t>(state::RX),
284 disable_msg, tx_frame_msg, idle_msg, frame_received_msg>
285 {
286 public:
287 etl::fsm_state_id_t
288 on_enter_state() override;
289
290 etl::fsm_state_id_t
291 on_event(const disable_msg &msg);
292
293 etl::fsm_state_id_t
294 on_event(const tx_frame_msg &msg);
295
296 etl::fsm_state_id_t
297 on_event(const idle_msg &msg);
298
299 etl::fsm_state_id_t
300 on_event(const frame_received_msg &msg);
301
302 etl::fsm_state_id_t
303 on_event_unknown(const etl::imessage &msg);
304 };
305
306 class idle_state
307 : public etl::fsm_state<iface_ctrl, idle_state,
308 static_cast<etl::fsm_state_id_t>(state::IDLE),
309 disable_msg, tx_frame_msg, rx_msg>
310 {
311 public:
312 etl::fsm_state_id_t
313 on_enter_state() override;
314
315 void
316 on_exit_state() override;
317
318 etl::fsm_state_id_t
319 on_event(const disable_msg &msg);
320
321 etl::fsm_state_id_t
322 on_event(const tx_frame_msg &msg);
323
324 etl::fsm_state_id_t
325 on_event(const rx_msg &msg);
326
327 etl::fsm_state_id_t
328 on_event_unknown(const etl::imessage &msg);
329 };
330
331private:
332 disabled_state m_disabled_state;
333 tx_state m_tx_state;
334 rx_state m_rx_state;
335 idle_state m_idle_state;
336 etl::ifsm_state *m_state_list[4];
337 stats m_stats;
338};
339} // namespace satnogs::comms::utils
A class representing error messages in the SatNOGS-COMMS system.
Definition exception.hpp:83
Exception base class.
Definition exception.hpp:63
severity
Severity levels of exceptions.
Definition exception.hpp:71
@ MINOR
Failure having minimal impact.
Definition exception.hpp:75
exception(severity sev, const char *file, int lineno, const error_msg &err_msg)
Constructor for the exception class.
interface
Radio interface identifier.
Definition radio.hpp:177
disabled_exception(string_type file_name, numeric_type line)
Radio interface statistics.
uint64_t last_valid_rx_ts
The timestamp of the last valid RX frame.
uint64_t last_rx_ts
The timestamp of the RX frame.
size_t tx_frames
TX frames successfully sent.
float last_rssi
The RSSI of the last RX frame.
size_t rx_frames_drop
RX frames dropped due to a full message queue.
size_t tx_frames_drop
TX frames dropped due to full message queue.
float last_valid_rssi
The RSSI of the last valid RX frame.
tx_inhibit_exception(string_type file_name, numeric_type line)
void restart()
Restarts the interface by disabling and enabling it again.
void frame_received(bool valid, float rssi)
Updates the RX stats.
const stats & get_stats() const
Returns the statistics class of the interface.
void reset_stats()
Resets the TX/RX statistics of the interface.
void rx_frame_dropped()
Increments the RX drop counter.
@ TX
Interface is either TX a frame or wait to TX the next frame.
void tx(const msg_arbiter::msg &msg, bool more=false)
void enable()
Enables the interface and set it automatically to RX state.
static constexpr uint32_t MAX_TRX_MS
iface_ctrl(satnogs::comms::lib::radio::interface iface)
void disable()
Disables the interface.
iface_ctrl::state get_state() const
Returns the current state of the interface.
#define ERADIO
Error in radio.