SatNOGS-COMMS  4.1.0
A COMMS subsystem for CubeSats
Loading...
Searching...
No Matches
telecommand.cpp
Go to the documentation of this file.
1/*
2 * SatNOGS-COMMS MCU software
3 *
4 * Copyright (C) 2024, 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#include "telecommand.hpp"
23#include "error_handler.hpp"
24#include "io.hpp"
25#include "io_wdg.hpp"
26#include "memory_monitor.hpp"
27#include "ota.hpp"
28#include "settings.hpp"
29#include "storage.hpp"
30#include "telemetry.hpp"
31#include "time.hpp"
32#include <etl/bit_stream.h>
33
34namespace satnogs::comms
35{
36
37void
38telecommand::deserialize(etl::bit_stream_reader &reader, float &x)
39{
40 uint32_t float_bits = reader.read<uint32_t>(32).value();
41 std::memcpy(&x, &float_bits, sizeof(float_bits));
42}
43
44void
45telecommand::deserialize(etl::bit_stream_reader &reader, double &x)
46{
47 uint64_t double_bits = reader.read<uint64_t>(64).value();
48 std::memcpy(&x, &double_bits, sizeof(double_bits));
49}
50
51bool
52telecommand::ccsds_frame_valid(const uint8_t *b, size_t len)
53{
54 etl::bit_stream_reader bit_stream(etl::span(b, len), etl::endian::big);
56 tc_header.deserialize(bit_stream);
57
58 /* FIXME: frame checking needs revising */
59 if ((tc_header.version != 0) && (tc_header.sec_hdr != 0) &&
60 (tc_header.group_flags != 0b11)) {
61 return false;
62 } else {
63 return true;
64 }
65}
66
67int
69{
70 return m_frame_count;
71}
72
73bool
74telecommand::parse_ring_buffer_logs(msg_arbiter::msg &m,
75 etl::bit_stream_reader &bit_stream)
76{
77 uint32_t num_of_logs = bit_stream.read<uint32_t>(32).value();
79 return false;
80}
81
82bool
83telecommand::parse_tlm_req(msg_arbiter::msg &m,
84 etl::bit_stream_reader &bit_stream)
85{
86 telemetry::apid tlm_type;
87 tlm_type =
88 static_cast<telemetry::apid>(bit_stream.read<uint16_t>(16).value());
89 switch (tlm_type) {
92 break;
95 break;
98 break;
101 break;
104 break;
107 break;
110 break;
113 break;
116 } break;
119 break;
122 return false;
123 }
124 default:
125 return false;
126 }
127 return true;
128}
129
130bool
131telecommand::parse_storage_tlm(msg_arbiter::msg &m,
132 etl::bit_stream_reader &reader, packet_id id)
133{
134 switch (id) {
136 telecommand::prefixed_string path;
137 path.deserialize(reader);
139 } break;
140
142 telecommand::prefixed_string path;
143 path.deserialize(reader);
144 size_t offset = reader.read<size_t>(32).value();
145 size_t len = reader.read<size_t>(32).value();
146 if (len == 0) {
147 len = CONFIG_MAX_MTU;
148 }
150 len);
151 } break;
153 telecommand::prefixed_string path;
154 path.deserialize(reader);
156 } break;
157 default:
158 return false;
159 }
160 return true;
161}
162
163telecommand::telecommand() : m_frame_count(0) {}
164
166{
167public:
168 static bool
169 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
170 {
171 auto &t = test::get_instance();
172 parser<telecommand::packet_id::TEST_TX_SIMPLE> req;
173 req.deserialize(bit_stream);
174 switch (req.iface) {
175 case static_cast<uint32_t>(lib::radio::interface::UHF):
177 {req.nframes, req.delay_us, req.len});
178 break;
179 case static_cast<uint32_t>(lib::radio::interface::SBAND):
181 {req.nframes, req.delay_us, req.len});
182 break;
183 default:
184 return false;
185 }
186 return true;
187 }
188
189private:
190 uint32_t iface;
191 uint32_t nframes;
192 uint32_t delay_us;
193 uint32_t len;
194 parser() : iface(0), nframes(0), delay_us(0), len(0) {}
195
196 void
197 deserialize(etl::bit_stream_reader &reader)
198 {
199 iface = reader.read<uint32_t>(1).value();
200 nframes = reader.read<uint32_t>(32).value();
201 delay_us = reader.read<uint32_t>(32).value();
202 len = reader.read<uint32_t>(32).value();
203 }
204};
205
207{
208public:
209 static bool
210 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
211 {
212 auto &t = test::get_instance();
213 t.stop();
214 return true;
215 }
216
217private:
218 bool yes;
219 parser() : yes(true) {}
220
221 void
222 deserialize(etl::bit_stream_reader &reader)
223 {
224 yes = reader.read<uint8_t>(1).value();
225 }
226};
227
229{
230public:
231 static bool
232 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
233 {
234 parser<telecommand::packet_id::FPGA_ENABLE> req;
235 req.deserialize(bit_stream);
236 auto &fpga = lib::board::get_instance().fpga();
237 if (req.enable_fpga) {
238 fpga.enable(true);
239 } else {
240 fpga.enable(false);
241 }
242 return true;
243 }
244
245private:
246 bool enable_fpga;
247 parser() : enable_fpga(false) {}
248
249 void
250 deserialize(etl::bit_stream_reader &reader)
251 {
252 enable_fpga = reader.read<uint8_t>(1).value();
253 }
254};
255
256template <>
258{
259public:
260 static bool
261 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
262 {
263 parser<telecommand::packet_id::SET_FLASH_MONITOR_DELAY_SEC> req;
264 req.deserialize(bit_stream);
265 auto &mem_mon = memory_monitor::get_instance();
266
267 if (req.flash_mon_delay_sec == 0) {
268 mem_mon.stop();
269 } else {
270 mem_mon.start(etl::clamp(req.flash_mon_delay_sec, 1U, 21600U));
271 }
272 return true;
273 }
274
275private:
276 uint32_t flash_mon_delay_sec;
277 parser() : flash_mon_delay_sec(0) {}
278
279 void
280 deserialize(etl::bit_stream_reader &reader)
281 {
282 flash_mon_delay_sec = reader.read<uint32_t>(32).value();
283 }
284};
286{
287public:
288 static bool
289 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
290 {
291 parser<telecommand::packet_id::STORAGE_ENABLE> req;
292 req.deserialize(bit_stream);
294 storage.enable(req.enable_storage);
295 return true;
296 }
297
298private:
299 bool enable_storage;
300 parser() : enable_storage(false) {}
301
302 void
303 deserialize(etl::bit_stream_reader &reader)
304 {
305 enable_storage = reader.read<uint8_t>(1).value();
306 }
307};
308
310{
311public:
312 static bool
313 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
314 {
315 parser<telecommand::packet_id::STORAGE_DIRECTION> req;
316 req.deserialize(bit_stream);
318 storage.enable(true);
319
320 switch (req.dir) {
323 return true;
324 }
327 return true;
328 }
329 default:
330 return false;
331 }
332 }
333
334private:
336 parser() : dir(storage_direction::MCU) {}
337
338 void
339 deserialize(etl::bit_stream_reader &reader)
340 {
341 dir = static_cast<storage_direction>(reader.read<uint8_t>(1).value());
342 }
343};
344
346{
347public:
348 static bool
349 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
350 {
351 parser<telecommand::packet_id::STOP_WDT_UPDATE> req;
352 req.deserialize(bit_stream);
353 if (req.stop_wdt_update) {
354 k_msleep(CONFIG_WATCHDOG_PERIOD_SYS + 1000);
355 }
356 return true;
357 }
358
359private:
360 bool stop_wdt_update;
361 parser() : stop_wdt_update(false) {}
362
363 void
364 deserialize(etl::bit_stream_reader &reader)
365 {
366 stop_wdt_update = reader.read<uint8_t>(1).value();
367 }
368};
369
371{
372public:
373 static bool
374 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
375 {
376 parser<telecommand::packet_id::FREQ_SET> req;
377 req.deserialize(bit_stream);
378 auto &s = settings::get_instance();
379 if (req.iface == lib::radio::interface::UHF &&
380 req.direction == lib::rf_frontend::dir::RX) {
381 s.set<settings::param::UHF_RX_FREQ>(req.freq);
382 } else if (req.iface == lib::radio::interface::UHF &&
383 req.direction == lib::rf_frontend::dir::TX) {
384 s.set<settings::param::UHF_TX_FREQ>(req.freq);
385 } else if (req.iface == lib::radio::interface::SBAND &&
386 req.direction == lib::rf_frontend::dir::RX) {
387 s.set<settings::param::SBAND_RX_FREQ>(req.freq);
388 } else if (req.iface == lib::radio::interface::SBAND &&
389 req.direction == lib::rf_frontend::dir::TX) {
390 s.set<settings::param::SBAND_TX_FREQ>(req.freq);
391 } else {
392 return false;
393 }
394 return true;
395 }
396
397private:
398 lib::rf_frontend::dir direction;
400 uint32_t freq;
401 parser()
402 : direction(lib::rf_frontend::dir::RX),
403 iface(lib::radio::interface::UHF),
404 freq(0U)
405 {
406 }
407
408 void
409 deserialize(etl::bit_stream_reader &reader)
410 {
411 direction =
412 static_cast<lib::rf_frontend::dir>(reader.read<uint8_t>(2).value());
413 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
414 freq = reader.read<uint32_t>(32).value();
415 }
416};
417
419{
420public:
421 static bool
422 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
423 {
424 parser<telecommand::packet_id::TX_INHIBIT> req;
425 req.deserialize(bit_stream);
426 auto &s = settings::get_instance();
427 switch (req.iface) {
429 s.set<settings::param::UHF_TX_EN>(!req.enable);
430 break;
432 s.set<settings::param::SBAND_TX_EN>(!req.enable);
433 break;
434 default:
435 return false;
436 }
437 return true;
438 }
439
440private:
442 bool enable;
443 parser() : iface(lib::radio::interface::UHF), enable(false) {}
444
445 void
446 deserialize(etl::bit_stream_reader &reader)
447 {
448 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
449 enable = reader.read<uint8_t>(1).value();
450 }
451};
452
453template <>
455{
456public:
457 static bool
458 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
459 {
460 parser<telecommand::packet_id::SET_TX_GS_TURNAROUND_TIME> req;
461 req.deserialize(bit_stream);
462 auto &s = settings::get_instance();
463 switch (req.iface) {
466 etl::clamp<uint32_t>(req.time_ms, 0U, utils::iface_ctrl::MAX_TRX_MS));
467 break;
470 etl::clamp<uint32_t>(req.time_ms, 0U, utils::iface_ctrl::MAX_TRX_MS));
471 break;
472 default:
473 return false;
474 }
475 return true;
476 }
477
478private:
480 uint32_t time_ms;
481 parser() : iface(lib::radio::interface::UHF), time_ms(0U) {}
482
483 void
484 deserialize(etl::bit_stream_reader &reader)
485 {
486 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
487 time_ms = reader.read<uint32_t>(32).value();
488 }
489};
490
491template <>
493{
494public:
495 static bool
496 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
497 {
498 auto &ota = ota::get_instance();
500 return true;
501 }
502
503private:
504 parser() = default;
505};
506
508{
509public:
510 static bool
511 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
512 {
513 auto &ota = ota::get_instance();
515 return true;
516 }
517
518private:
519 parser() = default;
520};
521
523{
524public:
525 static bool
526 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
527 {
528 parser<telecommand::packet_id::RESET_OTA_SESSION> req;
529 req.deserialize(bit_stream);
530 auto &ota = ota::get_instance();
531 ota.reset_session(req.idx);
532 return true;
533 }
534
535private:
536 uint32_t idx;
537 parser() : idx(0U) {}
538
539 void
540 deserialize(etl::bit_stream_reader &reader)
541 {
542 idx = reader.read<uint32_t>(32).value();
543 }
544};
545
547{
548public:
549 static bool
550 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
551 {
552 parser<telecommand::packet_id::SET_RADIO_ENABLE> req;
553 req.deserialize(bit_stream);
554 auto &radio_ctrl = io::get_instance().radio_ctrl();
555 switch (req.iface) {
558 radio_ctrl.enable(req.iface, req.enable);
559 break;
560 default:
561 return false;
562 }
563 return true;
564 }
565
566private:
568 bool enable;
569 parser() : iface(lib::radio::interface::UHF), enable(false) {}
570
571 void
572 deserialize(etl::bit_stream_reader &reader)
573 {
574 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
575 enable = reader.read<uint8_t>(1).value();
576 }
577};
578
580{
581public:
582 static bool
583 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
584 {
585 parser<telecommand::packet_id::TX_GAIN> req;
586 req.deserialize(bit_stream);
587 auto &s = settings::get_instance();
588 switch (req.iface) {
590 s.set<settings::param::UHF_TX_GAIN>(req.gain);
591 break;
593 s.set<settings::param::SBAND_TX_GAIN>(req.gain);
594 break;
595 default:
596 return false;
597 }
598 return true;
599 }
600
601private:
603 float gain;
604 parser() : iface(lib::radio::interface::UHF), gain(0.0f) {}
605
606 void
607 deserialize(etl::bit_stream_reader &reader)
608 {
609 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
610 telecommand::deserialize(reader, gain);
611 }
612};
613
615{
616public:
617 static bool
618 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
619 {
620 parser<telecommand::packet_id::IO_WDT_PERIOD> req;
621 req.deserialize(bit_stream);
622 auto &wdg = io_wdg::get_instance();
623 wdg.set_period(req.period_mins);
624 return true;
625 }
626
627private:
628 uint32_t period_mins;
629 parser() : period_mins(0) {}
630
631 void
632 deserialize(etl::bit_stream_reader &reader)
633 {
634 period_mins = reader.read<uint32_t>(32).value();
635 }
636};
637
639{
640public:
641 static bool
642 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
643 {
644 parser<telecommand::packet_id::SET_RX_GAIN_MODE> req;
645 req.deserialize(bit_stream);
646 auto &s = settings::get_instance();
647 switch (req.iface) {
649 s.set<settings::param::UHF_GAIN0_MODE>(req.gain0_mode);
650 s.set<settings::param::UHF_GAIN1_MODE>(req.gain1_mode);
651 } break;
653 s.set<settings::param::SBAND_GAIN0_MODE>(req.gain0_mode);
654 s.set<settings::param::SBAND_GAIN1_MODE>(req.gain1_mode);
655 } break;
656 default:
657 return false;
658 }
659 return true;
660 }
661
662private:
666 parser()
667 : iface(lib::radio::interface::UHF),
668 gain0_mode(lib::rf_frontend::gain_mode::AUTO),
669 gain1_mode(lib::rf_frontend::gain_mode::AUTO)
670 {
671 }
672
673 void
674 deserialize(etl::bit_stream_reader &reader)
675 {
676 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
677 gain0_mode = static_cast<lib::rf_frontend::gain_mode>(
678 reader.read<uint8_t>(1).value());
679 gain1_mode = static_cast<lib::rf_frontend::gain_mode>(
680 reader.read<uint8_t>(1).value());
681 }
682};
683
685{
686public:
687 static bool
688 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
689 {
690 parser<telecommand::packet_id::EMMC_TEST> req;
691 req.deserialize(bit_stream);
692 auto &t = test::get_instance();
693 t.exec_test(test::test_id::EMMC_SIMPLE, {req.nbytes});
694 return true;
695 }
696
697private:
698 uint32_t nbytes;
699 parser() : nbytes(0) {}
700
701 void
702 deserialize(etl::bit_stream_reader &reader)
703 {
704 nbytes = reader.read<uint32_t>(32).value();
705 }
706};
707
709{
710public:
711 static bool
712 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
713 {
714 parser<telecommand::packet_id::RESET_RADIO_STATS> req;
715 req.deserialize(bit_stream);
717 return true;
718 }
719
720private:
722 parser() : iface(lib::radio::interface::UHF) {}
723
724 void
725 deserialize(etl::bit_stream_reader &reader)
726 {
727 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
728 }
729};
730
732{
733public:
734 static bool
735 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
736 {
737 parser<telecommand::packet_id::SET_RFFE_PARAMS> req;
738 req.deserialize(bit_stream);
739 auto &s = settings::get_instance();
740 switch (req.iface) {
742 s.set<settings::param::UHF_RX_RANGE_MIN>(req.rx_range_min);
743 s.set<settings::param::UHF_RX_RANGE_MAX>(req.rx_range_max);
744 s.set<settings::param::UHF_TX_RANGE_MIN>(req.tx_range_min);
745 s.set<settings::param::UHF_TX_RANGE_MAX>(req.tx_range_max);
746 s.set<settings::param::UHF_AGC0_RANGE_MIN>(req.agc0_range_min);
747 s.set<settings::param::UHF_AGC0_RANGE_MAX>(req.agc0_range_max);
748 s.set<settings::param::UHF_GAIN0_RANGE_MIN>(req.gain0_range_min);
749 s.set<settings::param::UHF_GAIN0_RANGE_MAX>(req.gain0_range_max);
750 s.set<settings::param::UHF_AGC0_CALIB_SLOPE>(req.agc0_calib_slope);
751 s.set<settings::param::UHF_AGC0_CALIB_INTRCPT>(req.agc0_calib_intrcpt);
752 s.set<settings::param::UHF_GAIN0_CALIB_SLOPE>(req.gain0_calib_slope);
753 s.set<settings::param::UHF_GAIN0_CALIB_INTRCPT>(req.gain0_calib_intrcpt);
754 break;
756 s.set<settings::param::SBAND_RX_RANGE_MIN>(req.rx_range_min);
757 s.set<settings::param::SBAND_RX_RANGE_MAX>(req.rx_range_max);
758 s.set<settings::param::SBAND_TX_RANGE_MIN>(req.tx_range_min);
759 s.set<settings::param::SBAND_TX_RANGE_MAX>(req.tx_range_max);
760 s.set<settings::param::SBAND_AGC0_RANGE_MIN>(req.agc0_range_min);
761 s.set<settings::param::SBAND_AGC0_RANGE_MAX>(req.agc0_range_max);
762 s.set<settings::param::SBAND_GAIN0_RANGE_MIN>(req.gain0_range_min);
763 s.set<settings::param::SBAND_GAIN0_RANGE_MAX>(req.gain0_range_max);
764 s.set<settings::param::SBAND_AGC0_CALIB_SLOPE>(req.agc0_calib_slope);
765 s.set<settings::param::SBAND_AGC0_CALIB_INTRCPT>(req.agc0_calib_intrcpt);
766 s.set<settings::param::SBAND_GAIN0_CALIB_SLOPE>(req.gain0_calib_slope);
768 req.gain0_calib_intrcpt);
769 break;
770 default:
771 return false;
772 }
773 return true;
774 }
775
776private:
778 uint32_t rx_range_min;
779 uint32_t rx_range_max;
780 uint32_t tx_range_min;
781 uint32_t tx_range_max;
782 float agc0_range_min;
783 float agc0_range_max;
784 float gain0_range_min;
785 float gain0_range_max;
786 float agc0_calib_slope;
787 float agc0_calib_intrcpt;
788 float gain0_calib_slope;
789 float gain0_calib_intrcpt;
790
791 parser()
792 : iface(lib::radio::interface::UHF),
793 rx_range_min(0U),
794 rx_range_max(0U),
795 tx_range_min(0U),
796 tx_range_max(0U),
797 agc0_range_min(0.0f),
798 agc0_range_max(0.0f),
799 gain0_range_min(0.0f),
800 gain0_range_max(0.0f),
801 agc0_calib_slope(0.0f),
802 agc0_calib_intrcpt(0.0f),
803 gain0_calib_slope(0.0f),
804 gain0_calib_intrcpt(0.0f)
805 {
806 }
807
808 void
809 deserialize(etl::bit_stream_reader &reader)
810 {
811 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
812 rx_range_min = reader.read<uint32_t>(32).value();
813 rx_range_max = reader.read<uint32_t>(32).value();
814 tx_range_min = reader.read<uint32_t>(32).value();
815 tx_range_max = reader.read<uint32_t>(32).value();
816 telecommand::deserialize(reader, agc0_range_min);
817 telecommand::deserialize(reader, agc0_range_max);
818 telecommand::deserialize(reader, gain0_range_min);
819 telecommand::deserialize(reader, gain0_range_max);
820 telecommand::deserialize(reader, agc0_calib_slope);
821 telecommand::deserialize(reader, agc0_calib_intrcpt);
822 telecommand::deserialize(reader, gain0_calib_slope);
823 telecommand::deserialize(reader, gain0_calib_intrcpt);
824 }
825};
826
828{
829public:
830 static bool
831 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
832 {
833 parser<telecommand::packet_id::SET_RTC> req;
834 req.deserialize(bit_stream);
836 /* Make the appropriate adjustments from human readable to tm representation
837 */
838 struct tm t = {.tm_sec = req.secs,
839 .tm_min = req.mins,
840 .tm_hour = req.hour,
841 .tm_mday = req.day,
842 .tm_mon = req.month - 1,
843 .tm_year = req.year - 1900};
844 time.set(t);
846 {"test", "t", 1});
847 auto &log = logger::get_instance();
848 log.log(e);
849 return true;
850 }
851
852private:
853 uint8_t secs;
854 uint8_t mins;
855 uint8_t hour;
856 uint8_t day;
857 uint8_t month;
858 uint16_t year;
859
860 parser() = default;
861
862 void
863 deserialize(etl::bit_stream_reader &reader)
864 {
865 secs = reader.read<uint8_t>(8).value();
866 mins = reader.read<uint8_t>(8).value();
867 hour = reader.read<uint8_t>(8).value();
868 day = reader.read<uint8_t>(8).value();
869 month = reader.read<uint8_t>(8).value();
870 year = reader.read<uint16_t>(16).value();
871 }
872};
873
875{
876public:
877 static bool
878 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
879 {
880 parser<telecommand::packet_id::SET_PLL_CLK_SRC> req;
881 req.deserialize(bit_stream);
882 auto &s = settings::get_instance();
883 s.set<settings::param::PLL_REF_CLK_SRC>(static_cast<uint32_t>(req.src));
884 /* Apply also ASAP the requested clock source */
886 radio.set_clk_src(req.src);
887 return true;
888 }
889
890private:
892 parser() : src(lib::radio::clk_src::INTERNAL) {}
893
894 void
895 deserialize(etl::bit_stream_reader &reader)
896 {
897 src = static_cast<lib::radio::clk_src>(reader.read<uint8_t>(1).value());
898 }
899};
900
902{
903public:
904 static bool
905 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
906 {
907 parser<telecommand::packet_id::SET_FILTER> req;
908 req.deserialize(bit_stream);
909 auto &s = settings::get_instance();
910 switch (req.iface) {
912 s.set<settings::param::UHF_FILTER>(req.filter);
913 break;
915 s.set<settings::param::SBAND_FILTER>(req.filter);
916 break;
917 default:
918 return false;
919 }
920 return true;
921 }
922
923private:
926 parser()
927 : iface(lib::radio::interface::UHF),
928 filter(lib::rf_frontend::filter::WIDE)
929 {
930 }
931
932 void
933 deserialize(etl::bit_stream_reader &reader)
934 {
935 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
936 filter =
937 static_cast<lib::rf_frontend::filter>(reader.read<uint8_t>(1).value());
938 }
939};
940
942{
943public:
944 static bool
945 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
946 {
947 auto &err = error_handler::get_instance();
948 err.system_reboot();
949 return true;
950 }
951
952private:
953 parser() = default;
954};
955
957{
958public:
959 static bool
960 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
961 {
962
963 auto &s = settings::get_instance();
964 s.reset_all();
965 return true;
966 }
967
968private:
969 parser() = default;
970};
971
973{
974public:
975 static bool
976 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
977 {
979 path.deserialize(bit_stream);
981 storage.rm(path.value);
982 return true;
983 }
984
985private:
986 parser() = default;
987};
988
990{
991public:
992 static bool
993 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
994 {
996 path.deserialize(bit_stream);
998 storage.rmdir(path.value);
999 return true;
1000 }
1001
1002private:
1003 parser() = default;
1004};
1005
1007{
1008public:
1009 static bool
1010 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1011 {
1013 path.deserialize(bit_stream);
1015 storage.mkdir(path.value);
1016 return true;
1017 }
1018
1019private:
1020 parser() = default;
1021};
1022
1024{
1025public:
1026 static bool
1027 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1028 {
1030 path.deserialize(bit_stream);
1031 parser<telecommand::packet_id::STORAGE_WRITE> data_length;
1032 data_length.deserialize(bit_stream);
1033 size_t offset = telecommand::ccsds_tc_header::size + sizeof(path.length) +
1034 path.length + sizeof(data_length.data_length);
1036 storage.write(path.value, (uint8_t *)(bit_stream.begin() + offset),
1037 data_length.data_length);
1038 return true;
1039 }
1040
1041private:
1042 size_t data_length;
1043 parser() : data_length(0) {}
1044
1045 void
1046 deserialize(etl::bit_stream_reader &reader)
1047 {
1048
1049 data_length = reader.read<uint32_t>(32).value();
1050 }
1051};
1052
1053template <>
1055{
1056public:
1057 static bool
1058 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1059 {
1061 path.deserialize(bit_stream);
1062
1063 parser<telecommand::packet_id::STORAGE_WRITE_OFFSET> off_len;
1064 off_len.deserialize(bit_stream);
1065 size_t offset = telecommand::ccsds_tc_header::size + sizeof(path.length) +
1066 path.length + sizeof(off_len.offset) +
1067 sizeof(off_len.data_length);
1069 storage.write(path.value, (uint8_t *)(bit_stream.begin() + offset),
1070 off_len.data_length, off_len.offset);
1071 return true;
1072 }
1073
1074private:
1075 size_t offset;
1076 size_t data_length;
1077 parser() : offset(0), data_length(0) {}
1078
1079 void
1080 deserialize(etl::bit_stream_reader &reader)
1081 {
1082 offset = reader.read<uint32_t>(32).value();
1083 data_length = reader.read<uint32_t>(32).value();
1084 }
1085};
1086
1088{
1089public:
1090 static bool
1091 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1092 {
1093
1094 auto &s = settings::get_instance();
1095 s.save();
1096 return true;
1097 }
1098
1099private:
1100 parser() = default;
1101};
1102
1104{
1105public:
1106 static bool
1107 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1108 {
1109 parser<telecommand::packet_id::SET_AGC0_CONF> req;
1110 req.deserialize(bit_stream);
1111 auto &s = settings::get_instance();
1112 switch (req.iface) {
1114 s.set<settings::param::UHF_GAIN0_TGT>(req.target);
1115 break;
1117 s.set<settings::param::SBAND_GAIN0_TGT>(req.target);
1118 break;
1119 default:
1120 return false;
1121 }
1122 return true;
1123 }
1124
1125private:
1127 float target;
1128 parser() : iface(lib::radio::interface::UHF), target(0.0f) {}
1129
1130 void
1131 deserialize(etl::bit_stream_reader &reader)
1132 {
1133 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1134 telecommand::deserialize(reader, target);
1135 }
1136};
1137
1139{
1140public:
1141 static bool
1142 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1143 {
1144 parser<telecommand::packet_id::SET_AGC1_CONF> req;
1145 req.deserialize(bit_stream);
1146 auto &s = settings::get_instance();
1147 switch (req.iface) {
1149 s.set<settings::param::UHF_GAIN1_AGC>(req.cnf);
1150 break;
1152 s.set<settings::param::SBAND_GAIN1_AGC>(req.cnf);
1153 break;
1154 default:
1155 return false;
1156 }
1157 return true;
1158 }
1159
1160private:
1162 settings::agc1 cnf;
1163 parser() : iface(lib::radio::interface::UHF) {}
1164
1165 void
1166 deserialize(etl::bit_stream_reader &reader)
1167 {
1168 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1169 cnf.avg =
1170 static_cast<at86rf215_agc_avgs_t>(reader.read<uint8_t>(2).value());
1171 cnf.input = reader.read<uint8_t>(1).value();
1172 cnf.tgt = static_cast<at86rf215_agc_tgt_t>(reader.read<uint8_t>(3).value());
1173 }
1174};
1175
1177{
1178public:
1179 static bool
1180 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1181 {
1182 parser<telecommand::packet_id::SET_GAIN0_CONF> req;
1183 req.deserialize(bit_stream);
1184 auto &s = settings::get_instance();
1185 switch (req.iface) {
1187 s.set<settings::param::UHF_GAIN0_GAIN>(req.gain);
1188 break;
1190 s.set<settings::param::SBAND_GAIN0_GAIN>(req.gain);
1191 break;
1192 default:
1193 return false;
1194 }
1195 return true;
1196 }
1197
1198private:
1200 float gain;
1201 parser() : iface(lib::radio::interface::UHF), gain(0.0f) {}
1202
1203 void
1204 deserialize(etl::bit_stream_reader &reader)
1205 {
1206
1207 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1208 telecommand::deserialize(reader, gain);
1209 }
1210};
1211
1213{
1214public:
1215 static bool
1216 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1217 {
1218 parser<telecommand::packet_id::SET_GAIN1_CONF> req;
1219 req.deserialize(bit_stream);
1220 auto &s = settings::get_instance();
1221 switch (req.iface) {
1223 s.set<settings::param::UHF_GAIN1_GAIN>(req.gain);
1224 break;
1226 s.set<settings::param::SBAND_GAIN1_GAIN>(req.gain);
1227 break;
1228 default:
1229 return false;
1230 }
1231 return true;
1232 }
1233
1234private:
1236 float gain;
1237 parser() : iface(lib::radio::interface::UHF), gain(0.0f) {}
1238
1239 void
1240 deserialize(etl::bit_stream_reader &reader)
1241 {
1242
1243 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1244 telecommand::deserialize(reader, gain);
1245 }
1246};
1247
1249{
1250public:
1251 static bool
1252 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1253 {
1254 parser<telecommand::packet_id::SET_MODULATION> req;
1255 req.deserialize(bit_stream);
1256 auto &s = settings::get_instance();
1257 if (req.iface == lib::radio::interface::UHF &&
1258 req.direction == lib::rf_frontend::dir::RX) {
1259 s.set<settings::param::UHF_RX_MODULATION>(req.modulation);
1260 } else if (req.iface == lib::radio::interface::UHF &&
1261 req.direction == lib::rf_frontend::dir::TX) {
1262 s.set<settings::param::UHF_TX_MODULATION>(req.modulation);
1263 } else if (req.iface == lib::radio::interface::SBAND &&
1264 req.direction == lib::rf_frontend::dir::RX) {
1265 s.set<settings::param::SBAND_RX_MODULATION>(req.modulation);
1266 } else if (req.iface == lib::radio::interface::SBAND &&
1267 req.direction == lib::rf_frontend::dir::TX) {
1268 s.set<settings::param::SBAND_TX_MODULATION>(req.modulation);
1269 } else {
1270 return false;
1271 }
1272 return true;
1273 }
1274
1275private:
1277 lib::rf_frontend::dir direction;
1278 lib::radio::modulation modulation;
1279 parser()
1280 : iface(lib::radio::interface::UHF),
1281 direction(lib::rf_frontend::dir::RX),
1282 modulation(lib::radio::modulation::FSK)
1283 {
1284 }
1285
1286 void
1287 deserialize(etl::bit_stream_reader &reader)
1288 {
1289 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1290 direction =
1291 static_cast<lib::rf_frontend::dir>(reader.read<uint8_t>(2).value());
1292 modulation =
1293 static_cast<lib::radio::modulation>(reader.read<uint8_t>(3).value());
1294 }
1295};
1296
1298{
1299public:
1300 static bool
1301 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1302 {
1303 parser<telecommand::packet_id::SET_TX_FSK_CONF> req;
1304 req.deserialize(bit_stream);
1305
1306 auto &s = settings::get_instance();
1307 switch (req.iface) {
1309 s.set<settings::param::UHF_FSK_TX>(req.cnf);
1310 break;
1312 s.set<settings::param::SBAND_FSK_TX>(req.cnf);
1313 break;
1314 default:
1315 return false;
1316 }
1317 return true;
1318 }
1319
1320private:
1322 settings::fsk cnf;
1323 parser() : iface(lib::radio::interface::UHF) {}
1324
1325 void
1326 deserialize(etl::bit_stream_reader &reader)
1327 {
1328 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1329 cnf.baudrate =
1330 static_cast<at86rf215_fsk_srate_t>(reader.read<uint8_t>(3).value());
1331 telecommand::deserialize(reader, cnf.mod_idx);
1332 telecommand::deserialize(reader, cnf.shaping);
1333 }
1334};
1335
1337{
1338public:
1339 static bool
1340 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1341 {
1342 parser<telecommand::packet_id::SET_RX_FSK_CONF> req;
1343 req.deserialize(bit_stream);
1344
1345 auto &s = settings::get_instance();
1346 switch (req.iface) {
1348 s.set<settings::param::UHF_FSK_RX>(req.cnf);
1349 break;
1351 s.set<settings::param::SBAND_FSK_RX>(req.cnf);
1352 break;
1353 default:
1354 return false;
1355 }
1356 return true;
1357 }
1358
1359private:
1361 settings::fsk cnf;
1362 parser() : iface(lib::radio::interface::UHF) {}
1363
1364 void
1365 deserialize(etl::bit_stream_reader &reader)
1366 {
1367 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1368 cnf.baudrate =
1369 static_cast<at86rf215_fsk_srate_t>(reader.read<uint8_t>(3).value());
1370 telecommand::deserialize(reader, cnf.mod_idx);
1371 cnf.shaping = 1.0f;
1372 }
1373};
1374
1376{
1377public:
1378 static bool
1379 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1380 {
1381
1382 /* Deserialize starting sector and data length */
1383 parser<telecommand::packet_id::DISK_RAW_WRITE> tlc;
1384 tlc.deserialize(bit_stream);
1385
1387 size_t sent =
1388 storage.write_raw(tlc.buffer, tlc.starting_sector, tlc.data_length);
1389
1390 if (sent < tlc.data_length) {
1391 return false;
1392 }
1393 return true;
1394 }
1395
1396private:
1397 uint32_t starting_sector;
1398 uint32_t data_length;
1399 const uint8_t *buffer;
1400
1401 parser() : starting_sector(0), data_length(0) {}
1402
1403 void
1404 deserialize(etl::bit_stream_reader &reader)
1405 {
1406 starting_sector = reader.read<uint32_t>(32).value();
1407 data_length = reader.read<uint32_t>(32).value();
1408 /* Buffer starts after the CCSDS header and the two 32-bit */
1409 buffer = reinterpret_cast<const uint8_t *>(
1410 reader.cbegin() + telecommand::ccsds_tc_header::size +
1411 sizeof(starting_sector) + sizeof(data_length));
1412 }
1413};
1414
1416{
1417public:
1418 static bool
1419 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1420 {
1421
1422 /* Deserialize starting sector and data length */
1423 parser<telecommand::packet_id::DISK_RAW_READ> tlc;
1424 tlc.deserialize(bit_stream);
1425
1427 tlc.sectors);
1428 return true;
1429 }
1430
1431private:
1432 uint32_t starting_sector;
1433 uint32_t sectors;
1434 parser() : starting_sector(0), sectors(0) {}
1435
1436 void
1437 deserialize(etl::bit_stream_reader &reader)
1438 {
1439 starting_sector = reader.read<uint32_t>(32).value();
1440 sectors = reader.read<uint32_t>(32).value();
1441 }
1442};
1443
1444template <>
1446{
1447public:
1448 static bool
1449 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1450 {
1451
1452 /* Deserialize starting sector and data length */
1453 parser<telecommand::packet_id::DISK_SECTORS_ERASE> tlc;
1454 tlc.deserialize(bit_stream);
1455
1457 storage.erase_sectors(tlc.starting_sector, tlc.sectors);
1458 return true;
1459 }
1460
1461private:
1462 uint32_t starting_sector;
1463 uint32_t sectors;
1464 parser() : starting_sector(0), sectors(0) {}
1465
1466 void
1467 deserialize(etl::bit_stream_reader &reader)
1468 {
1469 starting_sector = reader.read<uint32_t>(32).value();
1470 sectors = reader.read<uint32_t>(32).value();
1471 }
1472};
1473
1474template <>
1476{
1477public:
1478 static bool
1479 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1480 {
1481 parser<telecommand::packet_id::SET_THERMAL_MONITOR_PARAMS> req;
1482 req.deserialize(bit_stream);
1483 auto &s = settings::get_instance();
1485 req.uhf_shutdown_temperature);
1486 s.set<settings::param::THERMAL_UHF_ENABLE_TEMP>(req.uhf_enable_temperature);
1488 req.sband_shutdown_temperature);
1490 req.sband_enable_temperature);
1492 req.pcb_shutdown_temperature);
1493 s.set<settings::param::THERMAL_PCB_ENABLE_TEMP>(req.pcb_enable_temperature);
1494 s.set<settings::param::THERMAL_MIN_VALID_TEMP>(req.min_valid_temperature);
1495 s.set<settings::param::THERMAL_MAX_VALID_TEMP>(req.max_valid_temperature);
1496 return true;
1497 }
1498
1499private:
1500 float uhf_shutdown_temperature;
1501 float uhf_enable_temperature;
1502 float sband_shutdown_temperature;
1503 float sband_enable_temperature;
1504 float pcb_shutdown_temperature;
1505 float pcb_enable_temperature;
1506 float min_valid_temperature;
1507 float max_valid_temperature;
1508 parser()
1509 : uhf_shutdown_temperature(0.0f),
1510 uhf_enable_temperature(0.0f),
1511 sband_shutdown_temperature(0.0f),
1512 sband_enable_temperature(0.0f),
1513 pcb_shutdown_temperature(0.0f),
1514 pcb_enable_temperature(0.0f),
1515 min_valid_temperature(0.0f),
1516 max_valid_temperature(0.0f)
1517 {
1518 }
1519
1520 void
1521 deserialize(etl::bit_stream_reader &reader)
1522 {
1523 telecommand::deserialize(reader, uhf_shutdown_temperature);
1524 telecommand::deserialize(reader, uhf_enable_temperature);
1525 telecommand::deserialize(reader, sband_shutdown_temperature);
1526 telecommand::deserialize(reader, sband_enable_temperature);
1527 telecommand::deserialize(reader, pcb_shutdown_temperature);
1528 telecommand::deserialize(reader, pcb_enable_temperature);
1529 telecommand::deserialize(reader, min_valid_temperature);
1530 telecommand::deserialize(reader, max_valid_temperature);
1531 }
1532};
1533
1534template <>
1536{
1537public:
1538 static bool
1539 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1540 {
1541 parser<telecommand::packet_id::FPGA_SET_BOOT_MODE> tlc;
1542 tlc.deserialize(bit_stream);
1543 auto &fpga = lib::board::get_instance().fpga();
1544 fpga.set_boot_mode(tlc.m_boot_mode);
1545 auto &s = settings::get_instance();
1546 s.set<settings::param::FPGA_BOOT_MODE>(tlc.m_boot_mode);
1547 return true;
1548 }
1549
1550private:
1551 lib::fpga::boot_mode m_boot_mode;
1552 parser() : m_boot_mode(lib::fpga::boot_mode::QSPI) {}
1553
1554 void
1555 deserialize(etl::bit_stream_reader &reader)
1556 {
1557 m_boot_mode =
1558 static_cast<lib::fpga::boot_mode>(reader.read<uint8_t>(2).value());
1559 }
1560};
1561
1563{
1564public:
1565 static bool
1566 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1567 {
1568 parser<telecommand::packet_id::OTA_REQUEST> req;
1569 req.deserialize(bit_stream);
1570
1571 ota::response_tlm resp;
1572 auto &ota = ota::get_instance();
1573 ota.start(req.start, resp);
1575 return true;
1576 }
1577
1578private:
1579 ota::start_tlc start;
1580 parser() = default;
1581
1582 void
1583 deserialize(etl::bit_stream_reader &reader)
1584 {
1585 start.dst = static_cast<ota::subsys>(reader.read<uint8_t>(8).value());
1586 for (uint8_t i = 0; i < 32; i++) {
1587 start.sha256[i] = reader.read<uint8_t>(8).value();
1588 }
1589 start.size = reader.read<uint32_t>(32).value();
1590 start.slot = reader.read<uint8_t>(8).value();
1592 path.deserialize(reader);
1593 start.name.append(path.value.cbegin(),
1594 path.value.cbegin() +
1595 std::min(ota::MAX_FILE_LEN, path.length));
1596 }
1597};
1598
1600{
1601public:
1602 static bool
1603 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1604 {
1605 parser<telecommand::packet_id::OTA_DATA> req;
1606 req.deserialize(bit_stream);
1607 ota::response_tlm resp;
1608 auto &ota = ota::get_instance();
1609 ota.recv(req.data, resp);
1611 return true;
1612 }
1613
1614private:
1615 ota::data_tlc data;
1616 parser() = default;
1617
1618 void
1619 deserialize(etl::bit_stream_reader &reader)
1620 {
1621 data.session = reader.read<uint8_t>(8).value();
1622 data.seq = reader.read<uint32_t>(32).value();
1623 data.len = reader.read<uint32_t>(32).value();
1624 /* Buffer starts after the CCSDS header and the previous fields */
1625 data.data = reinterpret_cast<const uint8_t *>(
1626 reader.cbegin() + telecommand::ccsds_tc_header::size + 9);
1627 }
1628};
1629
1631{
1632public:
1633 static bool
1634 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream, int wdgid)
1635 {
1636 parser<telecommand::packet_id::OTA_FINISH> req;
1637 req.deserialize(bit_stream);
1638 ota::response_tlm resp;
1639 auto &ota = ota::get_instance();
1640 ota.finalize(req.fin, resp, wdgid);
1642 return true;
1643 }
1644
1645private:
1646 ota::fin_tlc fin;
1647 parser() = default;
1648
1649 void
1650 deserialize(etl::bit_stream_reader &reader)
1651 {
1652 fin.session = reader.read<uint8_t>(8).value();
1653 fin.method = reader.read<uint8_t>(8).value();
1654 fin.delay_secs = reader.read<uint32_t>(32).value();
1655 }
1656};
1657
1658template <>
1660{
1661public:
1662 static bool
1663 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1664 {
1665 parser<telecommand::packet_id::SET_RADIO_DUTY_CYCLE> req;
1666 req.deserialize(bit_stream);
1667
1668 auto &s = settings::get_instance();
1669 switch (req.iface) {
1671 s.set<settings::param::UHF_RX_ON_SECS>(req.on_secs);
1672 s.set<settings::param::UHF_RX_OFF_SECS>(req.off_secs);
1673 break;
1675 s.set<settings::param::SBAND_RX_ON_SECS>(req.on_secs);
1676 s.set<settings::param::SBAND_RX_OFF_SECS>(req.off_secs);
1677 break;
1678 default:
1679 return false;
1680 }
1681 return true;
1682 }
1683
1684private:
1686 uint32_t on_secs;
1687 uint32_t off_secs;
1688 parser() : iface(lib::radio::interface::UHF) {}
1689
1690 void
1691 deserialize(etl::bit_stream_reader &reader)
1692 {
1693 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1694 on_secs = reader.read<uint32_t>(32).value();
1695 off_secs = reader.read<uint32_t>(32).value();
1696 }
1697};
1698
1700{
1701public:
1702 static bool
1703 exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
1704 {
1705 parser<telecommand::packet_id::SET_TX_WAIT_MS> req;
1706 req.deserialize(bit_stream);
1707
1708 auto &s = settings::get_instance();
1709 switch (req.iface) {
1711 s.set<settings::param::UHF_TX_WAIT_MS>(req.time_ms);
1712 break;
1714 s.set<settings::param::SBAND_TX_WAIT_MS>(req.time_ms);
1715 break;
1716 default:
1717 return false;
1718 }
1719 return true;
1720 }
1721
1722private:
1724 uint32_t time_ms;
1725 parser() : iface(lib::radio::interface::UHF) {}
1726
1727 void
1728 deserialize(etl::bit_stream_reader &reader)
1729 {
1730 iface = static_cast<lib::radio::interface>(reader.read<uint8_t>(1).value());
1731 time_ms = reader.read<uint32_t>(32).value();
1732 }
1733};
1734
1743bool
1745 const msg_arbiter::msg &req, int wdgid)
1746{
1747 etl::bit_stream_reader bit_stream(etl::span(req.data, req.len),
1748 etl::endian::big);
1750 tc_header.deserialize(bit_stream);
1751 m_frame_count++;
1752 bool res = false;
1753
1754 switch (static_cast<packet_id>(tc_header.packet_id_type)) {
1755 case packet_id::PING: {
1759 return true;
1760 }
1762 return parse_tlm_req(resp, bit_stream);
1763 }
1765 return parser<packet_id::OTA_REQUEST>::exec(resp, bit_stream);
1766 }
1767 case packet_id::OTA_FINISH: {
1768 return parser<packet_id::OTA_FINISH>::exec(resp, bit_stream, wdgid);
1769 }
1770 case packet_id::OTA_DATA: {
1771 return parser<packet_id::OTA_DATA>::exec(resp, bit_stream);
1772 }
1774 res =
1776 break;
1777 }
1778 case packet_id::TESTS_STOP: {
1780 break;
1781 }
1784 break;
1785 }
1787 res =
1789 break;
1790 }
1793 bit_stream);
1794 break;
1795 }
1797 res =
1799 break;
1800 }
1801 case packet_id::FREQ_SET: {
1802 res = parser<telecommand::packet_id::FREQ_SET>::exec(resp, bit_stream);
1803 break;
1804 }
1805 case packet_id::TX_INHIBIT: {
1807 break;
1808 }
1809 case packet_id::TX_GAIN: {
1810 res = parser<telecommand::packet_id::TX_GAIN>::exec(resp, bit_stream);
1811 break;
1812 }
1815 break;
1816 }
1819 bit_stream);
1820 break;
1821 }
1822 case packet_id::EMMC_TEST: {
1824 break;
1825 }
1828 bit_stream);
1829 break;
1830 }
1832 res =
1834 break;
1835 }
1836 case packet_id::SET_RTC: {
1837 res = parser<telecommand::packet_id::SET_RTC>::exec(resp, bit_stream);
1838 break;
1839 }
1840 case packet_id::REBOOT: {
1841 res = parser<telecommand::packet_id::REBOOT>::exec(resp, bit_stream);
1842 break;
1843 }
1845 res =
1847 break;
1848 }
1850 res =
1852 break;
1853 }
1854 case packet_id::SET_FILTER: {
1856 break;
1857 }
1858 case packet_id::STORAGE_RM: {
1860 break;
1861 }
1864 break;
1865 }
1868 break;
1869 }
1872 break;
1873 }
1876 resp, bit_stream);
1877 break;
1878 }
1880 return parse_storage_tlm(resp, bit_stream,
1882 }
1883 case packet_id::STORAGE_LS: {
1884 return parse_storage_tlm(resp, bit_stream,
1886 }
1888 return parse_storage_tlm(resp, bit_stream,
1890 }
1892 return parse_ring_buffer_logs(resp, bit_stream);
1893 }
1896 break;
1897 }
1900 break;
1901 }
1904 break;
1905 }
1907 res =
1909 break;
1910 }
1912 res =
1914 break;
1915 }
1917 res =
1919 break;
1920 }
1922 res =
1924 break;
1925 }
1927 res =
1929 break;
1930 }
1932 res =
1934 break;
1935 }
1938 return res;
1939 }
1942 bit_stream);
1943 break;
1944 }
1947 bit_stream);
1948 break;
1949 }
1952 resp, bit_stream);
1953 break;
1954 }
1957 resp, bit_stream);
1958 break;
1959 }
1962 bit_stream);
1963 break;
1964 }
1967 resp, bit_stream);
1968 break;
1969 }
1972 resp, bit_stream);
1973 break;
1974 }
1977 bit_stream);
1978 break;
1979 }
1982 break;
1983 }
1986 resp, bit_stream);
1987 break;
1988 }
1990 res =
1992 break;
1993 }
1994 /*
1995 * If no match, either the TC was completely invalid, or it might be a mission
1996 * specific. In both cases, the handling stops here without any other action
1997 */
1998 default:
1999 return false;
2000 }
2002 return res;
2003}
2004
2005} // namespace satnogs::comms
static error_handler & get_instance()
Singleton access to the error_handler subsystem.
void reset_stats(scl::radio::interface iface)
Definition io.hpp:147
static io_wdg & get_instance()
Singleton access to the io_wdg subsystem.
Definition io_wdg.hpp:62
static io & get_instance()
Definition io.hpp:181
radio & radio_ctrl()
Definition io.cpp:139
comms::lib::radio & radio()
Returns a reference to the radio subsystem.
Definition board.cpp:80
comms::lib::fpga & fpga()
Returns a reference to the FPGA subsystem.
Definition board.cpp:113
static board & get_instance()
Gets a reference to the single instance of the Board interface class.
Definition board.cpp:66
Exception base class.
Definition exception.hpp:63
@ CRITICAL
Failure causing mission degradation or significant damage.
Definition exception.hpp:73
void set_boot_mode(boot_mode mode)
Definition fpga.cpp:133
modulation
Supported modulation schemes.
Definition radio.hpp:196
interface
Radio interface identifier.
Definition radio.hpp:177
clk_src
PLL Reference Clock identifier.
Definition radio.hpp:167
static logger & get_instance()
Singleton access to the logger subsystem.
Definition logger.hpp:102
static memory_monitor & get_instance()
uint8_t data[mtu]
Buffer to hold the data.
size_t len
Data size in bytes.
const uint8_t * data
Definition ota.hpp:113
etl::string< MAX_FILE_LEN > name
Definition ota.hpp:103
void recv(const data_tlc &tlc, response_tlm &tlm)
Definition ota.cpp:214
void finalize(const fin_tlc &tlc, response_tlm &tlm, int wdgid)
Definition ota.cpp:280
void reset_session(uint32_t id)
Definition ota.cpp:54
subsys
Destination target for a firmware file.
Definition ota.hpp:67
static ota & get_instance()
Definition ota.hpp:51
void start(const start_tlc &req, response_tlm &tlm)
Definition ota.cpp:84
static constexpr size_t MAX_FILE_LEN
The maximum supported filename length.
Definition ota.hpp:45
void confirm_image()
Sets the running firmware as confirmed.
Definition ota.cpp:346
void reset_sessions()
Definition ota.cpp:66
static settings & get_instance()
Get a singleton access to the settings subsystem.
Definition settings.hpp:210
void rmdir(const etl::istring &path)
Removes a directory and all its contents.
Definition storage.cpp:329
void mkdir(const etl::istring &path)
Creates a directory at the specified path.
Definition storage.cpp:248
size_t write_raw(const uint8_t *b, size_t start_sector, size_t len)
Writes raw bytes on the eMMC.
Definition storage.cpp:796
static storage & get_instance()
Definition storage.hpp:94
size_t write(const etl::istring &path, const uint8_t *b, size_t len)
Writes data to a file.
Definition storage.cpp:395
void erase_sectors(size_t start_sector, size_t sectors)
Erase a specific number of sectors.
Definition storage.cpp:887
void enable(bool en)
Enable or disable the storage subsystem.
Definition storage.cpp:125
void rm(const etl::istring &path)
Removes a file from the filesystem.
Definition storage.cpp:295
void set_dir(lib::emmc::dir d)
Set the direction of the eMMC.
Definition storage.cpp:206
void deserialize(etl::bit_stream_reader &reader)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream, int wdgid)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
static bool exec(msg_arbiter::msg &m, etl::bit_stream_reader &bit_stream)
void deserialize(etl::bit_stream_reader &reader)
etl::string< CONFIG_STORAGE_MAX_PATH_LEN > value
static void deserialize(etl::bit_stream_reader &reader, float &x)
telecommand(telecommand const &)=delete
bool decode_ccsds_xtce(msg_arbiter::msg &m, int wdgid)
bool ccsds_frame_valid(const uint8_t *b, size_t len)
static void send_ring_buffer_logs_tlm(msg_arbiter::msg &m, const size_t num_of_logs)
Definition telemetry.cpp:48
static void send_all_ota_sessions_info_tlm(msg_arbiter::msg &m)
Definition telemetry.cpp:93
static void tlm(msg_arbiter::msg &m, Args &&...args)
static test & get_instance()
Definition test.hpp:42
Time and position information.
Definition time.hpp:60
void set(const struct tm &t)
Sets the RTC time.
Definition time.cpp:200
static time & get_instance()
Definition time.hpp:63
static constexpr uint32_t MAX_TRX_MS
scl::radio radio
Definition settings.cpp:30
constexpr off_t offset
Definition settings.cpp:34
at86rf215_agc_avgs_t avg
Definition settings.hpp:158
at86rf215_agc_tgt_t tgt
Definition settings.hpp:157
at86rf215_fsk_srate_t baudrate
Definition settings.hpp:164