diff --git a/firmware/.cproject b/firmware/.cproject
index 483ad28a..9b04468e 100644
--- a/firmware/.cproject
+++ b/firmware/.cproject
@@ -54,6 +54,7 @@
+
@@ -201,4 +202,4 @@
-
\ No newline at end of file
+
diff --git a/firmware/app/libs/libconops/LICENSE b/firmware/app/libs/libconops/LICENSE
new file mode 100644
index 00000000..a5af3451
--- /dev/null
+++ b/firmware/app/libs/libconops/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Carlos Augusto Porto Freitas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/firmware/app/libs/libconops/README.rst b/firmware/app/libs/libconops/README.rst
new file mode 100644
index 00000000..a48ced1e
--- /dev/null
+++ b/firmware/app/libs/libconops/README.rst
@@ -0,0 +1,43 @@
+libconops
+=========
+
+A simple library to facilitate the mission control and planning.
+
+.. _building-sec:
+
+Building
+--------
+
+ Currently, the library supports both CMake and Meson. How to compile the library using them can be seen below.
+
+Meson
+~~~~~
+ To build the library with Meson, run the following command in the repo's root::
+
+ meson setup build
+ meson compile -C build
+
+CMake
+~~~~~
+ To build the library with CMake, run the following command in the repo's root::
+
+ mkdir build && cd build
+ cmake ..
+ make
+
+Tests
+-----
+
+ To run the library unit tests, assuming that the commands from `Building <#building>`_ were used, run the following commands.
+
+CMake builds
+~~~~~~~~~~~~
+ Run in the build directory::
+
+ ctest --output-on-failure
+
+Meson builds
+~~~~~~~~~~~~
+ Run in the repo's root::
+
+ meson test -C build --print-errorlogs
diff --git a/firmware/app/libs/libconops/include/conops/conops.h b/firmware/app/libs/libconops/include/conops/conops.h
new file mode 100644
index 00000000..e8b5f585
--- /dev/null
+++ b/firmware/app/libs/libconops/include/conops/conops.h
@@ -0,0 +1,77 @@
+#ifndef CONOPS_H_
+#define CONOPS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+/* Library ERRNO meanings */
+#define ERRNO_CONOPS_INVALID_ARG 1
+#define ERRNO_CONOPS_NO_TRANSITION_TABLE 2
+#define ERRNO_CONOPS_INSUFFICIENT_BUFFER_SIZE 3
+#define ERRNO_CONOPS_INVALID_STATE 4
+#define ERRNO_CONOPS_INVALID_EV_ID 5
+#define ERRNO_CONOPS_NO_MAPPER_FUNCTION 6
+#define ERRNO_CONOPS_MAPPING_ERROR 7
+#define ERRNO_CONOPS_INVALID_TRANSITION 8
+
+/* Library FSM default config */
+#define CONOPS_DEFAULT_N_STATES 256U
+#define CONOPS_DEFAULT_MAX_EV_ID UINT16_MAX
+#define CONOPS_DEFAULT_INIT_STATE 0U
+#define CONOPS_DEFAULT_EV_NAME_SIZE 12U
+#define CONOPS_DEFAULT_CALLBACK_IGNORE_SRC 0x5443
+
+/* Foward declarations */
+struct conops_fsm;
+struct conops_event;
+
+typedef int (*conops_transition_handler_t)(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to);
+
+typedef int32_t (*conops_event_mapper_t)(const struct conops_fsm *ctx,
+ const struct conops_event *ev);
+
+typedef void (*conops_event_callback_t)(struct conops_fsm *ctx, const struct conops_event *ev);
+
+typedef int (*conops_init_callback_t)(struct conops_fsm *ctx);
+
+struct conops_fsm_config {
+ uint16_t n_states;
+ uint16_t max_ev_id;
+ uint16_t init_state;
+};
+
+struct conops_fsm {
+ struct conops_fsm_config conf;
+ uint16_t state;
+ uint16_t last_valid_ev_id;
+ const void *transition_table;
+ void *user_data;
+ conops_event_mapper_t ev_mapper_fn;
+};
+
+struct conops_event {
+ uint16_t src;
+ uint16_t ev_id;
+ char ev_name[CONOPS_DEFAULT_EV_NAME_SIZE];
+ conops_event_callback_t callback;
+};
+
+int conops_fsm_init(struct conops_fsm *fsm, const void *transition_table, const uint16_t n_states,
+ const uint16_t max_ev_id, const uint16_t init_state,
+ conops_init_callback_t callback);
+
+int conops_fsm_process_event(struct conops_fsm *fsm, const struct conops_event *ev);
+
+int conops_register_mapper(struct conops_fsm *fsm, conops_event_mapper_t mapper);
+
+int conops_register_fsm_user_data(struct conops_fsm *fsm, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/firmware/app/libs/libconops/include/conops/util/cmd_queue.h b/firmware/app/libs/libconops/include/conops/util/cmd_queue.h
new file mode 100644
index 00000000..66e83704
--- /dev/null
+++ b/firmware/app/libs/libconops/include/conops/util/cmd_queue.h
@@ -0,0 +1,48 @@
+#ifndef CONOPS_CMD_QUEUE_H
+#define CONOPS_CMD_QUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+#define PAYLOAD_SIZE 20U
+#define CMD_QUEUE_CAPACITY 10U
+
+typedef void (*cmd_queue_lock_t)(void *lock);
+typedef void (*cmd_queue_unlock_t)(void *lock);
+
+struct conops_cmd {
+ uint32_t timestamp;
+ uint8_t payload[PAYLOAD_SIZE];
+};
+
+struct conops_cmd_queue {
+ struct conops_cmd buffer[CMD_QUEUE_CAPACITY];
+ uint16_t size;
+ void *lock;
+ cmd_queue_lock_t queue_lock;
+ cmd_queue_unlock_t queue_unlock;
+};
+
+void cmd_queue_init(struct conops_cmd_queue *queue, void *lock, cmd_queue_lock_t queue_lock,
+ cmd_queue_unlock_t queue_unlock);
+
+int cmd_queue_dequeue(struct conops_cmd_queue *queue, uint32_t current_time,
+ struct conops_cmd *out);
+
+int cmd_queue_enqueue(struct conops_cmd_queue *queue, const struct conops_cmd *cmd);
+
+void cmd_queue_reset(struct conops_cmd_queue *queue);
+
+bool cmd_queue_is_empty(const struct conops_cmd_queue *queue);
+
+void heapify_cmd_buffer(struct conops_cmd *buffer, uint16_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/firmware/app/libs/libconops/src/conops.c b/firmware/app/libs/libconops/src/conops.c
new file mode 100644
index 00000000..6adbe3c3
--- /dev/null
+++ b/firmware/app/libs/libconops/src/conops.c
@@ -0,0 +1,94 @@
+#include
+#include
+
+int conops_fsm_init(struct conops_fsm *fsm, const void *transition_table, const uint16_t n_states,
+ const uint16_t max_ev_id, const uint16_t init_state,
+ conops_init_callback_t callback)
+{
+ if (!fsm || !transition_table)
+ return -ERRNO_CONOPS_INVALID_ARG;
+
+ if (init_state >= n_states)
+ return -ERRNO_CONOPS_INVALID_STATE;
+
+ fsm->ev_mapper_fn = NULL;
+ fsm->user_data = NULL;
+ fsm->transition_table = transition_table;
+ fsm->conf.n_states = n_states;
+ fsm->conf.max_ev_id = (max_ev_id != 0) ? max_ev_id : CONOPS_DEFAULT_MAX_EV_ID;
+ fsm->conf.init_state = init_state;
+ fsm->state = init_state;
+
+ if (callback) {
+ return callback(fsm);
+ }
+
+ return 0;
+}
+
+int conops_fsm_process_event(struct conops_fsm *fsm, const struct conops_event *ev)
+{
+ int err = 0;
+
+ if (!fsm || !ev)
+ return -ERRNO_CONOPS_INVALID_ARG;
+
+ if (!fsm->transition_table)
+ return -ERRNO_CONOPS_NO_TRANSITION_TABLE;
+
+ if (ev->ev_id > fsm->conf.max_ev_id)
+ return -ERRNO_CONOPS_INVALID_EV_ID;
+
+ if (!fsm->ev_mapper_fn)
+ return -ERRNO_CONOPS_NO_MAPPER_FUNCTION;
+
+ int32_t transition_to = fsm->ev_mapper_fn(fsm, ev);
+
+ if (transition_to < 0)
+ return -ERRNO_CONOPS_MAPPING_ERROR;
+
+ const conops_transition_handler_t(*table)[fsm->conf.n_states] =
+ (const conops_transition_handler_t(*)[fsm->conf.n_states])fsm->transition_table;
+
+ conops_transition_handler_t handler = table[fsm->state][transition_to];
+
+ if (transition_to == fsm->state)
+ goto ev_callback_run;
+
+ if (handler) {
+ err = handler(fsm, ev, transition_to);
+
+ if (err < 0)
+ return err;
+ } else {
+ return -ERRNO_CONOPS_INVALID_TRANSITION;
+ }
+
+ev_callback_run:
+ if (ev->callback)
+ ev->callback(fsm, ev);
+
+ fsm->last_valid_ev_id = ev->ev_id;
+
+ return 0;
+}
+
+int conops_register_mapper(struct conops_fsm *fsm, conops_event_mapper_t mapper)
+{
+ if (!fsm || !mapper)
+ return -ERRNO_CONOPS_INVALID_ARG;
+
+ fsm->ev_mapper_fn = mapper;
+
+ return 0;
+}
+
+int conops_register_fsm_user_data(struct conops_fsm *fsm, void *user_data)
+{
+ if (!fsm || !user_data)
+ return -ERRNO_CONOPS_INVALID_ARG;
+
+ fsm->user_data = user_data;
+
+ return 0;
+}
diff --git a/firmware/app/libs/libconops/src/util/cmd_queue.c b/firmware/app/libs/libconops/src/util/cmd_queue.c
new file mode 100644
index 00000000..66a67ae6
--- /dev/null
+++ b/firmware/app/libs/libconops/src/util/cmd_queue.c
@@ -0,0 +1,139 @@
+#include
+
+#include
+
+static void default_queue_lock(void *lock)
+{
+ (void)lock;
+ return;
+}
+
+static void default_queue_unlock(void *lock)
+{
+ (void)lock;
+ return;
+}
+
+static void swap(struct conops_cmd *a, struct conops_cmd *b)
+{
+ struct conops_cmd temp;
+ (void)memcpy(&temp, a, sizeof(*a));
+ (void)memcpy(a, b, sizeof(*a));
+ (void)memcpy(b, &temp, sizeof(*b));
+}
+
+static void bubble_up(struct conops_cmd *buffer, uint16_t index)
+{
+ while (index > 0U) {
+ uint16_t parent_idx = (index - 1U) >> 1U;
+
+ if (buffer[parent_idx].timestamp <= buffer[index].timestamp)
+ break;
+
+ swap(&buffer[parent_idx], &buffer[index]);
+
+ index = parent_idx;
+ }
+}
+
+static void bubble_down(struct conops_cmd *buffer, uint16_t size, uint16_t index)
+{
+ while (true) {
+ uint16_t left = 2U * index + 1U;
+ uint16_t right = 2U * index + 2U;
+ uint16_t smallest = index;
+
+ if ((left < size) && (buffer[left].timestamp < buffer[smallest].timestamp))
+ smallest = left;
+
+ if ((right < size) && (buffer[right].timestamp < buffer[smallest].timestamp))
+ smallest = right;
+
+ if (smallest == index)
+ break;
+
+ swap(&buffer[index], &buffer[smallest]);
+
+ index = smallest;
+ }
+}
+
+void heapify_cmd_buffer(struct conops_cmd *buffer, uint16_t size)
+{
+ for (int32_t i = (int32_t)((size >> 1U) - 1U); i >= 0; i--) {
+ bubble_down(buffer, size, (uint16_t)i);
+ }
+}
+
+void cmd_queue_init(struct conops_cmd_queue *queue, void *lock, cmd_queue_lock_t queue_lock,
+ cmd_queue_unlock_t queue_unlock)
+{
+ if ((lock == NULL) || (queue_lock == NULL) || (queue_unlock == NULL)) {
+ queue->queue_lock = default_queue_lock;
+ queue->queue_unlock = default_queue_unlock;
+ queue->lock = NULL;
+ } else {
+ queue->queue_lock = queue_lock;
+ queue->queue_unlock = queue_unlock;
+ queue->lock = lock;
+ }
+ queue->size = 0;
+}
+
+int cmd_queue_enqueue(struct conops_cmd_queue *queue, const struct conops_cmd *cmd)
+{
+ int err = -1;
+
+ if (queue->size < CMD_QUEUE_CAPACITY) {
+ queue->queue_lock(queue->lock);
+
+ (void)memcpy(&queue->buffer[queue->size], cmd, sizeof(*cmd));
+
+ queue->size++;
+
+ bubble_up(queue->buffer, queue->size - 1U);
+
+ queue->queue_unlock(queue->lock);
+
+ err = 0;
+ }
+
+ return err;
+}
+
+int cmd_queue_dequeue(struct conops_cmd_queue *queue, uint32_t current_time, struct conops_cmd *out)
+{
+ int retval = 0;
+
+ if ((queue->size != 0U) && (queue->buffer[0].timestamp <= current_time)) {
+ queue->queue_lock(queue->lock);
+
+ (void)memcpy(out, &queue->buffer[0], sizeof(*out));
+
+ queue->size--;
+
+ if (queue->size > 0U) {
+ (void)memcpy(&queue->buffer[0], &queue->buffer[queue->size],
+ sizeof(queue->buffer[0]));
+ bubble_down(queue->buffer, queue->size, 0);
+ }
+
+ queue->queue_unlock(queue->lock);
+
+ retval = 1;
+ }
+
+ return retval;
+}
+
+void cmd_queue_reset(struct conops_cmd_queue *queue)
+{
+ queue->queue_lock(queue->lock);
+ queue->size = 0U;
+ queue->queue_unlock(queue->lock);
+}
+
+bool cmd_queue_is_empty(const struct conops_cmd_queue *queue)
+{
+ return (queue->size == 0U);
+}
diff --git a/firmware/app/structs/obdh_data.c b/firmware/app/structs/obdh_data.c
index e814616c..dd637318 100644
--- a/firmware/app/structs/obdh_data.c
+++ b/firmware/app/structs/obdh_data.c
@@ -33,9 +33,15 @@
* \{
*/
+#include
+#include
#include
#include
+#include
#include
+#include
+#include
+#include
#include "obdh_data.h"
#include "satellite.h"
@@ -55,7 +61,41 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
}
case OBDH_PARAM_ID_MODE:
{
- const event_t mode_change = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = (uint8_t)(*buf), .args[1] = 0U, .args[2] = 0U };
+ uint16_t mode = UINT16_MAX;
+
+ switch (*buf)
+ {
+ case OBDH_MODE_DEPLOYMENT:
+ mode = EV_TC_GOTO_DEPLOYMENT_MODE;
+ break;
+ case OBDH_MODE_NORMAL:
+ mode = EV_TC_GOTO_NORMAL_MODE;
+ break;
+ case OBDH_MODE_STAND_BY:
+ mode = EV_TC_GOTO_STAND_BY_MODE;
+ break;
+ case OBDH_MODE_EXPERIMENT:
+ mode = EV_TC_GOTO_EXPERIMENT_MODE;
+ break;
+ case OBDH_MODE_FDIR:
+ mode = EV_TC_GOTO_FDIR_MODE;
+ break;
+ case OBDH_MODE_MANUAL:
+ mode = EV_TC_GOTO_MANUAL_MODE;
+ break;
+ case OBDH_MODE_COMMISSION:
+ mode = EV_TC_GOTO_COMMISSION_MODE;
+ break;
+ default:
+ break;
+ }
+
+ const struct conops_event mode_change = {
+ .ev_id = mode,
+ .ev_name = "ModeCH",
+ .callback = NULL,
+ .src = 0U,
+ };
if (notify_event_to_mission_manager(&mode_change) != 0)
{
@@ -78,29 +118,9 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
}
break;
}
- case OBDH_PARAM_ID_MANUAL_MODE_ON:
+ case OBDH_PARAM_ID_ANT_DEPLOYMENT_COUNTER:
{
- if (*buf == 0x00U)
- {
- sat_data_buf.obdh.data.manual_mode_on = false;
-
- sys_log_print_event_from_module(SYS_LOG_INFO, OBDH_DATA_LOG_NAME, "Manual mode is now Off!");
- sys_log_new_line();
- }
- else if (*buf == 0x01U)
- {
- sat_data_buf.obdh.data.manual_mode_on = true;
-
- sys_log_print_event_from_module(SYS_LOG_INFO, OBDH_DATA_LOG_NAME, "Manual mode is now On!");
- sys_log_new_line();
- }
- else
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, OBDH_DATA_LOG_NAME, "Invalid value for Manual Mode ID");
- sys_log_new_line();
- err = -1;
- }
-
+ sat_data_buf.obdh.data.ant_deployment_counter = (uint8_t)(*buf);
break;
}
case OBDH_PARAM_ID_MAIN_EDC:
@@ -138,11 +158,25 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
break;
}
+ case OBDH_PARAM_ID_RESET_TC_QUEUE:
+ {
+ if (*buf == 0x01U)
+ {
+ reset_sched_tc_queue();
+ }
+
+ break;
+ }
case OBDH_PARAM_ID_MAIN_PAYLOAD_STATE:
{
if ((*buf == PL_ID_EDC_1) || (*buf == PL_ID_EDC_2))
{
- const event_t payload_activate = { .event = EV_NOTIFY_ACTIVATE_PAYLOAD_RQ, .args[0] = (uint8_t)(*buf), .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event payload_activate = {
+ .ev_id = EV_TC_ENABLE_PAYLOAD,
+ .src = (uint16_t)*buf,
+ .callback = NULL,
+ .ev_name = "MAIN_PL",
+ };
if (notify_event_to_mission_manager(&payload_activate) != 0)
{
@@ -153,7 +187,12 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
}
else if (*buf == 0U)
{
- const event_t payload_deactivate = { .event = EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ, .args[0] = sat_data_buf.obdh.data.main_payload_state, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event payload_deactivate = {
+ .ev_id = EV_TC_DISABLE_PAYLOAD,
+ .src = sat_data_buf.obdh.data.main_payload_state,
+ .callback = NULL,
+ .ev_name = "MAIN_PL",
+ };
if (notify_event_to_mission_manager(&payload_deactivate) != 0)
{
@@ -172,7 +211,12 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
{
if (*buf == PL_ID_PAYLOAD_X)
{
- const event_t payload_activate = { .event = EV_NOTIFY_ACTIVATE_PAYLOAD_RQ, .args[0] = (uint8_t)(*buf), .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event payload_activate = {
+ .ev_id = EV_TC_ENABLE_PAYLOAD,
+ .src = (uint16_t)*buf,
+ .callback = NULL,
+ .ev_name = "SEC_PL",
+ };
if (notify_event_to_mission_manager(&payload_activate) != 0)
{
@@ -183,7 +227,12 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
}
else if (*buf == 0U)
{
- const event_t payload_deactivate = { .event = EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ, .args[0] = (uint8_t)PL_ID_PAYLOAD_X, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event payload_deactivate = {
+ .ev_id = EV_TC_DISABLE_PAYLOAD,
+ .src = (uint16_t)PAYLOAD_X,
+ .callback = NULL,
+ .ev_name = "SEC_PL",
+ };
if (notify_event_to_mission_manager(&payload_deactivate) != 0)
{
@@ -205,6 +254,52 @@ int8_t obdh_set_param(uint8_t param_id, uint32_t *buf)
taskEXIT_CRITICAL();
break;
}
+ case OBDH_PARAM_ID_TS_COMMISSION_TIMEOUT:
+ {
+ taskENTER_CRITICAL();
+ sat_data_buf.obdh.data.ts_commission_timeout = *buf;
+ taskEXIT_CRITICAL();
+ break;
+ }
+ case OBDH_PARAM_ID_EPS_BEACON_ON:
+ {
+ uint8_t retry_count = 5U;
+
+ if ((*buf == 0x00U) || (*buf == 0x01U))
+ {
+ sat_data_buf.obdh.data.eps_beacon_on = (bool)(*buf);
+ do
+ {
+ err = eps_set_param(SL_EPS2_REG_BEACON_ENABLE, *buf);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+ }
+ else
+ {
+ err = -1;
+ }
+
+ break;
+ }
+ case OBDH_PARAM_ID_BATT_CRITICAL_LEVEL_MV:
+ {
+ sat_data_buf.obdh.data.batt_crit_level_mv = *buf;
+ break;
+ }
+ case OBDH_PARAM_ID_MANUAL_EXPERIMENT_ON:
+ {
+ if ((*buf == 0x00U) || (*buf == 0x01U))
+ {
+ sat_data_buf.obdh.data.manual_experiments = (bool)(*buf);
+ }
+ else
+ {
+ err = -1;
+ }
+
+ break;
+ }
default:
sys_log_print_event_from_module(SYS_LOG_ERROR, OBDH_DATA_LOG_NAME, "Received invalid parameter: ");
sys_log_print_hex((uint32_t)param_id);
@@ -249,7 +344,6 @@ int8_t obdh_get_param(uint8_t param_id, uint32_t *buf)
case OBDH_PARAM_ID_LAST_PAGE_EDC_DATA: *buf = sat_data_buf.obdh.data.media.last_page_edc_data; break;
case OBDH_PARAM_ID_LAST_PAGE_PX_DATA: *buf = sat_data_buf.obdh.data.media.last_page_px_data; break;
case OBDH_PARAM_ID_LAST_PAGE_SBCD_PKTS: *buf = sat_data_buf.obdh.data.media.last_page_sbcd_pkts; break;
- case OBDH_PARAM_ID_MANUAL_MODE_ON: *buf = sat_data_buf.obdh.data.manual_mode_on; break;
case OBDH_PARAM_ID_MAIN_EDC: *buf = sat_data_buf.obdh.data.main_edc; break;
case OBDH_PARAM_ID_GENERAL_TELEMETRY_ON: *buf = sat_data_buf.obdh.data.general_telemetry_on; break;
case OBDH_PARAM_ID_TS_LAST_TLE_UPDATE: *buf = sat_data_buf.obdh.data.position.ts_last_tle_update; break;
@@ -259,6 +353,13 @@ int8_t obdh_get_param(uint8_t param_id, uint32_t *buf)
case OBDH_PARAM_ID_HIB_DURATION: *buf = sat_data_buf.obdh.data.hib_duration; break;
case OBDH_PARAM_ID_TS_POSITION: *buf = sat_data_buf.obdh.data.position.timestamp; break;
case OBDH_PARAM_ID_TS_LAST_CONTACT: *buf = sat_data_buf.obdh.data.ts_last_contact; break;
+ case OBDH_PARAM_ID_TS_COMMISSION_TIMEOUT: *buf = sat_data_buf.obdh.data.ts_commission_timeout; break;
+ case OBDH_PARAM_ID_EPS_BEACON_ON: *buf = sat_data_buf.obdh.data.eps_beacon_on; break;
+ case OBDH_PARAM_ID_BATT_CRITICAL_LEVEL_MV: *buf = sat_data_buf.obdh.data.batt_crit_level_mv; break;
+ case OBDH_PARAM_ID_HIBERNATION_ON: *buf = sat_data_buf.obdh.data.hibernation_on; break;
+ case OBDH_PARAM_ID_MANUAL_EXPERIMENT_ON: *buf = sat_data_buf.obdh.data.manual_experiments; break;
+ case OBDH_PARAM_ID_TC_QUEUE_SIZE: *buf = sat_data_buf.obdh.data.tc_queue_size; break;
+ case OBDH_PARAM_ID_TS_NEXT_SCHED_TC: *buf = sat_data_buf.obdh.data.ts_next_sched_tc; break;
default:
sys_log_print_event_from_module(SYS_LOG_ERROR, OBDH_DATA_LOG_NAME, "Received invalid parameter: ");
sys_log_print_hex((uint32_t)param_id);
diff --git a/firmware/app/structs/obdh_data.h b/firmware/app/structs/obdh_data.h
index 3d1e9020..a105ddb4 100644
--- a/firmware/app/structs/obdh_data.h
+++ b/firmware/app/structs/obdh_data.h
@@ -73,7 +73,7 @@
#define OBDH_PARAM_ID_LAST_PAGE_EDC_DATA 24U /**< Last used memory page of the EDC data. */
#define OBDH_PARAM_ID_LAST_PAGE_PX_DATA 25U /**< Last used memory page of the Payload-X data. */
#define OBDH_PARAM_ID_LAST_PAGE_SBCD_PKTS 26U /**< Last used memory page of the SBCD packets. */
-#define OBDH_PARAM_ID_MANUAL_MODE_ON 27U /**< Manual operation mode selection flag. */
+#define OBDH_PARAM_ID_HIBERNATION_ON 27U /**< Satellite in hibernation flag. */
#define OBDH_PARAM_ID_MAIN_EDC 28U /**< Main EDC ID. */
#define OBDH_PARAM_ID_GENERAL_TELEMETRY_ON 29U /**< General telemetry on flag. */
#define OBDH_PARAM_ID_RESET_DEVICE 30U /**< Resets device (Only write param, writing "0x01" to it resets OBDH). */
@@ -85,6 +85,14 @@
#define OBDH_PARAM_ID_BIN_TLE 36U /**< Compact binary TLE line. More about the format on libpredict */
#define OBDH_PARAM_ID_TS_POSITION 37U /**< Timestamp of the last position determination. */
#define OBDH_PARAM_ID_TS_LAST_CONTACT 38U /**< Timestamp of the last received TC by ground station. */
+#define OBDH_PARAM_ID_TS_COMMISSION_TIMEOUT 39U /**< Timestamp when commission mode will timeout. */
+#define OBDH_PARAM_ID_LAST_TRAN_EV_ID 40U /**< Last valid event id that caused an mode transition. */
+#define OBDH_PARAM_ID_EPS_BEACON_ON 41U /**< EPS beacon on flag. */
+#define OBDH_PARAM_ID_BATT_CRITICAL_LEVEL_MV 42U /**< Battery critical level threshold in millivolts. */
+#define OBDH_PARAM_ID_MANUAL_EXPERIMENT_ON 43U /**< Flag to state if the experiments are manually enabled. */
+#define OBDH_PARAM_ID_RESET_TC_QUEUE 44U /**< Resets the TC Queue (Only write param, writing "0x01" to it resets the queue) */
+#define OBDH_PARAM_ID_TC_QUEUE_SIZE 45U /**< Current TC Queue size */
+#define OBDH_PARAM_ID_TS_NEXT_SCHED_TC 46U /**< Next scheduled telecommand execution timestamp. */
/* Default values */
#define OBDH_TIMESTAMP_DEFAULT_VAL 0U
@@ -103,11 +111,12 @@
#define OBDH_PARAM_INITIAL_HIB_TIME_COUNT_DEFAULT_VAL 0U
#define OBDH_PARAM_ANT_DEPLOYMENT_EXECUTED_DEFAULT_VAL 0U
#define OBDH_PARAM_ANT_DEPLOYMENT_COUNTER_DEFAULT_VAL 0U
-#define OBDH_PARAM_MANUAL_MODE_ON_DEFAULT_VAL 0U
+#define OBDH_PARAM_HIBERNATION_ON_DEFAULT_VAL 1U
#define OBDH_PARAM_MAIN_EDC_DEFAULT_VAL 1U
#define OBDH_PARAM_MAIN_PAYLOAD_STATE_DEFAULT_VAL 0U
#define OBDH_PARAM_SEC_PAYLOAD_STATE_DEFAULT_VAL 0U
-#define OBDH_PARAM_GENERAL_TELEMETRY_ON_DEFAUL_VAL 1U
+#define OBDH_PARAM_GENERAL_TELEMETRY_ON_DEFAUL_VAL 0U
+#define OBDH_PARAM_MANUAL_EXPERIMENT_ON_DEFAUL_VAL 1U
#define OBDH_PARAM_POSITION_TIMESTAMP_DEFAULT_VAL 0U
#define OBDH_PARAM_POSITION_TS_LAST_TLE_UPT_DEFAULT_VAL 0U
#define OBDH_PARAM_POSITION_BIN_TLE_DEFAULT_VAL {0x00, 0x19, 0x40, 0x50, 0x14, 0x90, 0xFC, 0x7C, 0x92, 0xCE, 0x00, 0x00, 0x1C, 0xA3, 0x43, 0x4E, 0x4F, 0xCC, 0x43, 0x19, 0xCA, 0x37, 0x3A, 0x87, 0x80, 0x92, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x4C, 0x4F, 0x4B, 0xC6, 0xA7, 0xEF, 0x9E, 0x40, 0x2E, 0x9D, 0x69, 0xF3, 0xE4, 0x93, 0xBE} /* HORYU-4 TLE converted to libpredict compact format */
@@ -124,24 +133,24 @@
#define OBDH_PARAM_MEDIA_LAST_SBCD_PKTS_DEFAULT_VAL CONFIG_MEM_SBCD_PKTS_START_PAGE
#define OBDH_PARAM_TS_READ_SENSORS_DEFAULT_VAL 0U
#define OBDH_PARAM_TS_LAST_CONTACT_TIME_DEFAULT_VAL 0U
-
-/* Operation modes */
-#define OBDH_MODE_NORMAL 0U
-#define OBDH_MODE_HIBERNATION 1U
-#define OBDH_MODE_STAND_BY 2U
-#define OBDH_WAKE_UP 3U
+#define OBDH_PARAM_TS_COMMISSION_TIMEOUT_DEFAULT_VAL 0U
+#define OBDH_PARAM_LAST_TRAN_EV_ID_DEFAULT_VAL 0U
+#define OBDH_PARAM_EPS_BEACON_ON_DEFAULT_VAL 0U
+#define OBDH_PARAM_BATT_CRITICAL_LEVEL_MV_DEFAULT_VAL 6500U
+#define OBDH_PARAM_TC_QUEUE_SIZE_DEFAULT_VAL 0U
+#define OBDH_PARAM_TS_NEXT_SCHED_TC_DEFAULT_VAL 0U
/**
* \brief Position data.
*/
typedef struct
{
- uint8_t bin_tle[50]; /**< Binary compact TLE lines. */
sys_time_t timestamp; /**< Timestamp of the position data. */
sys_time_t ts_last_tle_update; /**< Timestamp of the last TLE update. */
int16_t latitude; /**< Latitude in degrees. */
int16_t altitude; /**< Altitude in kilometers. */
int16_t longitude; /**< Lontitude in degrees. */
+ uint8_t bin_tle[50]; /**< Binary compact TLE lines. */
} position_data_t;
/**
@@ -164,31 +173,38 @@ typedef struct
*/
typedef struct
{
- media_data_t media; /**< Memories data. */
- sys_time_t ts_last_mode_change; /**< Timestamp of the last change in the operation mode. */
- sys_time_t ts_read_sensors; /**< Timestamp of the last sensor readings. */
- sys_time_t ts_last_contact; /**< Timestamp of the last TC reception. */
- sys_time_t hib_duration; /**< Hibernation duration in seconds. */
- uint32_t fw_version; /**< Firmware version (ex.: "v1.2.3" = 0x00010203). */
- uint16_t temperature; /**< Temperature of the uC in Kelvin. */
- uint16_t current; /**< Input current in mA. */
- uint16_t voltage; /**< Input voltage in mV. */
- uint16_t reset_counter; /**< Reset counter. */
- uint8_t mode; /**< Satellite mode. */
- uint8_t last_reset_cause; /**< Last reset cause code. */
- uint8_t last_valid_tc; /**< Last valid telecommand ID. */
- uint8_t ant_deployment_counter; /**< Antenna deployment counter. */
- uint8_t initial_hib_time_count; /**< Initial hibernation time counter in minutes. */
- uint8_t hw_version; /**< Hardware version. */
- uint8_t main_edc; /**< Main EDC. */
- uint8_t main_payload_state; /**< Main payload state. (PL_ID for active and 0 for inactive.) */
- uint8_t sec_payload_state; /**< Secundary payload state. (PL_ID for active and 0 for inactive.) */
- bool initial_hib_executed; /**< Initial hibernation executed flag. */
- bool ant_deployment_executed; /**< Antenna deployment executed flag. */
- bool manual_mode_on; /**< Manual operation mode selection flag. */
- bool general_telemetry_on; /**< General telemetry on flag. */
- position_data_t position; /**< Current position of the satellite. */
-} obdh_data_t;
+ media_data_t media; /**< Memories data. */
+ sys_time_t ts_last_mode_change; /**< Timestamp of the last change in the operation mode. */
+ sys_time_t ts_read_sensors; /**< Timestamp of the last sensor readings. */
+ sys_time_t ts_last_contact; /**< Timestamp of the last TC reception. */
+ sys_time_t ts_commission_timeout; /**< Timestamp when the commission mode will timeout. */
+ sys_time_t hib_duration; /**< Hibernation duration in seconds. */
+ sys_time_t ts_next_sched_tc; /**< Next scheduled telecommand execution timestamp. */
+ uint32_t fw_version; /**< Firmware version (ex.: "v1.2.3" = 0x00010203). */
+ uint16_t temperature; /**< Temperature of the uC in Kelvin. */
+ uint16_t current; /**< Input current in mA. */
+ uint16_t voltage; /**< Input voltage in mV. */
+ uint16_t reset_counter; /**< Reset counter. */
+ uint16_t last_tran_ev_id; /**< Last valid event id that caused an mode transition */
+ uint16_t batt_crit_level_mv; /**< Battery critical level threshold in millivolts */
+ uint8_t mode; /**< Satellite mode. */
+ uint8_t last_reset_cause; /**< Last reset cause code. */
+ uint8_t last_valid_tc; /**< Last valid telecommand ID. */
+ uint8_t ant_deployment_counter; /**< Antenna deployment counter. */
+ uint8_t initial_hib_time_count; /**< Initial hibernation time counter in minutes. */
+ uint8_t hw_version; /**< Hardware version. */
+ uint8_t main_edc; /**< Main EDC. */
+ uint8_t main_payload_state; /**< Main payload state. (PL_ID for active and 0 for inactive.) */
+ uint8_t sec_payload_state; /**< Secundary payload state. (PL_ID for active and 0 for inactive.) */
+ uint8_t tc_queue_size; /**< Current TC Queue size */
+ bool initial_hib_executed; /**< Initial hibernation executed flag. */
+ bool ant_deployment_executed; /**< Antenna deployment executed flag. */
+ bool hibernation_on; /**< Satellite in hibernation flag. */
+ bool general_telemetry_on; /**< General telemetry on flag. */
+ bool eps_beacon_on; /**< EPS beacon on. */
+ bool manual_experiments; /**< Flag to state if the experiments are manually enabled. */
+ position_data_t position; /**< Current position of the satellite. */
+} obdh_data_t;
/**
* \brief Reads a OBDH parameter.
diff --git a/firmware/app/structs/satellite.h b/firmware/app/structs/satellite.h
index 269277cd..f086a0b9 100644
--- a/firmware/app/structs/satellite.h
+++ b/firmware/app/structs/satellite.h
@@ -44,6 +44,7 @@
#include
#include
+#include
#include
#include
@@ -57,7 +58,7 @@ typedef enum {
PKT_ID_DOWNLINK_PING_ANS = 0x02,
PKT_ID_DOWNLINK_GENERAL_TELEMETRY = 0x10,
PKT_ID_DOWNLINK_DATA_REQUEST_ANS = 0x11,
- PKT_ID_DOWNLINK_PAYLOAD_DATA = 0x12,
+ PKT_ID_DOWNLINK_SUBSYSTEM_TABLE = 0x12,
PKT_ID_DOWNLINK_TC_FEEDBACK = 0x13,
PKT_ID_DOWNLINK_PARAM_VALUE = 0x14,
PKT_ID_DOWNLINK_PACKET_BROADCAST = 0x15,
@@ -72,11 +73,12 @@ typedef enum {
PKT_ID_UPLINK_DEACTIVATE_PAYLOAD = 0x48,
PKT_ID_UPLINK_ERASE_MEMORY = 0x49,
PKT_ID_UPLINK_FORCE_RESET = 0x4A,
- PKT_ID_UPLINK_GET_PAYLOAD_DATA = 0x4B,
+ PKT_ID_UPLINK_GET_SUBSYSTEM_TABLE = 0x4B,
PKT_ID_UPLINK_SET_PARAM = 0x4C,
PKT_ID_UPLINK_GET_PARAM = 0x4D,
PKT_ID_UPLINK_TRANSMIT_PACKET = 0x4E,
PKT_ID_UPLINK_UPDATE_TLE = 0x4F,
+ PKT_ID_UPLINK_SCHED_TC = 0x50,
} packet_id_e;
/**
@@ -121,6 +123,21 @@ typedef enum {
DATA_ID_PAYLOAD_INFO = 6,
} data_id_e;
+/**
+ * \brief Table IDs
+ */
+typedef enum {
+ TABLE_ID_OBDH = 0,
+ TABLE_ID_EPS = 1,
+ TABLE_ID_TTC_0 = 2,
+ TABLE_ID_TTC_1 = 3,
+ TABLE_ID_ANT = 4,
+ TABLE_ID_SBCD = 5,
+ TABLE_ID_EDC_0 = 6,
+ TABLE_ID_EDC_1 = 7,
+ TABLE_ID_PAYLOAD_X = 8,
+} table_id_e;
+
/**
* \brief Memory IDs
*/
@@ -129,6 +146,16 @@ typedef enum {
MEMORY_ID_FRAM = 1,
} memory_id_e;
+/**
+ * \brief Feedback Error codes.
+ */
+#define ERRNO_FB_SUCESSFULL_EXEC (0)
+#define ERRNO_FB_MISSION_MANAGER_NOTIFY_TIMEOUT (-1)
+#define ERRNO_FB_SUBSYSTEM_COMM_FAIL (-2)
+#define ERRNO_FB_DEVICE_COMM_FAIL (-3)
+#define ERRNO_FB_FAILED_TO_UPDATE_FRAM (-4)
+#define ERRNO_FB_FAILED_TO_SCHED_TC (-5)
+
/**
* \brief OBDH telemetry type.
*/
@@ -175,12 +202,24 @@ typedef struct
uint8_t data[220]; /**< Payload data. */
} payload_telemetry_t;
+/**
+ * \brief EDC telemetry type.
+ */
+typedef struct
+{
+ sys_time_t timestamp; /**< Timestamp of the Payload data. */
+ uint8_t id; /**< Payload id [Ex: CONFIG_PL_ID_EDC_1] */
+ edc_hk_t hk; /**< EDC Housekeeping */
+ edc_state_t state; /**< EDC State */
+ edc_ptt_t ptt; /**< EDC PTT Packet */
+} edc_telemetry_t;
+
/**
* \brief Payloads state type.
*/
typedef struct
{
- payload_telemetry_t *c_edc; /**< Pointer to the active EDC telemetry data. */
+ edc_telemetry_t *c_edc; /**< Pointer to the active EDC telemetry data. */
} payload_state_t;
/**
@@ -193,8 +232,8 @@ typedef struct
ttc_telemetry_t ttc_0; /**< TTC 0 telemetry. */
ttc_telemetry_t ttc_1; /**< TTC 1 telemetry. */
antenna_telemetry_t antenna; /**< Antenna telemetry. */
- payload_telemetry_t edc_0; /**< EDC 0 telemetry. */
- payload_telemetry_t edc_1; /**< EDC 1 telemetry. */
+ edc_telemetry_t edc_0; /**< EDC 0 telemetry. */
+ edc_telemetry_t edc_1; /**< EDC 1 telemetry. */
payload_telemetry_t payload_x; /**< Payload-X telemetry. */
payload_state_t state; /**< Payload state. */
} sat_data_t;
diff --git a/firmware/app/tasks/antenna_deployment.c b/firmware/app/tasks/antenna_deployment.c
index 3bea5a76..5be5c259 100644
--- a/firmware/app/tasks/antenna_deployment.c
+++ b/firmware/app/tasks/antenna_deployment.c
@@ -34,7 +34,9 @@
* \{
*/
+#include "tasks/mission_manager.h"
#include
+#include
#include
#include
@@ -48,15 +50,26 @@ xTaskHandle xTaskAntennaDeploymentHandle;
void vTaskAntennaDeployment(void *p)
{
(void)p;
+
/* Initial hibernation */
if (!sat_data_buf.obdh.data.initial_hib_executed)
{
uint8_t initial_hib_time_counter = sat_data_buf.obdh.data.initial_hib_time_count;
- uint8_t i = 0;
+ taskENTER_CRITICAL();
+ sat_data_buf.obdh.data.hib_duration = (uint32_t)CONFIG_ANTENNA_DEPLOYMENT_HIBERNATION_MIN * 60UL;
+ sat_data_buf.obdh.data.hibernation_on = true;
+ taskEXIT_CRITICAL();
+ uint8_t i = 0;
for(i = initial_hib_time_counter; (i < CONFIG_ANTENNA_DEPLOYMENT_HIBERNATION_MIN) && (!sat_data_buf.obdh.data.initial_hib_executed); i++)
{
+ uint32_t hib_dur = CONFIG_ANTENNA_DEPLOYMENT_HIBERNATION_MIN - (uint32_t)i;
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_ANTENNA_DEPLOYMENT_NAME, "Antenna deployment will happen in ");
+ sys_log_print_uint(hib_dur);
+ sys_log_print_msg(" minutes!");
+ sys_log_new_line();
+
vTaskDelay(pdMS_TO_TICKS(60000U));
sat_data_buf.obdh.data.initial_hib_time_count++;
@@ -89,6 +102,19 @@ void vTaskAntennaDeployment(void *p)
sat_data_buf.obdh.data.ant_deployment_executed = true;
sat_data_buf.obdh.data.ant_deployment_counter++;
+
+ const struct conops_event ant_deploy = {
+ .ev_id = EV_DEPLOYMENT_COMPLETE,
+ .ev_name = "DEPLOY_END",
+ .src = 0U,
+ .callback = NULL,
+ };
+
+ if (notify_event_to_mission_manager(&ant_deploy) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_ANTENNA_DEPLOYMENT_NAME, "Failed to notify Mission Manager of Antenna Deploy!");
+ sys_log_new_line();
+ }
}
else
{
diff --git a/firmware/app/tasks/data_log.c b/firmware/app/tasks/data_log.c
index 7d6b4c19..5c863265 100644
--- a/firmware/app/tasks/data_log.c
+++ b/firmware/app/tasks/data_log.c
@@ -154,7 +154,7 @@ void vTaskDataLog(void *p)
(void)memset(&page_buf[0], 0, 256);
/* EDC data */
- (void)memcpy(&page_buf[0], (void*)sat_data_buf.state.c_edc, sizeof(payload_telemetry_t));
+ (void)memcpy(&page_buf[0], (void*)sat_data_buf.state.c_edc, sizeof(edc_telemetry_t));
if (mem_mng_write_data_to_flash_page(page_buf, &sat_data_buf.obdh.data.media.last_page_edc_data, nor_info.page_size, CONFIG_MEM_EDC_DATA_START_PAGE, CONFIG_MEM_EDC_DATA_END_PAGE) == 0)
{
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_DATA_LOG_NAME, "Writing to EDC sector, flash page number: ");
diff --git a/firmware/app/tasks/general_telemetry.c b/firmware/app/tasks/general_telemetry.c
index fad2a026..088cfa7b 100644
--- a/firmware/app/tasks/general_telemetry.c
+++ b/firmware/app/tasks/general_telemetry.c
@@ -176,15 +176,21 @@ void vTaskGeneralTelemetry(void *p)
gen_tel_pl.payload[94] = (sat_data_buf.obdh.data.ts_last_contact >> 16U) & 0xFFU;
gen_tel_pl.payload[95] = (sat_data_buf.obdh.data.ts_last_contact >> 8U) & 0xFFU;
gen_tel_pl.payload[96] = sat_data_buf.obdh.data.ts_last_contact & 0xFFU;
+ gen_tel_pl.payload[97] = (sat_data_buf.obdh.data.ts_next_sched_tc >> 24U) & 0xFFU;
+ gen_tel_pl.payload[98] = (sat_data_buf.obdh.data.ts_next_sched_tc >> 16U) & 0xFFU;
+ gen_tel_pl.payload[99] = (sat_data_buf.obdh.data.ts_next_sched_tc >> 8U) & 0xFFU;
+ gen_tel_pl.payload[100] = sat_data_buf.obdh.data.ts_next_sched_tc & 0xFFU;
+ gen_tel_pl.payload[101] = sat_data_buf.obdh.data.tc_queue_size;
+ gen_tel_pl.payload[102] = sat_data_buf.obdh.data.mode;
- gen_tel_pl.length = 97U;
+ gen_tel_pl.length = 103U;
uint8_t gen_tel_pl_raw[120] = {0};
uint16_t gen_tel_pl_raw_len = 0;
fsat_pkt_encode(&gen_tel_pl, gen_tel_pl_raw, &gen_tel_pl_raw_len);
- if ((sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION) && (sat_data_buf.obdh.data.general_telemetry_on))
+ if ((!sat_data_buf.obdh.data.hibernation_on) && (sat_data_buf.obdh.data.general_telemetry_on))
{
if (ttc_send(TTC_0, gen_tel_pl_raw, gen_tel_pl_raw_len) != 0)
{
diff --git a/firmware/app/tasks/housekeeping.c b/firmware/app/tasks/housekeeping.c
index 308ffea2..8c3724cd 100644
--- a/firmware/app/tasks/housekeeping.c
+++ b/firmware/app/tasks/housekeeping.c
@@ -34,6 +34,9 @@
* \{
*/
+#include
+#include
+#include
#include
#include
@@ -46,6 +49,7 @@
#include "housekeeping.h"
#include "mission_manager.h"
#include "startup.h"
+#include "sched_tc.h"
xTaskHandle xTaskHousekeepingHandle;
@@ -61,7 +65,7 @@ void vTaskHousekeeping(void *p)
while(1)
{
/* Hibernation mode check */
- if (sat_data_buf.obdh.data.mode == OBDH_MODE_HIBERNATION)
+ if ((sat_data_buf.obdh.data.hibernation_on) && (sat_data_buf.obdh.data.mode != OBDH_MODE_DEPLOYMENT))
{
uint32_t hib = sat_data_buf.obdh.data.hib_duration;
@@ -81,7 +85,12 @@ void vTaskHousekeeping(void *p)
if (sat_data_buf.obdh.data.hib_duration == 0U)
{
- const event_t leave_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_WAKE_UP, .args[1] = HOUSEKEEPING_WAKE_UP_RQ, .args[2] = 0U };
+ const struct conops_event leave_hib = {
+ .callback = NULL,
+ .ev_name = "WAKE-UP",
+ .src = 0U,
+ .ev_id = EV_HIBERNATION_TIMEOUT,
+ };
if (notify_event_to_mission_manager(&leave_hib) != 0)
{
@@ -91,18 +100,82 @@ void vTaskHousekeeping(void *p)
}
}
+ vTaskDelay(pdMS_TO_TICKS(100U));
+
+ if (sat_data_buf.obdh.data.mode == OBDH_MODE_COMMISSION)
+ {
+ if (system_get_time() >= sat_data_buf.obdh.data.ts_commission_timeout)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HOUSEKEEPING_NAME, "Commission Mode timedout! Notifying Mission Manager...");
+ sys_log_new_line();
+
+ const struct conops_event commission_timeout = {
+ .callback = NULL,
+ .ev_name = "COMM-TIME",
+ .src = 0U,
+ .ev_id = EV_COMISSION_TIMEOUT,
+ };
+
+ if (notify_event_to_mission_manager(&commission_timeout) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HOUSEKEEPING_NAME, "Failed to notify Commission Timeout event");
+ sys_log_new_line();
+ }
+ }
+ }
+
/* Save the last available OBDH data at every minute */
- if (mem_mng_save_obdh_data_to_fram(&sat_data_buf.obdh) != 0)
+ if (mem_mng_save_obdh_data_to_fram(&sat_data_buf.obdh) == 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HOUSEKEEPING_NAME, "Error writing data to the FRAM memory!");
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HOUSEKEEPING_NAME, "Saved OBDH data to FRAM!");
sys_log_new_line();
}
else
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HOUSEKEEPING_NAME, "Saving obdh data to fram...");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HOUSEKEEPING_NAME, "Error writing data to FRAM!");
sys_log_new_line();
}
-
+
+ vTaskDelay(pdMS_TO_TICKS(50U));
+
+ uint32_t eps_beacon_state = UINT32_MAX;
+
+ if (eps_get_param(SL_EPS2_REG_BEACON_ENABLE, &eps_beacon_state) == 0)
+ {
+ if (eps_beacon_state != (uint32_t)sat_data_buf.obdh.data.eps_beacon_on)
+ {
+ int err = 0;
+ uint8_t retry_count = 5U;
+
+ do
+ {
+ err = eps_set_param(SL_EPS2_REG_BEACON_ENABLE, (uint32_t)sat_data_buf.obdh.data.eps_beacon_on);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HOUSEKEEPING_NAME, "Failed to update EPS beacon state!");
+ sys_log_new_line();
+ }
+ }
+ }
+
+ vTaskDelay(pdMS_TO_TICKS(50U));
+
+ /* Save the last available TC Queue at every minute */
+ if (save_sched_tc_queue_to_fram() == 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HOUSEKEEPING_NAME, "Saved TC Queue to FRAM!");
+ sys_log_new_line();
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HOUSEKEEPING_NAME, "Error saving TC Queue to FRAM!");
+ sys_log_new_line();
+ }
+
vTaskDelayUntil(&last_cycle, pdMS_TO_TICKS(TASK_HOUSEKEEPING_PERIOD_MS));
}
}
diff --git a/firmware/app/tasks/housekeeping.h b/firmware/app/tasks/housekeeping.h
index 4534b786..a4d48598 100644
--- a/firmware/app/tasks/housekeeping.h
+++ b/firmware/app/tasks/housekeeping.h
@@ -42,7 +42,7 @@
#include
#define TASK_HOUSEKEEPING_NAME "Housekeeping" /**< Task name. */
-#define TASK_HOUSEKEEPING_STACK_SIZE 225 /**< Stack size in bytes. */
+#define TASK_HOUSEKEEPING_STACK_SIZE 512 /**< Stack size in bytes. */
#define TASK_HOUSEKEEPING_PRIORITY 3 /**< Task priority. */
#define TASK_HOUSEKEEPING_PERIOD_MS (60000) /**< Task period in milliseconds. */
#define TASK_HOUSEKEEPING_INIT_TIMEOUT_MS 5000 /**< Wait time to initialize the task in milliseconds. */
diff --git a/firmware/app/tasks/mission_manager.c b/firmware/app/tasks/mission_manager.c
index 3dc2d71b..be0f5a20 100644
--- a/firmware/app/tasks/mission_manager.c
+++ b/firmware/app/tasks/mission_manager.c
@@ -1,40 +1,41 @@
/*
* mission_manager.c
- *
+ *
* Copyright The OBDH 2.0 Contributors.
- *
+ *
* This file is part of OBDH 2.0.
- *
+ *
* OBDH 2.0 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* OBDH 2.0 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with OBDH 2.0. If not, see .
- *
+ *
*/
/**
* \brief Mission Manager Task implementation
- *
+ *
* \author Carlos Augusto Porto Freitas
- *
+ *
* \version 1.0.0
- *
+ *
* \date 2024/08/04
- *
+ *
* \addtogroup mission_man
* \{
*/
#include
#include
+#include
#include
#include
@@ -43,6 +44,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
@@ -52,585 +56,1058 @@
#include "system_reset.h"
#include "process_tc.h"
#include "startup.h"
+#include "pos_det.h"
-static void handle_event(const event_t *ev);
-static int8_t handle_mode_change_rq(const uint8_t *args);
-static int8_t activate_payload_rq(const uint8_t *args);
-static int8_t deactivate_payload_rq(const uint8_t *args);
-static int8_t satellite_persist_state(sat_data_t *sat);
-
-static int enable_ttc_tx(void);
-static int disable_ttc_tx(void);
+static inline int32_t handle_deployment_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
+{
+ (void)ctx;
-static bool in_hibernation = false;
-static bool in_brazil = false;
+ int32_t transition_to = OBDH_MODE_DEPLOYMENT;
-QueueHandle_t event_queue;
+ switch (ev->ev_id)
+ {
+ case EV_OUT_OF_BRAZIL:
+ break;
+ case EV_IN_BRAZIL:
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ case EV_TC_GOTO_COMMISSION_MODE:
+ transition_to = OBDH_MODE_COMMISSION;
+ break;
+ case EV_DEPLOYMENT_COMPLETE:
+ transition_to = OBDH_MODE_COMMISSION;
+ break;
+ default:
+ transition_to = -1;
+ break;
+ }
-TaskHandle_t xTaskMissionManagerHandle;
+ return transition_to;
+}
-void vTaskMissionManager(void *p)
+static inline int32_t handle_commission_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
{
- (void)p;
+ sat_data_t *sat = ctx->user_data;
+ int transition_to = OBDH_MODE_COMMISSION;
- event_t ev;
+ switch (ev->ev_id)
+ {
+ /* In commission there's simple no reason to react to position related
+ * events since the TLEs are still not updated */
+ case EV_OUT_OF_BRAZIL:
+ break;
+ case EV_IN_BRAZIL:
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ case EV_TC_ENABLE_PAYLOAD:
+ {
+ payload_t pl = (payload_t)ev->src;
- (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_MISSION_MANAGER_STARTUP_TIMEOUT_MS));
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Enabling Payload (");
+ sys_log_print_hex((uint32_t)ev->src);
+ sys_log_print_msg(") manually...");
+ sys_log_new_line();
- if (satellite_persist_state(&sat_data_buf) != 0)
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to restore state!");
- sys_log_new_line();
- }
+ if (payload_enable(pl) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable Payload!");
+ sys_log_new_line();
+ }
- while (1)
- {
- if (xQueueReceive(event_queue, &ev, pdMS_TO_TICKS_64(TASK_MISSION_MANAGER_EV_NOTIFICATION_TIMEOUT)) == pdPASS)
- {
- handle_event(&ev);
+ break;
}
- else
+ case EV_TC_DISABLE_PAYLOAD:
{
- sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_MISSION_MANAGER_NAME, "Notification waiting timed out!");
+ payload_t pl = (payload_t)ev->src;
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Disabling Payload (");
+ sys_log_print_hex((uint32_t)ev->src);
+ sys_log_print_msg(") manually...");
sys_log_new_line();
+
+ if (payload_disable(pl) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Payload!");
+ sys_log_new_line();
+ }
+
+ break;
}
+ case EV_COMISSION_TIMEOUT:
+ if (is_satellite_in_brazil((float)sat->obdh.data.position.latitude, (float)sat->obdh.data.position.longitude))
+ {
+ transition_to = OBDH_MODE_NORMAL;
+ }
+ else
+ {
+ transition_to = OBDH_MODE_STAND_BY;
+ }
+
+ break;
+ case EV_BATTERY_LEVEL_CRITICAL:
+ (void)payload_disable(PAYLOAD_X);
+ (void)payload_disable(PAYLOAD_EDC_0);
+ (void)payload_disable(PAYLOAD_EDC_1);
+ break;
+ default:
+ transition_to = -1;
+ break;
}
+
+ return transition_to;
}
-int8_t notify_event_to_mission_manager(const event_t *ev)
+static inline int32_t handle_nominal_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
{
- int8_t err = 0;
+ sat_data_t *sat = ctx->user_data;
+ int32_t transition_to = OBDH_MODE_NORMAL;
- if (xQueueSendToBack(event_queue, ev, pdMS_TO_TICKS(10U)) != pdPASS)
+ switch (ev->ev_id)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, "Event Queue", "Failed to enqueue event");
- sys_log_new_line();
-
- err = -1;
+ case EV_OUT_OF_BRAZIL:
+ if (sat->obdh.data.manual_experiments)
+ {
+ transition_to = OBDH_MODE_STAND_BY;
+ }
+ else
+ {
+ transition_to = OBDH_MODE_EXPERIMENT;
+ }
+ break;
+ case EV_IN_BRAZIL:
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_BATTERY_LEVEL_CRITICAL:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ default:
+ transition_to = -1;
+ break;
}
- return err;
+ return transition_to;
}
-void satellite_change_mode(const uint8_t mode)
+static inline int32_t handle_standby_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
{
- /* This ensures the mode change is done atomically */
- taskENTER_CRITICAL();
- sat_data_buf.obdh.data.mode = mode;
- sat_data_buf.obdh.data.ts_last_mode_change = system_get_time();
- taskEXIT_CRITICAL();
+ (void)ctx;
+ int32_t transition_to = OBDH_MODE_STAND_BY;
+
+ switch (ev->ev_id)
+ {
+ case EV_OUT_OF_BRAZIL:
+ break;
+ case EV_IN_BRAZIL:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_BATTERY_LEVEL_CRITICAL:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ default:
+ transition_to = -1;
+ break;
+ }
+
+ return transition_to;
}
-static int8_t satellite_persist_state(sat_data_t *sat)
+static inline int32_t handle_experiment_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
{
- int8_t err = 0;
- uint8_t args[3] = {0};
+ (void)ctx;
+ int32_t transition_to = OBDH_MODE_EXPERIMENT;
- uint8_t main_pl = sat->obdh.data.main_payload_state;
- uint8_t sec_pl = sat->obdh.data.sec_payload_state;
+ switch (ev->ev_id)
+ {
+ case EV_OUT_OF_BRAZIL:
+ break;
+ case EV_IN_BRAZIL:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_BATTERY_LEVEL_CRITICAL:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ case EV_PX_FINISHED:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ default:
+ transition_to = -1;
+ break;
+ }
+
+ return transition_to;
+}
- if (main_pl != (uint8_t)PAYLOAD_NONE)
+static inline int32_t handle_fdir_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
+{
+ sat_data_t *sat = ctx->user_data;
+ int32_t transition_to = OBDH_MODE_FDIR;
+
+ switch (ev->ev_id)
{
- args[0] = main_pl;
+ case EV_OUT_OF_BRAZIL:
+ break;
+ case EV_IN_BRAZIL:
+ break;
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_BATTERY_LEVEL_CRITICAL:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ case EV_FDIR_RESOLVED:
+ if (is_satellite_in_brazil((float)sat->obdh.data.position.latitude, (float)sat->obdh.data.position.longitude))
+ {
+ transition_to = OBDH_MODE_NORMAL;
+ }
+ else
+ {
+ transition_to = OBDH_MODE_STAND_BY;
+ }
+ break;
+ default:
+ transition_to = -1;
+ break;
+ }
+
+ return transition_to;
+}
+
+static inline int32_t handle_manual_evs(const struct conops_fsm *ctx, const struct conops_event *ev)
+{
+ (void)ctx;
+ int transition_to = OBDH_MODE_MANUAL;
- if (activate_payload_rq(args) == 0)
+ switch (ev->ev_id)
+ {
+ case EV_TC_GOTO_NORMAL_MODE:
+ transition_to = OBDH_MODE_NORMAL;
+ break;
+ case EV_TC_GOTO_FDIR_MODE:
+ transition_to = OBDH_MODE_FDIR;
+ break;
+ case EV_TC_GOTO_EXPERIMENT_MODE:
+ transition_to = OBDH_MODE_EXPERIMENT;
+ break;
+ case EV_TC_GOTO_STAND_BY_MODE:
+ transition_to = OBDH_MODE_STAND_BY;
+ break;
+ case EV_TC_GOTO_MANUAL_MODE:
+ transition_to = OBDH_MODE_MANUAL;
+ break;
+ case EV_TC_ENABLE_PAYLOAD:
{
- sat->state.c_edc = (main_pl == (uint8_t)PAYLOAD_EDC_0) ? &sat_data_buf.edc_0 : &sat_data_buf.edc_1;
+ payload_t pl = (payload_t)ev->src;
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Enabling Payload (");
+ sys_log_print_hex((uint32_t)ev->src);
+ sys_log_print_msg(") manually...");
+ sys_log_new_line();
+
+ if (payload_enable(pl) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable Payload!");
+ sys_log_new_line();
+ }
+
+ break;
}
- else
+ case EV_TC_DISABLE_PAYLOAD:
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to activate main payload on Mission Manager initialization!");
+ payload_t pl = (payload_t)ev->src;
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Disabling Payload (");
+ sys_log_print_hex((uint32_t)ev->src);
+ sys_log_print_msg(") manually...");
sys_log_new_line();
- sat->state.c_edc = NULL;
- err = -1;
+
+ if (payload_disable(pl) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Payload!");
+ sys_log_new_line();
+ }
+
+ break;
}
- }
+ default:
+ transition_to = -1;
+ break;
+ }
+
+ return transition_to;
+}
+
+static int enable_ttc_tx(void)
+{
+ int err = 0;
+ uint8_t retry_count = 5U;
- if (sec_pl != (uint8_t)PAYLOAD_NONE)
+ do
{
- args[0] = sec_pl;
+ err = 0;
+
+ if (ttc_leave_hibernation(TTC_0) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable TTC 0 TX");
+ sys_log_new_line();
+ err--;
+ }
- if (activate_payload_rq(args) != 0)
+ if (ttc_leave_hibernation(TTC_1) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to activate secundary payload on Mission Manager initialization!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable TTC 1 TX");
sys_log_new_line();
- err = -1;
+ err--;
}
+
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
+ {
+ err = -1;
}
return err;
}
-static void handle_event(const event_t *ev)
+static int disable_ttc_tx(void)
{
- switch (ev->event)
+ int err = 0;
+ uint8_t retry_count = 5U;
+
+ do
{
- case EV_NOTIFY_IN_BRAZIL:
+ err = 0;
+
+ if (ttc_enter_hibernation(TTC_0) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Satellite in Brazil!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable TTC 0 TX");
sys_log_new_line();
-
- in_brazil = true;
+ err--;
+ }
- if (!sat_data_buf.obdh.data.manual_mode_on)
- {
- /* Enable Main EDC and update state */
- payload_t main = sat_data_buf.obdh.data.main_edc;
+ if (ttc_enter_hibernation(TTC_1) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable TTC 1 TX");
+ sys_log_new_line();
+ err--;
+ }
- if (main != PAYLOAD_NONE)
- {
- if (sat_data_buf.obdh.data.main_payload_state != (uint8_t)main)
- {
- (void)payload_disable(sat_data_buf.obdh.data.main_payload_state);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
+ {
+ err = -1;
+ }
- /* Update satellite state */
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)main;
- sat_data_buf.state.c_edc = (main == PAYLOAD_EDC_0) ? &sat_data_buf.edc_0 : &sat_data_buf.edc_1;
+ return err;
+}
- (void)payload_enable(main);
+#if defined (CONFIG_MISSION_GOLDS_UFSC) && (CONFIG_MISSION_GOLDS_UFSC == 1)
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
- }
- }
- }
+static int goto_commission_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
+{
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
+ int retval = 0;
+ int err = 0;
+ uint8_t retry_count = 5U;
- break;
- }
- case EV_NOTIFY_OUT_OF_BRAZIL:
- {
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Satellite out of Brazil!");
- sys_log_new_line();
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Transitioning to Commission Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
- in_brazil = false;
+ sat->obdh.data.hibernation_on = false;
+ sat->obdh.data.general_telemetry_on = true;
+ sat->obdh.data.eps_beacon_on = true;
+ sat->obdh.data.ts_commission_timeout = system_get_time() + (uint32_t)COMMISSION_MODE_TIMEOUT_SEC;
+ sat->obdh.data.hib_duration = 0U;
- if (!sat_data_buf.obdh.data.manual_mode_on)
- {
- if (sat_data_buf.obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE)
- {
- (void)payload_disable((payload_t)sat_data_buf.obdh.data.main_payload_state);
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
- }
+ if (enable_ttc_tx() < 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable TTC transmission!");
+ sys_log_new_line();
+ }
- #if defined (CONFIG_DEV_PAYLOAD_X_ENABLED) && defined (CONFIG_TASK_PAYLOAD_X_ENABLED) && (CONFIG_DEV_PAYLOAD_X_ENABLED == 1) && (CONFIG_TASK_PAYLOAD_X_ENABLED == 1)
- /* Activate PX */
- if (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE)
- {
- const uint32_t px_active_time_ms = (uint32_t)PAYLOAD_X_EXPERIMENT_PERIOD_MS;
- sat_data_buf.obdh.data.sec_payload_state = (uint8_t)PAYLOAD_X;
-
- (void)payload_enable(PAYLOAD_X);
-
- /* Send notifcation to read_px task to initialize experiment */
- (void)xTaskNotify(xTaskReadPXHandle, px_active_time_ms, eSetValueWithOverwrite);
-
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
- }
- #else
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
- #endif
- }
+ do
+ {
+ err = eps_set_param(SL_EPS2_REG_BEACON_ENABLE, 1U);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- break;
- }
- #if defined (CONFIG_DEV_PAYLOAD_X_ENABLED) && defined (CONFIG_TASK_PAYLOAD_X_ENABLED) && (CONFIG_DEV_PAYLOAD_X_ENABLED == 1) && (CONFIG_TASK_PAYLOAD_X_ENABLED == 1)
- case EV_NOTIFY_PX_FINISHED:
- {
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "PX Exp finished");
- sys_log_new_line();
+ if (retry_count == 0U)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable EPS beacon!");
+ sys_log_new_line();
+ }
- if (!sat_data_buf.obdh.data.manual_mode_on)
- {
- /* Deactivate PX */
- sat_data_buf.obdh.data.sec_payload_state = (uint8_t)PAYLOAD_NONE;
+ if ((ev->ev_id != EV_PERSIST_STATE_ON_INIT) && (retval == 0))
+ {
+ satellite_change_mode(OBDH_MODE_COMMISSION);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_COMMISSION;
+ }
- (void)payload_disable(PAYLOAD_X);
+ return retval;
+}
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
- }
+static int goto_standby_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
+{
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
+ int retval = 0;
+ int err = 0;
+ uint8_t retry_count = 5U;
- break;
- }
- #endif
- case EV_NOTIFY_MODE_CHANGE_RQ:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Transitioning to Stand-by Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
+
+ if (sat->obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE)
+ {
+ do
{
- int8_t err = handle_mode_change_rq(ev->args);
+ err = payload_disable((payload_t)sat->obdh.data.main_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- if (err == 0)
- {
- (void)xTaskNotify(xTaskProcessTCHandle, 0U, eNoAction);
- }
- else if (err == HOUSEKEEPING_WAKE_UP_RQ)
- {
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Housekeeping Wake Up!");
- sys_log_new_line();
- }
- else
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to handle mode change EV");
- sys_log_new_line();
- }
- break;
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
}
- case EV_NOTIFY_ACTIVATE_PAYLOAD_RQ:
+ else
{
- if (activate_payload_rq(ev->args) == 0)
- {
- (void)xTaskNotify(xTaskProcessTCHandle, 0U, eNoAction);
- }
- else
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to handle activate payload EV");
- sys_log_new_line();
- }
- break;
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Main payload!");
+ sys_log_new_line();
+ retval = -1;
}
- case EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ:
+
+ err = 0;
+ retry_count = 5U;
+ }
+
+ if (sat->obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE)
+ {
+ do
{
- if (deactivate_payload_rq(ev->args) == 0)
- {
- (void)xTaskNotify(xTaskProcessTCHandle, 0U, eNoAction);
- }
- else
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to handle activate payload EV");
- sys_log_new_line();
- }
- break;
+ err = payload_disable((payload_t)sat->obdh.data.sec_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.sec_payload_state = (uint8_t)PAYLOAD_NONE;
}
- default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Invalid event notifcation was made!");
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Secondary payload!");
sys_log_new_line();
- break;
+ retval = -1;
+ }
+ }
+
+ if ((ev->ev_id != EV_PERSIST_STATE_ON_INIT) && (retval == 0))
+ {
+ satellite_change_mode(OBDH_MODE_STAND_BY);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_STAND_BY;
}
+
+ return retval;
}
-static int8_t handle_mode_change_rq(const uint8_t *args)
+static int goto_nominal_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
{
- int8_t err = 0;
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
+ int retval = 0;
+ int err = 0;
+ uint8_t retry_count = 5U;
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Transitioning to Nominal Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
- switch (args[0])
+ if (sat->obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE)
{
- case OBDH_MODE_NORMAL:
+ do
{
- if (in_hibernation)
- {
- if (enable_ttc_tx() == 0)
- {
- in_hibernation = false;
- }
- else
- {
- err = -1;
- }
- }
-
- if ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (err == 0))
- {
- payload_t main = sat_data_buf.obdh.data.main_edc;
+ err = payload_disable((payload_t)sat->obdh.data.sec_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- if (main != PAYLOAD_NONE)
- {
- if (sat_data_buf.obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE)
- {
- (void)payload_disable((payload_t)sat_data_buf.obdh.data.sec_payload_state);
- }
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.sec_payload_state = (uint8_t)PAYLOAD_NONE;
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Secondary payload!");
+ sys_log_new_line();
+ retval = -1;
+ }
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)main;
- sat_data_buf.state.c_edc = (main == PAYLOAD_EDC_0) ? &sat_data_buf.edc_0 : &sat_data_buf.edc_1;
+ err = 0;
+ retry_count = 5U;
+ }
- (void)payload_enable(main);
- }
- else
- {
- err = -1;
- }
- }
+ payload_t main = (payload_t)sat->obdh.data.main_edc;
- if (err == 0)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
+ if (main != PAYLOAD_NONE)
+ {
+ if ((sat->obdh.data.main_payload_state != (uint8_t)main) && (sat->obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE))
+ {
+ (void)payload_disable((payload_t)sat_data_buf.obdh.data.main_payload_state);
+ }
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Entering Nominal Mode!");
- sys_log_new_line();
- }
+ do
+ {
+ err = payload_enable(main);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- break;
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.main_payload_state = (uint8_t)main;
+ sat->state.c_edc = (main == PAYLOAD_EDC_0) ? &sat_data_buf.edc_0 : &sat_data_buf.edc_1;
}
- case OBDH_MODE_HIBERNATION:
+ else
{
- taskENTER_CRITICAL();
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable Main payload!");
+ sys_log_new_line();
+ retval = -1;
+ }
+ }
- in_hibernation = true;
- sys_time_t hib_duration_hours = (((sys_time_t)args[1] << 8) | (sys_time_t)args[2]);
- sat_data_buf.obdh.data.hib_duration = hib_duration_hours * 60UL * 60UL;
+ if ((ev->ev_id != EV_PERSIST_STATE_ON_INIT) && (retval == 0))
+ {
+ satellite_change_mode(OBDH_MODE_NORMAL);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_NORMAL;
+ }
- taskEXIT_CRITICAL();
+ return retval;
+}
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Hibernating for ");
- sys_log_print_uint(hib_duration_hours);
- sys_log_print_msg(" hours!");
- sys_log_new_line();
+static int goto_experiment_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
+{
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
+ int retval = 0;
+ int err = 0;
+ uint8_t retry_count = 5U;
- satellite_change_mode(OBDH_MODE_HIBERNATION);
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Transitioning to Experiment Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
- (void)disable_ttc_tx();
- break;
- }
- case OBDH_MODE_STAND_BY:
+ if (sat->obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE)
+ {
+ do
{
- if (sat_data_buf.obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE)
- {
- (void)payload_disable((payload_t)sat_data_buf.obdh.data.main_payload_state);
- sat_data_buf.obdh.data.main_payload_state = PAYLOAD_NONE;
- }
-
- if (sat_data_buf.obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE)
- {
- (void)payload_disable((payload_t)sat_data_buf.obdh.data.sec_payload_state);
- sat_data_buf.obdh.data.sec_payload_state = PAYLOAD_NONE;
- }
-
- satellite_change_mode(OBDH_MODE_STAND_BY);
-
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Entering Stand-by Mode!");
- sys_log_new_line();
+ err = payload_disable((payload_t)sat->obdh.data.main_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- break;
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
}
- case OBDH_WAKE_UP:
+ else
{
- in_hibernation = false;
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Main payload!");
+ sys_log_new_line();
+ retval = -1;
+ }
- if (in_brazil || (sat_data_buf.obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE) || (sat_data_buf.obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE))
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
- else
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
+ err = 0;
+ retry_count = 5U;
+ }
- (void)enable_ttc_tx();
+ do
+ {
+ err = payload_enable(PAYLOAD_X);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- if (args[1] == (uint8_t)HOUSEKEEPING_WAKE_UP_RQ)
- {
- err = (int8_t)HOUSEKEEPING_WAKE_UP_RQ;
- }
+ if (retry_count != 0U)
+ {
+ const uint32_t px_active_time_ms = (uint32_t)PAYLOAD_X_EXPERIMENT_PERIOD_MS;
+ sat->obdh.data.sec_payload_state = (uint8_t)PAYLOAD_X;
- break;
- }
- default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Invalid Mode received");
- sys_log_new_line();
- err = -1;
- break;
+ /* Send notifcation to read_px task to initialize experiment */
+ (void)xTaskNotify(xTaskReadPXHandle, px_active_time_ms, eSetValueWithOverwrite);
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable Secondary payload!");
+ sys_log_new_line();
+ retval = -1;
}
- return err;
+ if ((ev->ev_id != EV_PERSIST_STATE_ON_INIT) && (retval == 0))
+ {
+ satellite_change_mode(OBDH_MODE_EXPERIMENT);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_EXPERIMENT;
+ }
+
+ return retval;
}
-static int8_t activate_payload_rq(const uint8_t *args)
+static int goto_fdir_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
{
- int8_t err = 0;
- uint8_t pl = args[0];
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
+ int retval = 0;
+ int err = 0;
+ uint8_t retry_count = 5U;
- switch (pl)
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_MISSION_MANAGER_NAME, "Transitioning to FDIR Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
+
+ if (sat->obdh.data.main_payload_state != (uint8_t)PAYLOAD_NONE)
{
- case PL_ID_EDC_1:
+ do
{
- if (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_1)
- {
- (void)payload_disable(PAYLOAD_EDC_1);
- }
+ err = payload_disable((payload_t)sat->obdh.data.main_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- /* Update satellite state */
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)PAYLOAD_EDC_0;
- sat_data_buf.state.c_edc = &sat_data_buf.edc_0;
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Main payload!");
+ sys_log_new_line();
+ retval = -1;
+ }
- (void)payload_enable(PAYLOAD_EDC_0);
+ err = 0;
+ retry_count = 5U;
+ }
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
+ if (sat->obdh.data.sec_payload_state != (uint8_t)PAYLOAD_NONE)
+ {
+ do
+ {
+ err = payload_disable((payload_t)sat->obdh.data.sec_payload_state);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- break;
+ if (retry_count != 0U)
+ {
+ sat->obdh.data.sec_payload_state = (uint8_t)PAYLOAD_NONE;
}
- case PL_ID_EDC_2:
+ else
{
- if (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_0)
- {
- (void)payload_disable(PAYLOAD_EDC_0);
- }
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable Secondary payload!");
+ sys_log_new_line();
+ retval = -1;
+ }
- /* Update satellite state */
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)PAYLOAD_EDC_1;
- sat_data_buf.state.c_edc = &sat_data_buf.edc_1;
+ err = 0;
+ retry_count = 5U;
+ }
- (void)payload_enable(PAYLOAD_EDC_1);
+ do
+ {
+ err = eps_set_param(SL_EPS2_REG_BEACON_ENABLE, 0U);
+ vTaskDelay(100U);
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
+ if (retry_count == 0U)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable EPS beacon!");
+ sys_log_new_line();
+ }
- break;
- }
- #if defined (CONFIG_DEV_PAYLOAD_X_ENABLED) && defined (CONFIG_TASK_PAYLOAD_X_ENABLED) && (CONFIG_DEV_PAYLOAD_X_ENABLED == 1) && (CONFIG_TASK_PAYLOAD_X_ENABLED == 1)
- case PL_ID_PAYLOAD_X:
- {
- if (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE)
- {
- const uint32_t px_active_time_ms = (uint32_t)PAYLOAD_X_EXPERIMENT_PERIOD_MS;
- sat_data_buf.obdh.data.sec_payload_state = (uint8_t)PAYLOAD_X;
+ if ((ev->ev_id != EV_PERSIST_STATE_ON_INIT) && (retval == 0))
+ {
+ satellite_change_mode(OBDH_MODE_FDIR);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_FDIR;
+ }
- (void)payload_enable(PAYLOAD_X);
+ return retval;
+}
- /* Send notifcation to read_px task to initialize experiment */
- (void)xTaskNotify(xTaskReadPXHandle, px_active_time_ms, eSetValueWithOverwrite);
+static int goto_manual_mode(struct conops_fsm *ctx, const struct conops_event *ev,
+ const uint16_t transition_to)
+{
+ (void)transition_to;
+ sat_data_t *sat = ctx->user_data;
- if (!in_hibernation)
- {
- satellite_change_mode(OBDH_MODE_NORMAL);
- }
- }
- break;
- }
- #endif
- default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Invalid payload received");
- sys_log_new_line();
- err = -1;
- break;
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_MISSION_MANAGER_NAME, "Transitioning to Manual Mode because of event (");
+ sys_log_print_hex((uint32_t)ev->ev_id);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
+ if (ev->ev_id != EV_PERSIST_STATE_ON_INIT)
+ {
+ satellite_change_mode(OBDH_MODE_MANUAL);
+ sat->obdh.data.last_tran_ev_id = ev->ev_id;
+ ctx->state = OBDH_MODE_MANUAL;
}
- return err;
+ return 0;
}
-static int8_t deactivate_payload_rq(const uint8_t *args)
+static int32_t event_mapper(const struct conops_fsm *ctx, const struct conops_event *ev)
{
- int8_t err = 0;
- uint8_t pl = args[0];
+ sat_data_t *sat = ctx->user_data;
+ int32_t transition_to = -2;
- switch (pl)
+ switch (ev->ev_id)
{
- case PL_ID_EDC_1:
+ case EV_TC_ENTER_HIBERNATION:
{
- if (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_0)
- {
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
+ taskENTER_CRITICAL();
- (void)payload_disable(PAYLOAD_EDC_0);
+ sat->obdh.data.hibernation_on = true;
+ sys_time_t hib_duration_hours = (sys_time_t)ev->src;
+ sat_data_buf.obdh.data.hib_duration = hib_duration_hours * 60UL * 60UL;
- if ((sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE))
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
+ taskEXIT_CRITICAL();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Hibernating for ");
+ sys_log_print_uint(hib_duration_hours);
+ sys_log_print_msg(" hours...");
+ sys_log_new_line();
+
+ if (disable_ttc_tx() < 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable transmissions through TTC!");
+ sys_log_new_line();
}
+ transition_to = ctx->state;
break;
}
- case PL_ID_EDC_2:
+ case EV_TC_LEAVE_HIBERNATION:
{
- if (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_1)
- {
- sat_data_buf.obdh.data.main_payload_state = (uint8_t)PAYLOAD_NONE;
+ sat->obdh.data.hibernation_on = false;
+ sat_data_buf.obdh.data.hib_duration = 0U;
- (void)payload_disable(PAYLOAD_EDC_1);
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Leaving hibernation...");
+ sys_log_new_line();
- if ((sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE))
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
+ if (enable_ttc_tx() < 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable transmissions through TTC!");
+ sys_log_new_line();
}
+ transition_to = ctx->state;
break;
}
- #if defined (CONFIG_DEV_PAYLOAD_X_ENABLED) && defined (CONFIG_TASK_PAYLOAD_X_ENABLED) && (CONFIG_DEV_PAYLOAD_X_ENABLED == 1) && (CONFIG_TASK_PAYLOAD_X_ENABLED == 1)
- case PL_ID_PAYLOAD_X:
- {
- if (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_X)
- {
- sat_data_buf.obdh.data.sec_payload_state = (uint8_t)PAYLOAD_NONE;
-
- /* Sends notification to read_px task to stop experiment */
- (void)xTaskNotify(xTaskReadPXHandle, PAYLOAD_X_CANCEL_EXPERIMENT_FLAG, eSetValueWithOverwrite);
-
- (void)payload_disable(PAYLOAD_X);
+ case EV_HIBERNATION_TIMEOUT:
+ {
+ sat->obdh.data.hibernation_on = false;
+ sat_data_buf.obdh.data.hib_duration = 0U;
- if ((sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE))
- {
- satellite_change_mode(OBDH_MODE_STAND_BY);
- }
- }
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Hibernation timeout! Enabling transmissions...");
+ sys_log_new_line();
- break;
+ if (enable_ttc_tx() < 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable transmissions through TTC!");
+ sys_log_new_line();
}
- #endif
+
+ transition_to = ctx->state;
+ break;
+ }
default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Invalid payload received");
- sys_log_new_line();
- err = -1;
break;
+ }
+ if (transition_to == -2)
+ {
+ switch (ctx->state)
+ {
+ case OBDH_MODE_DEPLOYMENT:
+ transition_to = handle_deployment_evs(ctx, ev);
+ break;
+ case OBDH_MODE_COMMISSION:
+ transition_to = handle_commission_evs(ctx, ev);
+ break;
+ case OBDH_MODE_NORMAL:
+ transition_to = handle_nominal_evs(ctx, ev);
+ break;
+ case OBDH_MODE_STAND_BY:
+ transition_to = handle_standby_evs(ctx, ev);
+ break;
+ case OBDH_MODE_EXPERIMENT:
+ transition_to = handle_experiment_evs(ctx, ev);
+ break;
+ case OBDH_MODE_FDIR:
+ transition_to = handle_fdir_evs(ctx, ev);
+ break;
+ case OBDH_MODE_MANUAL:
+ if (EV_CHECK_CRIT_BITMASK(ev->ev_id))
+ {
+ transition_to = handle_manual_evs(ctx, ev);
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_MISSION_MANAGER_NAME, "Manual Mode is enabled! Ignoring automatic event...");
+ sys_log_new_line();
+
+ transition_to = OBDH_MODE_MANUAL;
+ }
+ break;
+ default:
+ transition_to = -1;
+ break;
+ }
}
- return err;
+ return transition_to;
}
-static int enable_ttc_tx(void)
+static conops_transition_handler_t mode_transition_table[MISSION_OPERATION_MODES][MISSION_OPERATION_MODES] = { // cppcheck-suppress misra-c2012-8.9
+ /* Deployment (DM) | Commission (CM) | Normal (NM) | Stand-by (SBM) | Experiment (EXM) | FDIR (FDM) | Manual (MNM) */
+/* DM */ {NULL, goto_commission_mode, goto_nominal_mode, goto_standby_mode, goto_experiment_mode, goto_fdir_mode, goto_manual_mode},
+/* CM */ {NULL, goto_commission_mode, goto_nominal_mode, goto_standby_mode, goto_experiment_mode, goto_fdir_mode, goto_manual_mode},
+/* NM */ {NULL, goto_commission_mode, NULL, goto_standby_mode, goto_experiment_mode, goto_fdir_mode, goto_manual_mode},
+/* SBM */ {NULL, goto_commission_mode, goto_nominal_mode, NULL, goto_experiment_mode, goto_fdir_mode, goto_manual_mode},
+/* EXM */ {NULL, goto_commission_mode, goto_nominal_mode, goto_standby_mode, NULL, goto_fdir_mode, goto_manual_mode},
+/* FDM */ {NULL, goto_commission_mode, goto_nominal_mode, goto_standby_mode, NULL, NULL, goto_manual_mode},
+/* MNM */ {NULL, goto_commission_mode, goto_nominal_mode, goto_standby_mode, goto_experiment_mode, goto_fdir_mode, NULL},
+};
+
+#endif
+
+static int satellite_persist_op_mode(struct conops_fsm *ctx)
{
- int err = 0;
+ int retval = 0;
+
+ const conops_transition_handler_t handlers[] = {NULL, NULL, goto_nominal_mode, goto_standby_mode, goto_experiment_mode, goto_fdir_mode, goto_manual_mode};
- if (ttc_leave_hibernation(TTC_0) != 0)
+ conops_transition_handler_t handler = goto_fdir_mode;
+
+ if (ctx->state < MISSION_OPERATION_MODES)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable TTC 0 TX");
- sys_log_new_line();
- err--;
+ handler = handlers[ctx->state];
}
- if (ttc_leave_hibernation(TTC_1) != 0)
+ if (handler != NULL)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to enable TTC 1 TX");
- sys_log_new_line();
- err--;
+ const struct conops_event fsm_init = {
+ .src = 0U,
+ .ev_id = EV_PERSIST_STATE_ON_INIT,
+ .ev_name = "INIT",
+ .callback = NULL,
+ };
+
+ retval = (handler)(ctx, &fsm_init, ctx->state);
}
- return err;
+ return retval;
}
-static int disable_ttc_tx(void)
+QueueHandle_t event_queue;
+
+TaskHandle_t xTaskMissionManagerHandle;
+
+void vTaskMissionManager(void *p)
{
+ (void)p;
+
+ struct conops_fsm op_mode_fsm = {0};
+ struct conops_event ev = {0};
int err = 0;
- if (ttc_enter_hibernation(TTC_0) != 0)
+ (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_MISSION_MANAGER_STARTUP_TIMEOUT_MS));
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Initializing operation mode state machine in mode (");
+ sys_log_print_hex((uint32_t)sat_data_buf.obdh.data.mode);
+ sys_log_print_msg(")...");
+ sys_log_new_line();
+
+ err = conops_fsm_init(&op_mode_fsm, mode_transition_table, MISSION_OPERATION_MODES, EV_TC_LEAVE_HIBERNATION, sat_data_buf.obdh.data.mode, satellite_persist_op_mode);
+
+ if (err < 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable TTC 0 TX");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to initialize operation mode state machine! Mode was (");
+ sys_log_print_hex((uint32_t)sat_data_buf.obdh.data.mode);
+ sys_log_print_msg(")");
sys_log_new_line();
- err--;
+
+ if (err == -ERRNO_CONOPS_INVALID_STATE)
+ {
+ sat_data_buf.obdh.data.mode = OBDH_MODE_FDIR;
+
+ /* Reinitialize FSM in FDIR, since something corrupted the operation mode stored in FRAM */
+ (void)conops_fsm_init(&op_mode_fsm, mode_transition_table, MISSION_OPERATION_MODES, EV_TC_LEAVE_HIBERNATION, sat_data_buf.obdh.data.mode, satellite_persist_op_mode);
+ }
+ }
+
+ (void)conops_register_mapper(&op_mode_fsm, event_mapper);
+ (void)conops_register_fsm_user_data(&op_mode_fsm, &sat_data_buf);
+
+ while (1)
+ {
+ if (xQueueReceive(event_queue, &ev, pdMS_TO_TICKS_64(TASK_MISSION_MANAGER_EV_NOTIFICATION_TIMEOUT)) == pdPASS)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_MISSION_MANAGER_NAME, "Received new event (");
+ sys_log_print_hex((uint32_t)ev.ev_id);
+ sys_log_print_msg(")!");
+ sys_log_new_line();
+
+ err = conops_fsm_process_event(&op_mode_fsm, &ev);
+
+ if (err == 0)
+ {
+ if (EV_CHECK_CRIT_BITMASK(ev.ev_id))
+ {
+ /* Notify TC executing task that the event was processed sucessfully */
+ (void)xEventGroupSetBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT);
+ }
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to process event!");
+ sys_log_new_line();
+ }
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_MISSION_MANAGER_NAME, "Notification waiting timed out!");
+ sys_log_new_line();
+ }
}
+}
- if (ttc_enter_hibernation(TTC_1) != 0)
+int8_t notify_event_to_mission_manager(const struct conops_event *ev)
+{
+ int8_t err = 0;
+
+ if (xQueueSendToBack(event_queue, ev, pdMS_TO_TICKS(10U)) != pdPASS)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_MISSION_MANAGER_NAME, "Failed to disable TTC 1 TX");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, "Event Queue", "Failed to enqueue event");
sys_log_new_line();
- err--;
+
+ err = -1;
}
return err;
}
+void satellite_change_mode(const uint8_t mode)
+{
+ /* This ensures the mode change is done atomically */
+ taskENTER_CRITICAL();
+ sat_data_buf.obdh.data.mode = mode;
+ sat_data_buf.obdh.data.ts_last_mode_change = system_get_time();
+ taskEXIT_CRITICAL();
+}
+
/** \} End of mission_man group */
diff --git a/firmware/app/tasks/mission_manager.h b/firmware/app/tasks/mission_manager.h
index a21ecc07..31af61cb 100644
--- a/firmware/app/tasks/mission_manager.h
+++ b/firmware/app/tasks/mission_manager.h
@@ -44,36 +44,63 @@
#include
#include
+#include
#include
+#include
#define TASK_MISSION_MANAGER_NAME "Mission Manager" /**< Task name. */
-#define TASK_MISSION_MANAGER_STACK_SIZE 512U /**< Stack size in bytes. */
+#define TASK_MISSION_MANAGER_STACK_SIZE 1024U /**< Stack size in bytes. */
#define TASK_MISSION_MANAGER_PRIORITY 4U /**< Task priority. */
#define TASK_MISSION_MANAGER_EV_NOTIFICATION_TIMEOUT (3600000UL) /**< Task maximum block time waiting for event notifications */
#define TASK_MISSION_MANAGER_STARTUP_TIMEOUT_MS (5000UL) /**< Task startup event group notification timeout */
-#define PAYLOAD_X_EXPERIMENT_PERIOD_MS (600000UL) /**< Payload X default experiment time in milliseconds. */
-#define PAYLOAD_X_CANCEL_EXPERIMENT_FLAG (1UL << 31UL) /**< Flag used as a notification to cancel running experiment */
-
-#define HOUSEKEEPING_WAKE_UP_RQ 0xAE /**< Used to check which task sent a wake up request */
-
-#define EV_NOTIFY_IN_BRAZIL 0 /**< In Brazil notification flag */
-#define EV_NOTIFY_OUT_OF_BRAZIL 1 /**< Outside Brazil notification flag */
-#define EV_NOTIFY_PX_FINISHED 2 /**< Payload X experiment period finished flag */
-#define EV_NOTIFY_MODE_CHANGE_RQ 3 /**< A request to change operation mode was made through TC */
-#define EV_NOTIFY_ACTIVATE_PAYLOAD_RQ 4 /**< A request to activate payload was made through TC */
-#define EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ 5 /**< A request to deactivate payload was made through TC */
-
-
-/**
- * \brief Event type. Used to pass events to the Mission Manager Task
- * from other tasks for processing.
- */
-typedef struct
-{
- uint8_t event; /**< Event to process. [Ex: EV_NOTIFY_IN_BRAZIL] */
- uint8_t args[3]; /**< Arguments used to describe event properties. */
-} event_t;
+/* Mission Specific Macros */
+#if defined (CONFIG_MISSION_GOLDS_UFSC) && (CONFIG_MISSION_GOLDS_UFSC == 1)
+ #define MISSION_OPERATION_MODES 7U
+
+ /* Mission Operation modes */
+ #define OBDH_MODE_DEPLOYMENT 0x00U
+ #define OBDH_MODE_COMMISSION 0x01U
+ #define OBDH_MODE_NORMAL 0x02U
+ #define OBDH_MODE_STAND_BY 0x03U
+ #define OBDH_MODE_EXPERIMENT 0x04U
+ #define OBDH_MODE_FDIR 0x05U
+ #define OBDH_MODE_MANUAL 0x06U
+
+ /* Mission Event Masking */
+ #define EV_ADD_CRIT_BITMASK(ev) ((ev) | 0x8000U)
+ #define EV_CHECK_CRIT_BITMASK(ev) (((ev) & 0x8000U) != 0U)
+
+ /* Mission Events */
+ #define EV_PERSIST_STATE_ON_INIT (0x0000U) /**< Used for the state machine initialization */
+ #define EV_IN_BRAZIL (0x0001U) /**< In Brazil notification flag */
+ #define EV_OUT_OF_BRAZIL (0x0002U) /**< Outside Brazil notification flag */
+ #define EV_PX_FINISHED (0x0003U) /**< Payload X experiment period finished flag */
+ #define EV_HIBERNATION_TIMEOUT (0x0004U) /**< Notifies that hibernation time has ended */
+ #define EV_BATTERY_LEVEL_CRITICAL (0x0005U) /**< Satellite battery is on critical levels */
+ #define EV_FDIR_RESOLVED (0x0006U) /**< FDIR condition was resolved */
+ #define EV_COMISSION_TIMEOUT (0x0007U) /**< Commission Mode timedout */
+ #define EV_DEPLOYMENT_COMPLETE (0x0008U) /**< Antenna Deployment complete */
+ #define EV_TC_GOTO_MANUAL_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_MANUAL))
+ #define EV_TC_GOTO_STAND_BY_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_STAND_BY))
+ #define EV_TC_GOTO_NORMAL_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_NORMAL))
+ #define EV_TC_GOTO_FDIR_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_FDIR))
+ #define EV_TC_GOTO_DEPLOYMENT_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_DEPLOYMENT))
+ #define EV_TC_GOTO_COMMISSION_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_COMMISSION))
+ #define EV_TC_GOTO_EXPERIMENT_MODE (EV_ADD_CRIT_BITMASK(OBDH_MODE_EXPERIMENT))
+ #define EV_TC_ENABLE_PAYLOAD (EV_ADD_CRIT_BITMASK(0x0010U)) /**< Enables payload specified on 'src' field from event */
+ #define EV_TC_DISABLE_PAYLOAD (EV_ADD_CRIT_BITMASK(0x0020U)) /**< Disables payload specified on 'src' field from event */
+ #define EV_TC_ENTER_HIBERNATION (EV_ADD_CRIT_BITMASK(0x0030U)) /**< Enter hibernation for a number of hours specified on 'src' field from event */
+ #define EV_TC_LEAVE_HIBERNATION (EV_ADD_CRIT_BITMASK(0x0040U))
+
+ /* Payload X defines */
+ #define PAYLOAD_X_EXPERIMENT_PERIOD_MS (600000UL) /**< Payload X default experiment time in milliseconds. */
+ #define PAYLOAD_X_CANCEL_EXPERIMENT_FLAG (1UL << 31UL) /**< Flag used as a notification to cancel running experiment */
+
+ /* Commission Mode defines */
+ #define COMMISSION_MODE_TIMEOUT_SEC (1209600UL) /**< Max time allowed on commission (Can be overwritten through system parameters) */
+
+#endif
/**
* \brief Changes satellite's operation mode.
@@ -105,20 +132,10 @@ void vTaskMissionManager(void* p);
* \brief Sends a event notification to the Mission Manager Task.
*
* \param[in] ev is the event to send to the Mission Manager Task.
- * A example of a event would be `{ .event = EV_NOTIFY_IN_BRAZIL, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U }`.
- *
- * \return The status/error code.
- */
-int8_t notify_event_to_mission_manager(const event_t *ev);
-
-/**
- * \brief Overrides current operation mode.
- *
- * \param[in] mode is the operation mode to enter.
*
* \return The status/error code.
*/
-int8_t override_op_mode(const uint8_t mode);
+int8_t notify_event_to_mission_manager(const struct conops_event *ev);
#endif
diff --git a/firmware/app/tasks/mode_check.c b/firmware/app/tasks/mode_check.c
index cf84d912..c0003741 100644
--- a/firmware/app/tasks/mode_check.c
+++ b/firmware/app/tasks/mode_check.c
@@ -45,10 +45,13 @@
#include
#include
#include
+#include
+#include
#include "mode_check.h"
#include "mission_manager.h"
#include "process_tc.h"
+#include "pos_det.h"
TaskHandle_t xTaskHealthCheckModeHandle;
@@ -67,14 +70,19 @@ void vTaskHealthCheckMode(void *p)
while(1)
{
- bool test_result;
-
if (xTaskNotifyWait(0UL, UINT32_MAX, NULL, portMAX_DELAY) == pdTRUE)
{
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Starting Operation Mode Health Check...");
sys_log_new_line();
-
- const event_t in_brazil_ev = { .event = EV_NOTIFY_IN_BRAZIL, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+
+ (void)mem_mng_load_obdh_data_from_default_values(&sat_data_buf.obdh);
+
+ const struct conops_event in_brazil_ev = {
+ .src = 0U,
+ .ev_name = "InBrazil",
+ .callback = NULL,
+ .ev_id = EV_IN_BRAZIL,
+ };
if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
{
@@ -84,14 +92,25 @@ void vTaskHealthCheckMode(void *p)
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_0) || (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_1));
+ bool payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_DEPLOYMENT) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ bool hibernation_test = (sat_data_buf.obdh.data.hibernation_on == true);
+ bool beacon_off = (sat_data_buf.obdh.data.general_telemetry_on == false);
- sys_log_print_test_result(test_result, "In Brazil Notify Test");
+ sys_log_print_test_result(payload_test, "DM(InBrazil) - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(hibernation_test, "DM(InBrazil) - Hibernation test");
+ sys_log_new_line();
+ sys_log_print_test_result(beacon_off, "DM(InBrazil) - Beacon test");
sys_log_new_line();
- const event_t out_of_brazil = { .event = EV_NOTIFY_OUT_OF_BRAZIL, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event out_brazil_ev = {
+ .src = 0U,
+ .ev_name = "OutBrazil",
+ .callback = NULL,
+ .ev_id = EV_OUT_OF_BRAZIL,
+ };
- if (notify_event_to_mission_manager(&out_of_brazil) != 0)
+ if (notify_event_to_mission_manager(&out_brazil_ev) != 0)
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `out of brazil` event");
sys_log_new_line();
@@ -99,77 +118,138 @@ void vTaskHealthCheckMode(void *p)
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_X) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_DEPLOYMENT) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ hibernation_test = (sat_data_buf.obdh.data.hibernation_on == true);
+ beacon_off = (sat_data_buf.obdh.data.general_telemetry_on == false);
- sys_log_print_test_result(test_result, "Out of Brazil Notify Test");
+ sys_log_print_test_result(payload_test, "DM(OutBrazil) - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(hibernation_test, "DM(OutBrazil) - Hibernation test");
+ sys_log_new_line();
+ sys_log_print_test_result(beacon_off, "DM(OutBrazil) - Beacon test");
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Commission Mode transition...");
sys_log_new_line();
- const event_t px_finished = { .event = EV_NOTIFY_PX_FINISHED, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event commission = {
+ .src = 0U,
+ .ev_name = "COMM",
+ .callback = NULL,
+ .ev_id = EV_DEPLOYMENT_COMPLETE,
+ };
- if (notify_event_to_mission_manager(&px_finished) != 0)
+ if (notify_event_to_mission_manager(&commission) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `px finished` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `deployment complete` event");
sys_log_new_line();
}
- vTaskDelay(pdMS_TO_TICKS(150));
+ vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_COMMISSION) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ hibernation_test = (sat_data_buf.obdh.data.hibernation_on == false) && (sat_data_buf.obdh.data.hib_duration == 0U);
+ bool beacon_on = (sat_data_buf.obdh.data.general_telemetry_on == true);
- sys_log_print_test_result(test_result, "Payload X finished Notify Test");
+ sys_log_print_test_result(payload_test, "CM - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(hibernation_test, "CM - Hibernation test");
+ sys_log_new_line();
+ sys_log_print_test_result(beacon_on, "CM - Beacon test");
sys_log_new_line();
- (void)notify_event_to_mission_manager(&in_brazil_ev);
- taskYIELD();
- (void)notify_event_to_mission_manager(&out_of_brazil);
- taskYIELD();
- (void)notify_event_to_mission_manager(&px_finished);
+ if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `in brazil` event");
+ sys_log_new_line();
+ }
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_COMMISSION) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
- sys_log_print_test_result(test_result, "Position relative Notifications Test");
+ sys_log_print_test_result(payload_test, "CM(InBrazil) - Payload State test");
sys_log_new_line();
- const event_t enter_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_MODE_HIBERNATION, .args[1] = 0x11U, .args[2] = 0x11U };
- if (notify_event_to_mission_manager(&enter_hib) != 0)
+ if (notify_event_to_mission_manager(&out_brazil_ev) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `enter hibernation` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `out of brazil` event");
sys_log_new_line();
}
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- uint32_t hib_time = ((uint32_t)0x1111UL * (uint32_t)60UL * (uint32_t)60UL);
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_HIBERNATION) && (sat_data_buf.obdh.data.hib_duration == hib_time);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_COMMISSION) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
- sys_log_print_test_result(test_result, "Enter hibernation Test");
+ sys_log_print_test_result(payload_test, "CM(OutBrazil) - Payload State test");
sys_log_new_line();
- const event_t leave_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_WAKE_UP, .args[1] = 0U, .args[2] = 0U };
- if (notify_event_to_mission_manager(&leave_hib) != 0)
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Normal Mode transition...");
+ sys_log_new_line();
+
+ const struct conops_event normal = {
+ .src = 0U,
+ .ev_name = "NM",
+ .callback = NULL,
+ .ev_id = EV_TC_GOTO_NORMAL_MODE,
+ };
+
+ if (notify_event_to_mission_manager(&normal) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `leave hibernation` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `goto normal mode` event");
sys_log_new_line();
}
- vTaskDelay(pdMS_TO_TICKS(2000U));
+ vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PL_ID_EDC_1) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ bool edc_pointer_test = (sat_data_buf.state.c_edc == &sat_data_buf.edc_0);
- sys_log_print_test_result(test_result, "Leave hibernation Test");
+ sys_log_print_test_result(payload_test, "NM(GOTO_NORMAL_MODE) - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(edc_pointer_test, "NM(GOTO_NORMAL_MODE) - EDC pointer test");
sys_log_new_line();
- if (notify_event_to_mission_manager(&enter_hib) != 0)
+ if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `enter hibernation` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `in_brazil` event");
+ sys_log_new_line();
+ }
+
+ vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
+
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PL_ID_EDC_1) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ edc_pointer_test = (sat_data_buf.state.c_edc == &sat_data_buf.edc_0);
+
+ sys_log_print_test_result(payload_test, "NM(InBRAZIL) - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(edc_pointer_test, "NM(InBRAZIL) - EDC pointer test");
+ sys_log_new_line();
+
+ sat_data_buf.obdh.data.manual_experiments = true;
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Stand-by Mode transition...");
+ sys_log_new_line();
+
+ if (notify_event_to_mission_manager(&out_brazil_ev) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `out of brazil` event");
sys_log_new_line();
}
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- taskYIELD();
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+
+ sys_log_print_test_result(payload_test, "NM(OutBRAZIL) - Payload State test");
+ sys_log_new_line();
+ sys_log_print_test_result(edc_pointer_test, "NM(OutBRAZIL) - EDC pointer test");
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Normal Mode transition and EDC switch...");
+ sys_log_new_line();
+
+ sat_data_buf.obdh.data.main_edc = PL_ID_EDC_2;
if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
{
@@ -179,14 +259,18 @@ void vTaskHealthCheckMode(void *p)
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_HIBERNATION);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PL_ID_EDC_2) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ edc_pointer_test = (sat_data_buf.state.c_edc == &sat_data_buf.edc_1);
- sys_log_print_test_result(test_result, "Hibernation mode persistency Test [EDC]");
+ sys_log_print_test_result(payload_test, "SBM(InBRAZIL) - Payload State test");
sys_log_new_line();
- taskYIELD();
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Experiment Mode transition...");
+ sys_log_new_line();
- if (notify_event_to_mission_manager(&out_of_brazil) != 0)
+ sat_data_buf.obdh.data.manual_experiments = false;
+
+ if (notify_event_to_mission_manager(&out_brazil_ev) != 0)
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `out of brazil` event");
sys_log_new_line();
@@ -194,56 +278,127 @@ void vTaskHealthCheckMode(void *p)
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_HIBERNATION);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_EXPERIMENT) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_X));
+
+ sys_log_print_test_result(payload_test, "NM(OutBRAZIL) - Payload State test");
+ sys_log_new_line();
- sys_log_print_test_result(test_result, "Hibernation mode persistency Test [PX]");
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing Stand-by Mode transition from Experiment...");
sys_log_new_line();
- const event_t mode_normal = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_MODE_NORMAL, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event exp_timeout = {
+ .src = 10U,
+ .ev_id = EV_PX_FINISHED,
+ .ev_name = "EXP_TIME",
+ .callback = NULL,
+ };
- if (notify_event_to_mission_manager(&mode_normal) != 0)
+ if (notify_event_to_mission_manager(&exp_timeout) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `mode change to normal` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `Px finished` event");
sys_log_new_line();
}
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_0) || (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_EDC_1));
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+
+ sys_log_print_test_result(payload_test, "EXP(PX-Finished) - Payload State test");
+ sys_log_new_line();
- sys_log_print_test_result(test_result, "TC change mode to NORMAL Test");
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing FDIR Mode transition...");
sys_log_new_line();
- const event_t mode_stand_by = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_MODE_STAND_BY, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event fdir = {
+ .src = 10U,
+ .ev_id = EV_BATTERY_LEVEL_CRITICAL,
+ .ev_name = "BATT_LVL",
+ .callback = NULL,
+ };
- if (notify_event_to_mission_manager(&mode_stand_by) != 0)
+ if (notify_event_to_mission_manager(&fdir) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `mode change to stand by` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `battery level` event");
sys_log_new_line();
}
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- test_result = (sat_data_buf.obdh.data.mode == (uint8_t)OBDH_MODE_STAND_BY) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE);
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_FDIR) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
- sys_log_print_test_result(test_result, "TC change mode to STAND_BY Test");
+ sys_log_print_test_result(payload_test, "FDIR(BATT_LVL) - Payload State test");
sys_log_new_line();
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Testing FDIR exit transition...");
+ sys_log_new_line();
+
+ const struct conops_event fdir_exit = {
+ .src = 10U,
+ .ev_id = EV_FDIR_RESOLVED,
+ .ev_name = "FDIR_RES",
+ .callback = NULL,
+ };
+
+ if (notify_event_to_mission_manager(&fdir_exit) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `fdir res` event");
+ sys_log_new_line();
+ }
+
vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS));
- sat_data_buf.obdh.data.manual_mode_on = true;
+ if (is_satellite_in_brazil((float) sat_data_buf.obdh.data.position.latitude, (float)sat_data_buf.obdh.data.position.longitude))
+ {
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_NORMAL) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PL_ID_EDC_2) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ }
+ else
+ {
+ payload_test = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && ((sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE));
+ }
+
+ sys_log_print_test_result(payload_test, "FDIR(BATT_LVL_RECOVERY) - Payload State test");
+ sys_log_new_line();
- if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
+ const struct conops_event enter_hib = {
+ .src = 10U,
+ .ev_id = EV_TC_ENTER_HIBERNATION,
+ .ev_name = "HIB",
+ .callback = NULL,
+ };
+
+ if (notify_event_to_mission_manager(&enter_hib) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `in brazil (manual)` event");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `enter hibernation` event");
sys_log_new_line();
}
- test_result = (sat_data_buf.obdh.data.mode == OBDH_MODE_STAND_BY) && (sat_data_buf.obdh.data.main_payload_state == (uint8_t)PAYLOAD_NONE) && (sat_data_buf.obdh.data.sec_payload_state == (uint8_t)PAYLOAD_NONE);
+ vTaskDelay(pdMS_TO_TICKS(200UL));
- sys_log_print_test_result(test_result, "Manual mode check");
+ const uint32_t hib_time = ((uint32_t)10UL * (uint32_t)60UL * (uint32_t)60UL);
+ bool test_result = (sat_data_buf.obdh.data.hibernation_on == true) && (sat_data_buf.obdh.data.hib_duration == hib_time);
+
+ sys_log_print_test_result(test_result, "Enter hibernation Test");
sys_log_new_line();
+ const struct conops_event leave_hib = {
+ .src = 0U,
+ .ev_id = EV_TC_LEAVE_HIBERNATION,
+ .ev_name = "LHIB",
+ .callback = NULL,
+ };
+
+ if (notify_event_to_mission_manager(&leave_hib) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_HEALTH_CHECK_MODE_NAME, "Failed to enqueue `leave hibernation` event");
+ sys_log_new_line();
+ }
+
+ vTaskDelay(pdMS_TO_TICKS(200U));
+
+ test_result = (sat_data_buf.obdh.data.hibernation_on == false) && (sat_data_buf.obdh.data.hib_duration == 0U);
+
+ sys_log_print_test_result(test_result, "Leave hibernation Test");
+ sys_log_new_line();
}
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_HEALTH_CHECK_MODE_NAME, "Operation Mode Health Check Finished!!!");
diff --git a/firmware/app/tasks/pos_det.c b/firmware/app/tasks/pos_det.c
index 21503b91..a9f5831b 100644
--- a/firmware/app/tasks/pos_det.c
+++ b/firmware/app/tasks/pos_det.c
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -58,9 +59,6 @@ void vTaskPosDet(void *p)
static struct predict_sgp4 sgp4_model;
static struct predict_sdp4 sdp4_model;
- /* Flag used to control notification sending */
- bool sat_is_inside_brazil = false;
-
/* Pointer used to see if TLE parsing was sucessfull */
predict_orbital_elements_t *sat = NULL;
@@ -109,13 +107,16 @@ void vTaskPosDet(void *p)
sys_log_print_msg(" km");
sys_log_new_line();
- bool current_position = is_satellite_in_brazil(sat_data_buf.obdh.data.position.latitude, sat_data_buf.obdh.data.position.longitude);
+ bool in_brazil = is_satellite_in_brazil(lat, lon);
- if (current_position && !sat_is_inside_brazil)
+ if (in_brazil)
{
- sat_is_inside_brazil = true;
-
- const event_t in_brazil_ev = { .event = EV_NOTIFY_IN_BRAZIL, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event in_brazil_ev = {
+ .ev_id = EV_IN_BRAZIL,
+ .src = 0U,
+ .ev_name = "InBrazil",
+ .callback = NULL,
+ };
if (notify_event_to_mission_manager(&in_brazil_ev) != 0)
{
@@ -123,12 +124,14 @@ void vTaskPosDet(void *p)
sys_log_new_line();
}
}
-
- if (!current_position && sat_is_inside_brazil)
+ else
{
- sat_is_inside_brazil = false;
-
- const event_t out_of_brazil_ev = { .event = EV_NOTIFY_OUT_OF_BRAZIL, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event out_of_brazil_ev = {
+ .ev_id = EV_OUT_OF_BRAZIL,
+ .src = 0U,
+ .ev_name = "OutBrazil",
+ .callback = NULL,
+ };
if (notify_event_to_mission_manager(&out_of_brazil_ev) != 0)
{
diff --git a/firmware/app/tasks/pos_det.h b/firmware/app/tasks/pos_det.h
index 86afbd0a..8c079450 100644
--- a/firmware/app/tasks/pos_det.h
+++ b/firmware/app/tasks/pos_det.h
@@ -51,10 +51,10 @@
#define TASK_POS_DET_PERIOD_MS 60000 /**< Task period in milliseconds. */
#define TASK_POS_DET_INIT_TIMEOUT_MS 5000 /**< Wait time to initialize the task in milliseconds. */
-#define POS_BRAZIL_LIM_N (6L) /**< Brazil territory North limit (Rounded up) */
-#define POS_BRAZIL_LIM_S (-34L) /**< Brazil territory South limit (Rounded up) */
-#define POS_BRAZIL_LIM_E (-35L) /**< Brazil territory East limit (Rounded up) */
-#define POS_BRAZIL_LIM_W (-74L) /**< Brazil territory West limit (Rounded up) */
+#define POS_BRAZIL_LIM_N (6.0f) /**< Brazil territory North limit (Rounded up) */
+#define POS_BRAZIL_LIM_S (-34.0f) /**< Brazil territory South limit (Rounded up) */
+#define POS_BRAZIL_LIM_E (-35.0f) /**< Brazil territory East limit (Rounded up) */
+#define POS_BRAZIL_LIM_W (-74.0f) /**< Brazil territory West limit (Rounded up) */
/**
* \brief Position determination task handle.
@@ -64,13 +64,13 @@ extern xTaskHandle xTaskPosDetHandle;
/**
* \brief Checks if the satellite is orbiting over Brazil, based on the last available position determined.
*
- * \param[in] latitude is the latitude of the satellite as a int16_t.
+ * \param[in] latitude is the latitude of the satellite.
*
- * \param[in] longitude is the longitude of the satellite as a int16_t.
+ * \param[in] longitude is the longitude of the satellite.
*
* \return True if the satellite is over Brazil, false if it is not.
*/
-static inline bool is_satellite_in_brazil(int16_t latitude, int16_t longitude)
+static inline bool is_satellite_in_brazil(float latitude, float longitude)
{
return ((latitude >= POS_BRAZIL_LIM_S) && (latitude <= POS_BRAZIL_LIM_N) && (longitude >= POS_BRAZIL_LIM_W) && (longitude <= POS_BRAZIL_LIM_E));
}
diff --git a/firmware/app/tasks/process_tc.c b/firmware/app/tasks/process_tc.c
index 07e52f6d..f93e78cd 100644
--- a/firmware/app/tasks/process_tc.c
+++ b/firmware/app/tasks/process_tc.c
@@ -39,6 +39,7 @@
#include
#include
+#include
#include
#include
@@ -54,6 +55,7 @@
#include
+#include "sched_tc.h"
#include "process_tc.h"
#include "mission_manager.h"
#include "pos_det.h"
@@ -81,9 +83,12 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
*
* \param[in] pkt is the received packet.
*
+ * \param[in] error_code is the status/error_code of the action performed
+ * through telecommand request.
+ *
* \return The status/error code.
*/
-static int8_t send_tc_feedback(uint8_t *pkt);
+static int8_t send_tc_feedback(uint8_t *pkt, int16_t error_code);
/**
* \brief Ping request telecommand.
@@ -94,7 +99,7 @@ static int8_t send_tc_feedback(uint8_t *pkt);
*
* \return None.
*/
-static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Data request telecommand.
@@ -103,9 +108,14 @@ static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Broadcast message telecommand.
@@ -116,7 +126,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len);
*
* \return None.
*/
-static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Enter hibernation telecommand.
@@ -125,9 +135,14 @@ static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Leave hibernation telecommand.
@@ -136,9 +151,14 @@ static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Activate module telecommand.
@@ -147,9 +167,14 @@ static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Deactivate module telecommand.
@@ -158,9 +183,14 @@ static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Activate payload telecommand.
@@ -169,9 +199,14 @@ static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Deactivate payload telecommand.
@@ -180,9 +215,14 @@ static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Erase memory telecommand.
@@ -191,9 +231,14 @@ static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Force reset telecommand.
@@ -202,20 +247,30 @@ static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_force_reset(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_force_reset(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
- * \brief Get payload data telecommand.
+ * \brief Get subsystem table telecommand.
*
* \param[in] pkt is the packet to process.
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_get_payload_data(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_get_subsystem_table(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Set parameter telecommand.
@@ -224,9 +279,14 @@ static void process_tc_get_payload_data(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Get parameter telecommand.
@@ -235,9 +295,14 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Update TLE telecommand.
@@ -246,9 +311,14 @@ static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Transmit packet telecommand.
@@ -257,9 +327,30 @@ static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len);
*
* \param[in] pkt_len is the number of bytes of the given packet.
*
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
+ * \return None.
+ */
+static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
+
+/**
+ * \brief Schedule TC telecommand.
+ *
+ * \param[in] pkt is the packet to process.
+ *
+ * \param[in] pkt_len is the number of bytes of the given packet.
+ *
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
* \return None.
*/
-static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len);
+static void process_tc_schedule(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled);
/**
* \brief Checks if a given HMAC is valid or not.
@@ -280,152 +371,201 @@ static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len);
*/
static bool process_tc_validate_hmac(uint8_t *msg, uint16_t msg_len, uint8_t *msg_hash, uint16_t msg_hash_len, uint8_t *key, uint16_t key_len);
-void vTaskProcessTC(void *p)
+int execute_tc(uint8_t *pkt, uint8_t pkt_len, bool is_scheduled)
{
- (void)p;
-
- /* Wait startup task to finish */
- (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_INIT_TIMEOUT_MS));
+ int err = 0;
- /* Delay before the first cycle */
- vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_INITIAL_DELAY_MS));
-
- while(1)
+ switch(pkt[0])
{
- TickType_t last_cycle = xTaskGetTickCount();
+ case PKT_ID_UPLINK_PING_REQ:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Ping TC received!");
+ sys_log_new_line();
- int pkts = ttc_avail(TTC_1);
+ process_tc_ping_request(pkt, pkt_len, is_scheduled);
- if (pkts > 0)
- {
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "New ");
- sys_log_print_uint((unsigned int)pkts);
- sys_log_print_msg(" packet(s) available!");
+ break;
+ case PKT_ID_UPLINK_DATA_REQ:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Data request TC received!");
sys_log_new_line();
- uint8_t pkt[300] = {0};
- uint16_t pkt_len = 0;
+ process_tc_data_request(pkt, pkt_len, is_scheduled);
- if (ttc_recv(TTC_1, pkt, &pkt_len) == 0)
+ break;
+ case PKT_ID_UPLINK_BROADCAST_MSG:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Broadcast message TC received!");
+ sys_log_new_line();
+
+ if (!is_scheduled)
{
- switch(pkt[0])
- {
- case PKT_ID_UPLINK_PING_REQ:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Ping TC received!");
- sys_log_new_line();
+ process_tc_broadcast_message(pkt, pkt_len, is_scheduled);
+ }
+ else
+ {
+ err = -1;
+ }
- process_tc_ping_request(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_ENTER_HIBERNATION:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Enter Hibernation\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_DATA_REQ:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Data request TC received!");
- sys_log_new_line();
+ process_tc_enter_hibernation(pkt, pkt_len, is_scheduled);
- process_tc_data_request(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_LEAVE_HIBERNATION:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Leave Hibernation\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_BROADCAST_MSG:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Broadcast message TC received!");
- sys_log_new_line();
+ process_tc_leave_hibernation(pkt, pkt_len, is_scheduled);
- process_tc_broadcast_message(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_ACTIVATE_MODULE:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Activate Module\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_ENTER_HIBERNATION:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Enter Hibernation\"...");
- sys_log_new_line();
+ process_tc_activate_module(pkt, pkt_len, is_scheduled);
- process_tc_enter_hibernation(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_DEACTIVATE_MODULE:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Deactivate Module\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_LEAVE_HIBERNATION:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Leave Hibernation\"...");
- sys_log_new_line();
+ process_tc_deactivate_module(pkt, pkt_len, is_scheduled);
- process_tc_leave_hibernation(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_ACTIVATE_PAYLOAD:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Activate Payload\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_ACTIVATE_MODULE:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Activate Module\"...");
- sys_log_new_line();
+ process_tc_activate_payload(pkt, pkt_len, is_scheduled);
- process_tc_activate_module(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_DEACTIVATE_PAYLOAD:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Deactivate Payload\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_DEACTIVATE_MODULE:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Deactivate Module\"...");
- sys_log_new_line();
+ process_tc_deactivate_payload(pkt, pkt_len, is_scheduled);
- process_tc_deactivate_module(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_ERASE_MEMORY:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Erase Memory\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_ACTIVATE_PAYLOAD:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Activate Payload\"...");
- sys_log_new_line();
+ process_tc_erase_memory(pkt, pkt_len, is_scheduled);
- process_tc_activate_payload(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_FORCE_RESET:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Force Reset\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_DEACTIVATE_PAYLOAD:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Deactivate Payload\"...");
- sys_log_new_line();
+ process_tc_force_reset(pkt, pkt_len, is_scheduled);
- process_tc_deactivate_payload(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_GET_SUBSYSTEM_TABLE:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Get Subsystem Table\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_ERASE_MEMORY:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Erase Memory\"...");
- sys_log_new_line();
+ process_tc_get_subsystem_table(pkt, pkt_len, is_scheduled);
+ break;
+ case PKT_ID_UPLINK_SET_PARAM:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Set Parameter\"...");
+ sys_log_new_line();
- process_tc_erase_memory(pkt, pkt_len);
+ process_tc_set_parameter(pkt, pkt_len, is_scheduled);
- break;
- case PKT_ID_UPLINK_FORCE_RESET:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Force Reset\"...");
- sys_log_new_line();
+ break;
+ case PKT_ID_UPLINK_GET_PARAM:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Get Parameter\"...");
+ sys_log_new_line();
- process_tc_force_reset(pkt, pkt_len);
+ process_tc_get_parameter(pkt, pkt_len, is_scheduled);
- break;
- case PKT_ID_UPLINK_GET_PAYLOAD_DATA:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Get Payload Data\"...");
- sys_log_new_line();
+ break;
+ case PKT_ID_UPLINK_TRANSMIT_PACKET:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Transmit Packet\"...");
+ sys_log_new_line();
- process_tc_get_payload_data(pkt, pkt_len);
- break;
- case PKT_ID_UPLINK_SET_PARAM:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Set Parameter\"...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ process_tc_transmit_packet(pkt, pkt_len, is_scheduled);
+ }
+ else
+ {
+ err = -1;
+ }
- process_tc_set_parameter(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_UPDATE_TLE:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Update TLE\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_GET_PARAM:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Get Parameter\"...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ process_tc_update_tle(pkt, pkt_len, is_scheduled);
+ }
+ else
+ {
+ err = -1;
+ }
- process_tc_get_parameter(pkt, pkt_len);
+ break;
+ case PKT_ID_UPLINK_SCHED_TC:
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Schedule TC\"...");
+ sys_log_new_line();
- break;
- case PKT_ID_UPLINK_TRANSMIT_PACKET:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Transmit Packet\"...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ process_tc_schedule(pkt, pkt_len, is_scheduled);
+ }
+ else
+ {
+ err = -1;
+ }
- process_tc_transmit_packet(pkt, pkt_len);
+ break;
+ default:
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Unknown packet received!");
+ sys_log_new_line();
+ err = -1;
- break;
- case PKT_ID_UPLINK_UPDATE_TLE:
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Executing the TC \"Update TLE\"...");
- sys_log_new_line();
+ break;
+ }
- process_tc_update_tle(pkt, pkt_len);
+ return err;
+}
- break;
- default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Unknown packet received!");
- sys_log_new_line();
+void vTaskProcessTC(void *p)
+{
+ (void)p;
+
+ /* Wait startup task to finish */
+ (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_INIT_TIMEOUT_MS));
+
+ /* Delay before the first cycle */
+ vTaskDelay(pdMS_TO_TICKS(TASK_PROCESS_TC_INITIAL_DELAY_MS));
+
+ while(1)
+ {
+ TickType_t last_cycle = xTaskGetTickCount();
+
+ int pkts = ttc_avail(TTC_1);
+
+ if (pkts > 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "New ");
+ sys_log_print_uint((unsigned int)pkts);
+ sys_log_print_msg(" packet(s) available!");
+ sys_log_new_line();
- break;
+ uint8_t pkt[300] = {0};
+ uint16_t pkt_len = 0;
+
+ if (ttc_recv(TTC_1, pkt, &pkt_len) == 0)
+ {
+ if (execute_tc(pkt, pkt_len, false) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Invalid TC request!");
+ sys_log_new_line();
}
}
}
@@ -434,8 +574,10 @@ void vTaskProcessTC(void *p)
}
}
-static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ (void)is_scheduled;
+
if (pkt_len >= 8U)
{
/* Update last valid tc parameters */
@@ -459,7 +601,7 @@ static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&pong_pl, pong_pl_raw, &pong_pl_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_1, pong_pl_raw, pong_pl_raw_len) != 0)
{
@@ -470,25 +612,35 @@ static void process_tc_ping_request(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ bool authed = false;
+
/* If the satellite is in hibernation mode there is no point in processing this telecommand */
- if ((pkt_len >= (1U + 7U + 1U + 4U + 4U)) && (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION))
+ if ((pkt_len >= (1U + 7U + 1U + 4U + 4U)) && (!sat_data_buf.obdh.data.hibernation_on))
{
- fsat_pkt_pl_t data_req_ans_pkt = {0};
- uint8_t data_req_ans_raw[300] = {0};
- uint16_t data_req_ans_raw_len = UINT16_MAX;
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_DATA_REQUEST; // cppcheck-suppress misra-c2012-7.4
- /* Packet ID */
- fsat_pkt_add_id(&data_req_ans_pkt, PKT_ID_DOWNLINK_DATA_REQUEST_ANS);
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 4U + 4U, &pkt[17], 20U, tc_key, sizeof(CONFIG_TC_KEY_DATA_REQUEST)-1U))
+ {
+ authed = true;
+ }
+ }
- /* Source callsign */
- (void)fsat_pkt_add_callsign(&data_req_ans_pkt, CONFIG_SATELLITE_CALLSIGN);
+ if ((authed) || (is_scheduled))
+ {
+ fsat_pkt_pl_t data_req_ans_pkt = {0};
+ uint8_t data_req_ans_raw[300] = {0};
+ uint16_t data_req_ans_raw_len = UINT16_MAX;
- uint8_t tc_key[16] = CONFIG_TC_KEY_DATA_REQUEST; // cppcheck-suppress misra-c2012-7.4
+ /* Packet ID */
+ fsat_pkt_add_id(&data_req_ans_pkt, PKT_ID_DOWNLINK_DATA_REQUEST_ANS);
+
+ /* Source callsign */
+ (void)fsat_pkt_add_callsign(&data_req_ans_pkt, CONFIG_SATELLITE_CALLSIGN);
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 4U + 4U, &pkt[17], 20U, tc_key, sizeof(CONFIG_TC_KEY_DATA_REQUEST)-1U))
- {
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
@@ -527,7 +679,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -571,7 +723,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -615,7 +767,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -659,7 +811,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -703,7 +855,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -747,7 +899,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -791,7 +943,7 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&data_req_ans_pkt, data_req_ans_raw, &data_req_ans_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, data_req_ans_raw, data_req_ans_raw_len) != 0)
{
@@ -823,8 +975,10 @@ static void process_tc_data_request(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ (void)is_scheduled;
+
if ((pkt_len >= 15U) && (pkt_len <= 53U))
{
/* Update last valid tc parameter */
@@ -850,7 +1004,7 @@ static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&broadcast_pl, broadcast_pl_raw, &broadcast_pl_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_1, broadcast_pl_raw, broadcast_pl_raw_len) != 0)
{
@@ -861,29 +1015,47 @@ static void process_tc_broadcast_message(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- if (pkt_len >= 30U)
+ bool authed = false;
+
+ if (pkt_len >= (1U + 7U + 2U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_ENTER_HIBERNATION; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ENTER_HIBERNATION; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 7U + 2U, &pkt[10], 20U, tc_key, sizeof(CONFIG_TC_KEY_ENTER_HIBERNATION)-1U))
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 2U, &pkt[10], 20U, tc_key, sizeof(CONFIG_TC_KEY_ENTER_HIBERNATION)-1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- const event_t enter_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_MODE_HIBERNATION, .args[1] = pkt[8], .args[2] = pkt[9] };
+ const struct conops_event enter_hib = {
+ .callback = NULL,
+ .ev_name = "ENTER_HIB",
+ .src = (uint16_t) ((pkt[8] << 8U) | pkt[9]),
+ .ev_id = EV_TC_ENTER_HIBERNATION,
+ };
+
(void)notify_event_to_mission_manager(&enter_hib);
- if (xTaskNotifyWait(0U, UINT32_MAX, NULL, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) == pdTRUE)
+ /* Waits for Mission Manager notification. [Reuses startup event group to avoid memory usage] */
+ if ((xEventGroupWaitBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) & MISSION_MANAGER_NOTIFICATION_BIT) != 0U)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
}
else
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Enter hibernation\"");
sys_log_new_line();
+ (void)send_tc_feedback(pkt, ERRNO_FB_MISSION_MANAGER_NOTIFY_TIMEOUT);
}
}
else
@@ -894,29 +1066,47 @@ static void process_tc_enter_hibernation(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- if (pkt_len >= 28U)
+ bool authed = false;
+
+ if (pkt_len >= (1U + 7U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_LEAVE_HIBERNATION; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_LEAVE_HIBERNATION; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 7U, &pkt[8], 20U, tc_key, sizeof(CONFIG_TC_KEY_LEAVE_HIBERNATION)-1U))
+ if (process_tc_validate_hmac(pkt, 1U + 7U, &pkt[8], 20U, tc_key, sizeof(CONFIG_TC_KEY_LEAVE_HIBERNATION)-1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- const event_t leave_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_WAKE_UP, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event leave_hib = {
+ .callback = NULL,
+ .ev_name = "LEAVE_HIB",
+ .src = 0U,
+ .ev_id = EV_TC_LEAVE_HIBERNATION,
+ };
+
(void)notify_event_to_mission_manager(&leave_hib);
- if (xTaskNotifyWait(0U, UINT32_MAX, NULL, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) == pdTRUE)
+ /* Waits for Mission Manager notification. [Reuses startup event group to avoid memory usage] */
+ if ((xEventGroupWaitBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) & MISSION_MANAGER_NOTIFICATION_BIT) != 0U)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
}
else
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Leave hibernation\"");
sys_log_new_line();
+ (void)send_tc_feedback(pkt, ERRNO_FB_MISSION_MANAGER_NOTIFY_TIMEOUT);
}
}
else
@@ -927,15 +1117,24 @@ static void process_tc_leave_hibernation(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
int8_t err = -2;
+ bool authed = false;
- if (pkt_len >= 29U)
+ if (pkt_len >= (1U + 7U + 1U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_MODULE; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_MODULE; // cppcheck-suppress misra-c2012-7.4
+
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_MODULE)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_MODULE)-1U))
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
@@ -948,26 +1147,40 @@ static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len)
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the battery heater...");
sys_log_new_line();
- /* Enable the EPS heater */
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
+ uint8_t retry_count = 5U;
+
+ do
{
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_DUTY_CYCLE, 20U) == 0)
+ err = -2;
+
+ /* Enable the EPS heater */
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
{
- ++err;
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_DUTY_CYCLE, 20U) == 0)
+ {
+ ++err;
+ }
}
- }
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
- {
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_DUTY_CYCLE, 20U) == 0)
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
{
- ++err;
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_DUTY_CYCLE, 20U) == 0)
+ {
+ ++err;
+ }
}
- }
- if (err == 0)
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while((err < 0) && (retry_count > 0U));
+
+ if (retry_count != 0U)
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUBSYSTEM_COMM_FAIL);
}
break;
@@ -977,9 +1190,15 @@ static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len)
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the beacon...");
sys_log_new_line();
+ sat_data_buf.obdh.data.eps_beacon_on = true;
+
if (eps_set_param(SL_EPS2_REG_BEACON_ENABLE, 0x01U) == 0)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUBSYSTEM_COMM_FAIL);
}
break;
@@ -991,7 +1210,7 @@ static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len)
/* Enable periodic general telemetry */
sat_data_buf.obdh.data.general_telemetry_on = true;
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
break;
}
@@ -1010,15 +1229,24 @@ static void process_tc_activate_module(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
int8_t err = -2;
+ bool authed = false;
- if (pkt_len >= 29U)
+ if (pkt_len >= (1U + 7U + 1U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_MODULE; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_MODULE; // cppcheck-suppress misra-c2012-7.4
+
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_MODULE)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_MODULE)-1U))
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
@@ -1031,26 +1259,40 @@ static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len)
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the battery heater...");
sys_log_new_line();
- /* Disable the EPS heater */
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
+ uint8_t retry_count = 5U;
+
+ do
{
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_DUTY_CYCLE, 0U) == 0)
+ err = -2;
+
+ /* Disable the EPS heater */
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
{
- ++err;
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_1_DUTY_CYCLE, 0U) == 0)
+ {
+ ++err;
+ }
}
- }
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
- {
- if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_DUTY_CYCLE, 0U) == 0)
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_MODE, SL_EPS2_HEATER_MODE_MANUAL) == 0)
{
- ++err;
+ if (eps_set_param(SL_EPS2_REG_BAT_HEATER_2_DUTY_CYCLE, 0U) == 0)
+ {
+ ++err;
+ }
}
- }
- if (err == 0)
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while((err < 0) && (retry_count > 0U));
+
+ if (retry_count != 0U)
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUBSYSTEM_COMM_FAIL);
}
break;
@@ -1060,9 +1302,15 @@ static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len)
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the beacon...");
sys_log_new_line();
+ sat_data_buf.obdh.data.eps_beacon_on = false;
+
if (eps_set_param(SL_EPS2_REG_BEACON_ENABLE, 0x00U) == 0)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUBSYSTEM_COMM_FAIL);
}
break;
@@ -1074,7 +1322,7 @@ static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len)
/* Disable periodic general telemetry */
sat_data_buf.obdh.data.general_telemetry_on = false;
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
break;
}
@@ -1092,29 +1340,42 @@ static void process_tc_deactivate_module(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ struct conops_event pl_event = {
+ .ev_name = "PL_EN",
+ .callback = NULL,
+ };
+
int8_t err = 0;
- event_t pl_event = { 0 };
+ bool authed = false;
- if (pkt_len >= 29U)
+ if (pkt_len >= (1U + 7U + 1U))
{
switch(pkt[8])
{
case PL_ID_EDC_1:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the EDC 1 payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the EDC 1 payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_ACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_EDC_1;
+ pl_event.ev_id = EV_TC_ENABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_EDC_1;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1128,18 +1389,26 @@ static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len)
}
case PL_ID_EDC_2:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the EDC 2 payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_EDC)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the EDC 2 payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_ACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_EDC_2;
+ pl_event.ev_id = EV_TC_ENABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_EDC_2;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1153,18 +1422,26 @@ static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len)
}
case PL_ID_PAYLOAD_X:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the Payload-X payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_PAYLOAD_X; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_ACTIVATE_PAYLOAD_PAYLOAD_X; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_PAYLOAD_X)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ACTIVATE_PAYLOAD_PAYLOAD_X)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Activating the Payload-X payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_ACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_PAYLOAD_X;
+ pl_event.ev_id = EV_TC_ENABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_PAYLOAD_X;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1185,42 +1462,57 @@ static void process_tc_activate_payload(uint8_t *pkt, uint16_t pkt_len)
if (err == 0)
{
- if (xTaskNotifyWait(0U, UINT32_MAX, NULL, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) == pdTRUE)
+ /* Waits for Mission Manager notification. [Reuses startup event group to avoid memory usage] */
+ if ((xEventGroupWaitBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) & MISSION_MANAGER_NOTIFICATION_BIT) != 0U)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
}
else
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Activate payload\"");
sys_log_new_line();
+ (void)send_tc_feedback(pkt, ERRNO_FB_MISSION_MANAGER_NOTIFY_TIMEOUT);
}
}
}
}
-static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- event_t pl_event = { 0 };
+ struct conops_event pl_event = {
+ .callback = NULL,
+ .ev_name = "PL_DIS",
+ };
+
int8_t err = 0;
+ bool authed = false;
- if (pkt_len >= 29U)
+ if (pkt_len >= (1U + 7U + 1U))
{
switch(pkt[8])
{
case PL_ID_EDC_1:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the EDC 1 payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the EDC 1 payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_EDC_1;
+ pl_event.ev_id = EV_TC_DISABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_EDC_1;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1234,18 +1526,26 @@ static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len)
}
case PL_ID_EDC_2:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the EDC 2 payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_EDC)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the EDC 2 payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_EDC_2;
+ pl_event.ev_id = EV_TC_DISABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_EDC_2;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1259,18 +1559,26 @@ static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len)
}
case PL_ID_PAYLOAD_X:
{
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the Payload-X payload...");
- sys_log_new_line();
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_PAYLOAD_X; // cppcheck-suppress misra-c2012-7.4
- uint8_t tc_key[16] = CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_PAYLOAD_X; // cppcheck-suppress misra-c2012-7.4
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_PAYLOAD_X)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_PAYLOAD_X)-1U))
+ if ((authed) || (is_scheduled))
{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Deactivating the Payload-X payload...");
+ sys_log_new_line();
+
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
- pl_event.event = EV_NOTIFY_DEACTIVATE_PAYLOAD_RQ;
- pl_event.args[0] = PL_ID_PAYLOAD_X;
+ pl_event.ev_id = EV_TC_DISABLE_PAYLOAD;
+ pl_event.src = (uint16_t)PL_ID_PAYLOAD_X;
(void)notify_event_to_mission_manager(&pl_event);
}
else
@@ -1291,28 +1599,39 @@ static void process_tc_deactivate_payload(uint8_t *pkt, uint16_t pkt_len)
if (err == 0)
{
- if (xTaskNotifyWait(0U, UINT32_MAX, NULL, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) == pdTRUE)
+ /* Waits for Mission Manager notification. [Reuses startup event group to avoid memory usage] */
+ if ((xEventGroupWaitBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) & MISSION_MANAGER_NOTIFICATION_BIT) != 0U)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
}
else
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Deactivate payload\"");
sys_log_new_line();
+ (void)send_tc_feedback(pkt, ERRNO_FB_MISSION_MANAGER_NOTIFY_TIMEOUT);
}
}
}
}
-static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
int8_t err = 0;
+ bool authed = false;
- if (pkt_len >= 29U)
+ if (pkt_len >= (1U + 7U + 1U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_ERASE_MEMORY; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_ERASE_MEMORY; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 1U + 7U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ERASE_MEMORY)-1U))
+ if (process_tc_validate_hmac(pkt, 1U + 1U + 7U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_ERASE_MEMORY)-1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
@@ -1357,7 +1676,11 @@ static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len)
if (err == 0)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_DEVICE_COMM_FAIL);
}
}
else
@@ -1368,13 +1691,23 @@ static void process_tc_erase_memory(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_force_reset(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_force_reset(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- if (pkt_len >= 28U)
+ bool authed = false;
+
+ if (pkt_len >= (1U + 7U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_FORCE_RESET; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_FORCE_RESET; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 7U, &pkt[8], 20U, tc_key, sizeof(CONFIG_TC_KEY_FORCE_RESET)-1U))
+ if (process_tc_validate_hmac(pkt, 1U + 7U, &pkt[8], 20U, tc_key, sizeof(CONFIG_TC_KEY_FORCE_RESET)-1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
(void)eps_set_param(SL_EPS2_REG_RESET_EPS, 0x01U);
(void)ttc_set_param(TTC_0, SL_TTC2_REG_RESET_DEVICE, 0x01U);
@@ -1389,43 +1722,83 @@ static void process_tc_force_reset(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_get_payload_data(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_get_subsystem_table(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- if (pkt_len >= (1U + 7U + 1U + 12U + 20U))
+ bool authed = false;
+
+ if (pkt_len >= (1U + 7U + 1U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_GET_PAYLOAD_DATA; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_GET_SUBSYSTEM_TABLE; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 12U, &pkt[21], 20U, tc_key, sizeof(CONFIG_TC_KEY_GET_PAYLOAD_DATA) - 1U))
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U, &pkt[9], 20U, tc_key, sizeof(CONFIG_TC_KEY_GET_SUBSYSTEM_TABLE) - 1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
sat_data_buf.obdh.data.ts_last_contact = system_get_time();
+ /* The table request just responds with the current RAM stored tables/structs so it makes sense to
+ * reuse the format_data_request function used to download the flash stored tables/structs. However,
+ * that means IDs must match or be adapted like the EDC ids that use payload info. */
switch (pkt[8])
{
- case PL_ID_EDC_1:
+ case TABLE_ID_OBDH:
{
- uint8_t data_id = pkt[9];
+ fsat_pkt_pl_t pl_data;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &sat_data_buf.obdh) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+ break;
+ }
+ case TABLE_ID_EPS:
+ {
fsat_pkt_pl_t pl_data;
- if (format_data_request(pl_data.payload, &pl_data.length, data_id, &sat_data_buf.edc_0) == 0)
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &sat_data_buf.eps) == 0)
{
uint8_t pkt_raw[60];
- uint16_t pkt_len;
+ uint16_t raw_pkt_len;
/* Prepare Packet */
(void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
- pl_data.payload[7] = pkt[9]; /* Payload Arg */
- fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_PAYLOAD_DATA);
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
(void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
- fsat_pkt_encode(&pl_data, pkt_raw, &pkt_len);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
- if (ttc_send(TTC_0, pkt_raw, pkt_len) != 0)
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Payload Data\" answer!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
sys_log_new_line();
}
}
@@ -1434,29 +1807,174 @@ static void process_tc_get_payload_data(uint8_t *pkt, uint16_t pkt_len)
break;
}
- case PL_ID_EDC_2:
+ case TABLE_ID_TTC_0:
{
- uint8_t data_id = pkt[9];
+ fsat_pkt_pl_t pl_data;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &sat_data_buf.ttc_0) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+ break;
+ }
+ case TABLE_ID_TTC_1:
+ {
fsat_pkt_pl_t pl_data;
- if (format_data_request(pl_data.payload, &pl_data.length, data_id, &sat_data_buf.edc_1) == 0)
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &sat_data_buf.ttc_1) == 0)
{
uint8_t pkt_raw[60];
- uint16_t pkt_len;
+ uint16_t raw_pkt_len;
/* Prepare Packet */
(void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
- pl_data.payload[7] = pkt[9]; /* Payload Arg */
- fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_PAYLOAD_DATA);
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
(void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
- fsat_pkt_encode(&pl_data, pkt_raw, &pkt_len);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
- if (ttc_send(TTC_0, pkt_raw, pkt_len) != 0)
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Payload Data\" answer!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+
+ break;
+ }
+ case TABLE_ID_ANT:
+ {
+ fsat_pkt_pl_t pl_data;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &sat_data_buf.antenna) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+
+ break;
+ }
+ case TABLE_ID_SBCD:
+ {
+ fsat_pkt_pl_t pl_data;
+
+ edc_telemetry_t *edc = (sat_data_buf.obdh.data.main_edc == (uint8_t)PL_ID_EDC_1) ? &sat_data_buf.edc_0 : &sat_data_buf.edc_1;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, pkt[8], &edc->ptt) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+
+ break;
+ }
+ case TABLE_ID_EDC_0:
+ {
+ fsat_pkt_pl_t pl_data;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, DATA_ID_PAYLOAD_INFO, &sat_data_buf.edc_0) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
+ sys_log_new_line();
+ }
+ }
+
+ }
+
+ break;
+ }
+ case TABLE_ID_EDC_1:
+ {
+ fsat_pkt_pl_t pl_data;
+
+ if (format_data_request(pl_data.payload, &pl_data.length, DATA_ID_PAYLOAD_INFO, &sat_data_buf.edc_1) == 0)
+ {
+ uint8_t pkt_raw[60];
+ uint16_t raw_pkt_len;
+
+ /* Prepare Packet */
+ (void)memcpy(&pl_data.payload[0], &pkt[1], 7); /* Requester callsign */
+ pl_data.payload[7] = pkt[8]; /* Table ID */
+ fsat_pkt_add_id(&pl_data, PKT_ID_DOWNLINK_SUBSYSTEM_TABLE);
+ (void)fsat_pkt_add_callsign(&pl_data, CONFIG_SATELLITE_CALLSIGN);
+ fsat_pkt_encode(&pl_data, pkt_raw, &raw_pkt_len);
+
+ if (!sat_data_buf.obdh.data.hibernation_on)
+ {
+ if (ttc_send(TTC_0, pkt_raw, raw_pkt_len) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error transmitting a \"Get Subsystem Table\" answer!");
sys_log_new_line();
}
}
@@ -1465,28 +1983,38 @@ static void process_tc_get_payload_data(uint8_t *pkt, uint16_t pkt_len)
break;
}
default:
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Invalid payload ID!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Invalid table ID!");
sys_log_new_line();
break;
}
}
else
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error executing the \"Get Payload Data\" TC! Invalid key!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error executing the \"Get Subsystem Table\" TC! Invalid key!");
sys_log_new_line();
}
}
}
-static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
int8_t err = 0;
+ bool authed = false;
+ uint8_t retry_count = 5;
- if (pkt_len >= (1U + 7U + 1U + 1U + 4U + 20U))
+ if (pkt_len >= (1U + 7U + 1U + 1U + 4U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_SET_PARAMETER; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_SET_PARAMETER; // cppcheck-suppress misra-c2012-7.4
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 1U + 4U, &pkt[14], 20U, tc_key, sizeof(CONFIG_TC_KEY_SET_PARAMETER)-1U))
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 1U + 4U, &pkt[14], 20U, tc_key, sizeof(CONFIG_TC_KEY_SET_PARAMETER)-1U))
+ {
+ authed = true;
+ }
+ }
+
+ if ((authed) || (is_scheduled))
{
/* Update last valid tc parameter */
sat_data_buf.obdh.data.last_valid_tc = pkt[0];
@@ -1502,12 +2030,12 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
case SUBSYSTEM_ID_OBDH:
if (obdh_set_param(pkt[9], &buf) == 0)
{
- if (pkt[9] == OBDH_PARAM_ID_MODE)
+ if ((pkt[9] == OBDH_PARAM_ID_MODE) || (pkt[9] == OBDH_PARAM_ID_MAIN_PAYLOAD_STATE) || (pkt[9] == OBDH_PARAM_ID_SEC_PAYLOAD_STATE))
{
- /* Check for notification from mission_manager */
- if (xTaskNotifyWait(0U, UINT32_MAX, NULL, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) != pdTRUE)
+ /* Waits for Mission Manager notification. [Reuses startup event group to avoid memory usage] */
+ if ((xEventGroupWaitBits(task_startup_status, MISSION_MANAGER_NOTIFICATION_BIT, pdTRUE, pdTRUE, pdMS_TO_TICKS(TASK_PROCESS_TC_MAX_WAIT_TIME_MS)) & MISSION_MANAGER_NOTIFICATION_BIT) != 0U)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Set param MODE\"");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Mission manager notify timed out for \"Set Param\"");
sys_log_new_line();
err = -1;
}
@@ -1515,26 +2043,32 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
if (pkt[9] == OBDH_PARAM_ID_SYSTEM_TIME)
{
- if (eps_set_param(SL_EPS2_REG_TIME_COUNTER, buf) != 0)
+ do
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with EPS!");
- sys_log_new_line();
- err = -1;
- }
+ if (eps_set_param(SL_EPS2_REG_TIME_COUNTER, buf) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with EPS!");
+ sys_log_new_line();
+ err = -1;
+ }
- if (ttc_set_param(TTC_0, SL_TTC2_REG_TIME_COUNTER, buf) != 0)
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with TTC 0!");
- sys_log_new_line();
- err = -1;
- }
+ if (ttc_set_param(TTC_0, SL_TTC2_REG_TIME_COUNTER, buf) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with TTC 0!");
+ sys_log_new_line();
+ err = -1;
+ }
- if (ttc_set_param(TTC_1, SL_TTC2_REG_TIME_COUNTER, buf) != 0)
- {
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with TTC 1!");
- sys_log_new_line();
- err = -1;
- }
+ if (ttc_set_param(TTC_1, SL_TTC2_REG_TIME_COUNTER, buf) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Failed to synchronize system time with TTC 1!");
+ sys_log_new_line();
+ err = -1;
+ }
+
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
}
}
else
@@ -1546,27 +2080,48 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
break;
case SUBSYSTEM_ID_TTC_1:
- if (ttc_set_param(TTC_0, pkt[9], buf) != 0)
+ do
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error writing a TTC 0 parameter!");
+ err = ttc_set_param(TTC_0, pkt[9], buf);
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Max retries reached trying to write TTC 0 parameter!");
sys_log_new_line();
err = -1;
}
break;
case SUBSYSTEM_ID_TTC_2:
- if (ttc_set_param(TTC_1, pkt[9], buf) != 0)
+ do
+ {
+ err = ttc_set_param(TTC_1, pkt[9], buf);
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error writing a TTC 1 parameter!");
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Max retries reached trying to write TTC 1 parameter!");
sys_log_new_line();
err = -1;
}
break;
case SUBSYSTEM_ID_EPS:
- if (eps_set_param(pkt[9], buf) != 0)
+ do
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error writing a EPS parameter!");
+ err = eps_set_param(pkt[9], buf);
+ vTaskDelay(pdMS_TO_TICKS(50U));
+ --retry_count;
+ } while ((err < 0) && (retry_count > 0U));
+
+ if (retry_count == 0U)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Max retries reached trying to write EPS parameter!");
sys_log_new_line();
err = -1;
}
@@ -1581,7 +2136,11 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
if (err == 0)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUBSYSTEM_COMM_FAIL);
}
}
else
@@ -1592,13 +2151,23 @@ static void process_tc_set_parameter(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
- if (pkt_len >= (1U + 7U + 1U + 1U + 20U))
+ bool authed = false;
+
+ if (pkt_len >= (1U + 7U + 1U + 1U))
{
- uint8_t tc_key[16] = CONFIG_TC_KEY_GET_PARAMETER; // cppcheck-suppress misra-c2012-7.4
+ if (!is_scheduled)
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_GET_PARAMETER; // cppcheck-suppress misra-c2012-7.4
+
+ if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 1U, &pkt[10], 20U, tc_key, sizeof(CONFIG_TC_KEY_GET_PARAMETER)-1U))
+ {
+ authed = true;
+ }
+ }
- if (process_tc_validate_hmac(pkt, 1U + 7U + 1U + 1U, &pkt[10], 20U, tc_key, sizeof(CONFIG_TC_KEY_GET_PARAMETER)-1U))
+ if ((authed) || (is_scheduled))
{
int err = 0;
@@ -1675,7 +2244,7 @@ static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(¶m_pl, param_pl_raw, ¶m_pl_raw_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, param_pl_raw, param_pl_raw_len) != 0)
{
@@ -1699,8 +2268,10 @@ static void process_tc_get_parameter(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ (void)is_scheduled;
+
if (pkt_len >= (1U + 7U + 50U + 20U))
{
uint8_t tc_key[16] = CONFIG_TC_KEY_UPDATE_TLE; // cppcheck-suppress misra-c2012-7.4
@@ -1713,7 +2284,11 @@ static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len)
if (update_tle_line(&sat_data_buf.obdh, &pkt[8]) == 0)
{
- (void)send_tc_feedback(pkt);
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_FAILED_TO_UPDATE_FRAM);
}
}
else
@@ -1724,8 +2299,10 @@ static void process_tc_update_tle(uint8_t *pkt, uint16_t pkt_len)
}
}
-static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len)
+static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
{
+ (void)is_scheduled;
+
if ((pkt_len >= (1U + 7U + 20U)) && (pkt_len <= 73U))
{
uint8_t tc_key[16] = CONFIG_TC_KEY_TRANSMIT_PACKET; // cppcheck-suppress misra-c2012-7.4
@@ -1748,7 +2325,7 @@ static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len)
fsat_pkt_encode(&pkt_broacast, raw_pkt, &raw_pkt_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
if (ttc_send(TTC_0, raw_pkt, raw_pkt_len) != 0)
{
@@ -1767,6 +2344,38 @@ static void process_tc_transmit_packet(uint8_t *pkt, uint16_t pkt_len)
}
}
+static void process_tc_schedule(uint8_t *pkt, uint16_t pkt_len, bool is_scheduled)
+{
+ (void)is_scheduled;
+
+ if (pkt_len >= (1U + 7U + 4U + 1U + 7U + 20U))
+ {
+ uint8_t tc_key[16] = CONFIG_TC_KEY_SCHEDULE_TC; // cppcheck-suppress misra-c2012-7.4
+
+ if (process_tc_validate_hmac(pkt, pkt_len - 20U, &pkt[pkt_len - 20U], 20U, tc_key, sizeof(CONFIG_TC_KEY_SCHEDULE_TC)-1U))
+ {
+ /* Update last valid tc parameter */
+ sat_data_buf.obdh.data.last_valid_tc = pkt[0];
+ sat_data_buf.obdh.data.ts_last_contact = system_get_time();
+
+ if (schedule_tc(pkt, pkt_len) == 0)
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_SUCESSFULL_EXEC);
+ }
+ else
+ {
+ (void)send_tc_feedback(pkt, ERRNO_FB_FAILED_TO_SCHED_TC);
+ }
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_PROCESS_TC_NAME, "Error executing the \"Schedule TC\" TC! Invalid key!");
+ sys_log_new_line();
+ }
+ }
+
+}
+
static bool process_tc_validate_hmac(uint8_t *msg, uint16_t msg_len, uint8_t *msg_hash, uint16_t msg_hash_len, uint8_t *key, uint16_t key_len)
{
bool res = false;
@@ -1798,6 +2407,7 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
{
obdh_telemetry_t *tel = (obdh_telemetry_t *)data; // cppcheck-suppress misra-c2012-11.5
sys_time_t mode_duration = tel->timestamp - tel->data.ts_last_mode_change;
+ uint32_t data_log_page = sat_data_buf.obdh.data.media.last_page_obdh_data - CONFIG_MEM_OBDH_DATA_START_PAGE;
pl[0] = (tel->timestamp >> 24U) & 0xFFU;
pl[1] = (tel->timestamp >> 16U) & 0xFFU;
@@ -1831,71 +2441,63 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
pl[29] = mode_duration & 0xFFU;
pl[30] = tel->data.initial_hib_executed;
pl[31] = tel->data.ant_deployment_executed;
- pl[32] = tel->data.manual_mode_on;
+ pl[32] = tel->data.hibernation_on;
pl[33] = tel->data.main_edc;
pl[34] = tel->data.general_telemetry_on;
- pl[35] = (tel->data.media.last_page_obdh_data >> 24U) & 0xFFU;
- pl[36] = (tel->data.media.last_page_obdh_data >> 16U) & 0xFFU;
- pl[37] = (tel->data.media.last_page_obdh_data >> 8U) & 0xFFU;
- pl[38] = tel->data.media.last_page_obdh_data & 0xFFU;
- pl[39] = (tel->data.media.last_page_eps_data >> 24U) & 0xFFU;
- pl[40] = (tel->data.media.last_page_eps_data >> 16U) & 0xFFU;
- pl[41] = (tel->data.media.last_page_eps_data >> 8U) & 0xFFU;
- pl[42] = tel->data.media.last_page_eps_data & 0xFFU;
- pl[43] = (tel->data.media.last_page_ttc_0_data >> 24U) & 0xFFU;
- pl[44] = (tel->data.media.last_page_ttc_0_data >> 16U) & 0xFFU;
- pl[45] = (tel->data.media.last_page_ttc_0_data >> 8U) & 0xFFU;
- pl[46] = tel->data.media.last_page_ttc_0_data & 0xFFU;
- pl[47] = (tel->data.media.last_page_ttc_1_data >> 24U) & 0xFFU;
- pl[48] = (tel->data.media.last_page_ttc_1_data >> 16U) & 0xFFU;
- pl[49] = (tel->data.media.last_page_ttc_1_data >> 8U) & 0xFFU;
- pl[50] = tel->data.media.last_page_ttc_1_data & 0xFFU;
- pl[51] = (tel->data.media.last_page_ant_data >> 24U) & 0xFFU;
- pl[52] = (tel->data.media.last_page_ant_data >> 16U) & 0xFFU;
- pl[53] = (tel->data.media.last_page_ant_data >> 8U) & 0xFFU;
- pl[54] = tel->data.media.last_page_ant_data & 0xFFU;
- pl[55] = (tel->data.media.last_page_edc_data >> 24U) & 0xFFU;
- pl[56] = (tel->data.media.last_page_edc_data >> 16U) & 0xFFU;
- pl[57] = (tel->data.media.last_page_edc_data >> 8U) & 0xFFU;
- pl[58] = tel->data.media.last_page_edc_data & 0xFFU;
- pl[59] = (tel->data.media.last_page_px_data >> 24U) & 0xFFU;
- pl[60] = (tel->data.media.last_page_px_data >> 16U) & 0xFFU;
- pl[61] = (tel->data.media.last_page_px_data >> 8U) & 0xFFU;
- pl[62] = tel->data.media.last_page_px_data & 0xFFU;
- pl[63] = (tel->data.media.last_page_sbcd_pkts >> 24U) & 0xFFU;
- pl[64] = (tel->data.media.last_page_sbcd_pkts >> 16U) & 0xFFU;
- pl[65] = (tel->data.media.last_page_sbcd_pkts >> 8U) & 0xFFU;
- pl[66] = tel->data.media.last_page_sbcd_pkts & 0xFFU;
- pl[67] = (tel->data.position.timestamp >> 24U) & 0xFFU;
- pl[68] = (tel->data.position.timestamp >> 16U) & 0xFFU;
- pl[69] = (tel->data.position.timestamp >> 8U) & 0xFFU;
- pl[70] = tel->data.position.timestamp & 0xFFU;
- pl[71] = (((uint16_t)tel->data.position.latitude) >> 8U) & 0xFFU;
- pl[72] = ((uint16_t)tel->data.position.latitude) & 0xFFU;
- pl[73] = (((uint16_t)tel->data.position.longitude) >> 8U) & 0xFFU;
- pl[74] = ((uint16_t)tel->data.position.longitude) & 0xFFU;
- pl[75] = (((uint16_t)tel->data.position.altitude) >> 8U) & 0xFFU;
- pl[76] = ((uint16_t)tel->data.position.altitude) & 0xFFU;
- pl[77] = (tel->data.position.ts_last_tle_update >> 24U) & 0xFFU;
- pl[78] = (tel->data.position.ts_last_tle_update >> 16U) & 0xFFU;
- pl[79] = (tel->data.position.ts_last_tle_update >> 8U) & 0xFFU;
- pl[80] = tel->data.position.ts_last_tle_update & 0xFFU;
- pl[81] = (tel->data.ts_read_sensors >> 24U) & 0xFFU;
- pl[82] = (tel->data.ts_read_sensors >> 16U) & 0xFFU;
- pl[83] = (tel->data.ts_read_sensors >> 8U) & 0xFFU;
- pl[84] = tel->data.ts_read_sensors & 0xFFU;
- pl[85] = tel->data.main_payload_state;
- pl[86] = tel->data.sec_payload_state;
- pl[87] = (tel->data.hib_duration >> 24U) & 0xFFU;
- pl[88] = (tel->data.hib_duration >> 16U) & 0xFFU;
- pl[89] = (tel->data.hib_duration >> 8U) & 0xFFU;
- pl[90] = tel->data.hib_duration & 0xFFU;
- pl[91] = (tel->data.ts_last_contact >> 24U) & 0xFFU;
- pl[92] = (tel->data.ts_last_contact >> 16U) & 0xFFU;
- pl[93] = (tel->data.ts_last_contact >> 8U) & 0xFFU;
- pl[94] = tel->data.ts_last_contact & 0xFFU;
-
- *pkt_pl_len = (uint16_t) 103U; /* 7b RQ CALLSIGN + 1b TC ID + 95b OBDH DATA */
+ pl[35] = (data_log_page >> 24U) & 0xFFU;
+ pl[36] = (data_log_page >> 16U) & 0xFFU;
+ pl[37] = (data_log_page >> 8U) & 0xFFU;
+ pl[38] = data_log_page & 0xFFU;
+ pl[39] = (tel->data.media.last_page_sbcd_pkts >> 24U) & 0xFFU;
+ pl[40] = (tel->data.media.last_page_sbcd_pkts >> 16U) & 0xFFU;
+ pl[41] = (tel->data.media.last_page_sbcd_pkts >> 8U) & 0xFFU;
+ pl[42] = tel->data.media.last_page_sbcd_pkts & 0xFFU;
+ pl[43] = (tel->data.position.timestamp >> 24U) & 0xFFU;
+ pl[44] = (tel->data.position.timestamp >> 16U) & 0xFFU;
+ pl[45] = (tel->data.position.timestamp >> 8U) & 0xFFU;
+ pl[46] = tel->data.position.timestamp & 0xFFU;
+ pl[47] = (((uint16_t)tel->data.position.latitude) >> 8U) & 0xFFU;
+ pl[48] = ((uint16_t)tel->data.position.latitude) & 0xFFU;
+ pl[49] = (((uint16_t)tel->data.position.longitude) >> 8U) & 0xFFU;
+ pl[50] = ((uint16_t)tel->data.position.longitude) & 0xFFU;
+ pl[51] = (((uint16_t)tel->data.position.altitude) >> 8U) & 0xFFU;
+ pl[52] = ((uint16_t)tel->data.position.altitude) & 0xFFU;
+ pl[53] = (tel->data.position.ts_last_tle_update >> 24U) & 0xFFU;
+ pl[54] = (tel->data.position.ts_last_tle_update >> 16U) & 0xFFU;
+ pl[55] = (tel->data.position.ts_last_tle_update >> 8U) & 0xFFU;
+ pl[56] = tel->data.position.ts_last_tle_update & 0xFFU;
+ pl[57] = (tel->data.ts_read_sensors >> 24U) & 0xFFU;
+ pl[58] = (tel->data.ts_read_sensors >> 16U) & 0xFFU;
+ pl[59] = (tel->data.ts_read_sensors >> 8U) & 0xFFU;
+ pl[60] = tel->data.ts_read_sensors & 0xFFU;
+ pl[61] = tel->data.main_payload_state;
+ pl[62] = tel->data.sec_payload_state;
+ pl[63] = (tel->data.hib_duration >> 24U) & 0xFFU;
+ pl[64] = (tel->data.hib_duration >> 16U) & 0xFFU;
+ pl[65] = (tel->data.hib_duration >> 8U) & 0xFFU;
+ pl[66] = tel->data.hib_duration & 0xFFU;
+ pl[67] = (tel->data.ts_last_contact >> 24U) & 0xFFU;
+ pl[68] = (tel->data.ts_last_contact >> 16U) & 0xFFU;
+ pl[69] = (tel->data.ts_last_contact >> 8U) & 0xFFU;
+ pl[70] = tel->data.ts_last_contact & 0xFFU;
+ pl[71] = (tel->data.batt_crit_level_mv >> 8U) & 0xFFU;
+ pl[72] = tel->data.batt_crit_level_mv & 0xFFU;
+ pl[73] = (tel->data.last_tran_ev_id >> 8U) & 0xFFU;
+ pl[74] = tel->data.last_tran_ev_id & 0xFFU; /**/
+ pl[75] = tel->data.manual_experiments;
+ pl[76] = tel->data.eps_beacon_on;
+ pl[77] = (tel->data.ts_commission_timeout >> 24U) & 0xFFU;
+ pl[78] = (tel->data.ts_commission_timeout >> 16U) & 0xFFU;
+ pl[79] = (tel->data.ts_commission_timeout >> 8U) & 0xFFU;
+ pl[80] = tel->data.ts_commission_timeout & 0xFFU;
+ pl[81] = (tel->data.ts_next_sched_tc >> 24U) & 0xFFU;
+ pl[82] = (tel->data.ts_next_sched_tc >> 16U) & 0xFFU;
+ pl[83] = (tel->data.ts_next_sched_tc >> 8U) & 0xFFU;
+ pl[84] = tel->data.ts_next_sched_tc & 0xFFU;
+ pl[85] = tel->data.tc_queue_size;
+ (void)memcpy(&pl[86], tel->data.position.bin_tle, 50U);
+
+ *pkt_pl_len = (uint16_t) 144U; /* 7b RQ CALLSIGN + 1b TC ID + 136b OBDH DATA */
break;
}
@@ -2152,17 +2754,14 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
break;
}
+ /* Also used for EDC 0 and EDC 1 subsystem tables */
case DATA_ID_PAYLOAD_INFO:
{
- payload_telemetry_t *tel = (payload_telemetry_t *)data; // cppcheck-suppress misra-c2012-11.5
+ edc_telemetry_t *tel = (edc_telemetry_t *)data; // cppcheck-suppress misra-c2012-11.5
- /* Cast is safe since the buffer is internally copied from a edc_ptt_t */
- edc_hk_t *hk = (edc_hk_t*)&tel->data[0]; // cppcheck-suppress misra-c2012-11.3
+ edc_hk_t *hk = &tel->hk;
- /* The state data is stored right after the housekeeping data
- * on payload_telemetry_t's data field. The offset of 26 is
- * precisely the housekeeping data length*/
- edc_state_t *st = (edc_state_t*)&tel->data[26]; // cppcheck-suppress misra-c2012-11.3
+ edc_state_t *st = &tel->state;
pl[0] = (tel->timestamp >> 24U) & 0xFFU;
pl[1] = (tel->timestamp >> 16U) & 0xFFU;
@@ -2205,7 +2804,6 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
break;
}
-
default:
err = -1;
break;
@@ -2214,7 +2812,7 @@ static int8_t format_data_request(uint8_t *pkt_pl, uint16_t *pkt_pl_len, uint8_t
return err;
}
-static int8_t send_tc_feedback(uint8_t *pkt)
+static int8_t send_tc_feedback(uint8_t *pkt, int16_t error_code)
{
int8_t err = 0;
fsat_pkt_pl_t feedback = {0};
@@ -2240,13 +2838,15 @@ static int8_t send_tc_feedback(uint8_t *pkt)
feedback.payload[9] = (time >> 16U) & 0xFFU;
feedback.payload[10] = (time >> 8U) & 0xFFU;
feedback.payload[11] = time & 0xFFU;
+ feedback.payload[12] = ((uint16_t)error_code >> 8U) & 0xFFU;
+ feedback.payload[13] = error_code & 0xFF;
/* Payload lenght */
- feedback.length = 12U;
+ feedback.length = 14U;
fsat_pkt_encode(&feedback, feedback_pkt, &feedback_pkt_len);
- if (sat_data_buf.obdh.data.mode != OBDH_MODE_HIBERNATION)
+ if (!sat_data_buf.obdh.data.hibernation_on)
{
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_PROCESS_TC_NAME, "Transmitting \"TC Feedback\"...");
sys_log_new_line();
diff --git a/firmware/app/tasks/process_tc.h b/firmware/app/tasks/process_tc.h
index a2599cd9..d0dc975a 100644
--- a/firmware/app/tasks/process_tc.h
+++ b/firmware/app/tasks/process_tc.h
@@ -1,35 +1,35 @@
/*
* process_tc.h
- *
+ *
* Copyright The OBDH 2.0 Contributors.
- *
+ *
* This file is part of OBDH 2.0.
- *
+ *
* OBDH 2.0 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* OBDH 2.0 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with OBDH 2.0. If not, see .
- *
+ *
*/
/**
* \brief Process TC task definition.
- *
+ *
* \author Gabriel Mariano Marcelino
* \author Carlos Augusto Porto Freitas
- *
+ *
* \version 1.0.0
- *
+ *
* \date 2021/07/06
- *
+ *
* \defgroup process_tc Process TC
* \ingroup tasks
* \{
@@ -38,16 +38,20 @@
#ifndef PROCESS_TC_H_
#define PROCESS_TC_H_
+#include
+
#include
#include
#define TASK_PROCESS_TC_NAME "Process TC" /**< Task name. */
-#define TASK_PROCESS_TC_STACK_SIZE 1024 /**< Stack size in bytes. */
+#define TASK_PROCESS_TC_STACK_SIZE 2048 /**< Stack size in bytes. */
#define TASK_PROCESS_TC_PRIORITY 4 /**< Task priority. */
#define TASK_PROCESS_TC_PERIOD_MS 1000 /**< Task period in milliseconds. */
#define TASK_PROCESS_TC_INITIAL_DELAY_MS 6500 /**< Delay, in milliseconds, before the first execution. */
#define TASK_PROCESS_TC_INIT_TIMEOUT_MS 10000 /**< Wait time to initialize the task in milliseconds. */
-#define TASK_PROCESS_TC_MAX_WAIT_TIME_MS (350) /**< Max wait time to received a confirmation notification from mission manager in milliseconds. */
+#define TASK_PROCESS_TC_MAX_WAIT_TIME_MS (5000) /**< Max wait time to received a confirmation notification from mission manager in milliseconds. */
+
+#define MISSION_MANAGER_NOTIFICATION_BIT (1U << 2U) /**< Mission Manager notification bit on event group. */
/**
* \brief Process TC handle.
@@ -61,6 +65,22 @@ extern xTaskHandle xTaskProcessTCHandle;
*/
void vTaskProcessTC(void* p);
+/**
+ * \brief Executes/Processes a telecommand.
+ *
+ * \param[in] pkt is the packet to process.
+ *
+ * \param[in] pkt_len is the number of bytes of the given packet.
+ *
+ * \param[in] is_scheduled is a flag to mark if a telecommand packet
+ * was scheduled instead of just received. This is needed because in a
+ * scheduled TC there is no need to authenticate it, since it was
+ * authenticated on queue insertion.
+ *
+ * \return The status/error code.
+ */
+int execute_tc(uint8_t *pkt, uint8_t pkt_len, bool is_scheduled);
+
#endif /* PROCESS_TC_H_ */
/** \} End of process_tc group */
diff --git a/firmware/app/tasks/read_edc.c b/firmware/app/tasks/read_edc.c
index 75693708..fb9cac07 100644
--- a/firmware/app/tasks/read_edc.c
+++ b/firmware/app/tasks/read_edc.c
@@ -53,7 +53,7 @@ xTaskHandle xTaskReadEDCHandle;
pl_edc_hk_raw_t edc_hk_buf = {0};
-static void print_edc_hk(uint8_t *hk);
+static void print_edc_hk(edc_hk_t *hk);
void vTaskReadEDC(void *p)
{
@@ -72,7 +72,7 @@ void vTaskReadEDC(void *p)
{
payload_t pl_edc_active = (payload_t)sat_data_buf.obdh.data.main_payload_state;
- payload_telemetry_t * const edc = sat_data_buf.state.c_edc;
+ edc_telemetry_t * const edc = sat_data_buf.state.c_edc;
if ((pl_edc_active != PAYLOAD_NONE) && (edc != NULL))
{
@@ -94,14 +94,18 @@ void vTaskReadEDC(void *p)
vTaskDelay(pdMS_TO_TICKS(50)); /* Wait a while for the next command */
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "Active EDC ID: ");
+ sys_log_print_hex((uint32_t)pl_edc_active);
+ sys_log_new_line();
+
/* Read housekeeping data */
- if (payload_get_data(pl_edc_active, PAYLOAD_EDC_RAW_HK, edc_hk_buf.buffer, &edc_hk_buf.length) == 0)
+ if (payload_get_data(pl_edc_active, PAYLOAD_EDC_HK, edc_hk_buf.buffer, &edc_hk_buf.length) == 0)
{
- (void)memcpy(edc->data, edc_hk_buf.buffer, EDC_FRAME_HK_LEN);
+ (void)memcpy(&edc->hk, edc_hk_buf.buffer, sizeof(edc_hk_t));
vTaskDelay(pdMS_TO_TICKS(50U));
- print_edc_hk(edc_hk_buf.buffer);
+ print_edc_hk(&edc->hk);
}
else
{
@@ -119,24 +123,21 @@ void vTaskReadEDC(void *p)
{
if (state_len >= (int32_t)sizeof(edc_state_t))
{
- (void)memcpy(&edc->data[EDC_FRAME_HK_LEN], state_arr, EDC_FRAME_STATE_LEN);
+ (void)memcpy(&edc->state, state_arr, EDC_FRAME_STATE_LEN);
edc->timestamp = system_get_time();
- /* Cast is safe since the buffer is internally copied from a edc_state_t */
- edc_state_t *state = (edc_state_t*)&state_arr[0]; // cppcheck-suppress misra-c2012-11.3
-
- if (state->ptt_available > 0U)
+ if (edc->state.ptt_available > 0U)
{
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "");
- sys_log_print_uint(state->ptt_available);
+ sys_log_print_uint(edc->state.ptt_available);
sys_log_print_msg(" PTT packet(s) available to read!");
sys_log_new_line();
vTaskDelay(pdMS_TO_TICKS(50U));
uint8_t i = 0;
- for(i = 0; i < state->ptt_available; i++)
+ for(i = 0; i < edc->state.ptt_available; i++)
{
uint8_t ptt_arr[50] = {0};
int32_t ptt_len = 0;
@@ -149,22 +150,21 @@ void vTaskReadEDC(void *p)
sys_log_new_line();
}
- /* Cast is safe since the buffer is internally copied from a edc_ptt_t */
- edc_ptt_t *ptt = (edc_ptt_t*)&ptt_arr[0]; // cppcheck-suppress misra-c2012-11.3
+ (void)memcpy(&edc->ptt, ptt_arr, sizeof(edc_ptt_t));
- int32_t ptt_power = -67 + (20 * log10(ptt->carrier_abs/32768.0));
+ int32_t ptt_power = -67 + (20 * log10(edc->ptt.carrier_abs/32768.0));
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "Received PTT packet:");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "\tTime: ");
- sys_log_print_uint(ptt->time_tag);
+ sys_log_print_uint(edc->ptt.time_tag);
sys_log_print_msg(" sec");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "\tError code: ");
- sys_log_print_uint(ptt->error_code);
+ sys_log_print_uint(edc->ptt.error_code);
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "\tCarrier frequency: ");
- sys_log_print_uint(ptt->carrier_freq);
+ sys_log_print_uint(edc->ptt.carrier_freq);
sys_log_print_msg(" Hz");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "\tReceived signal power: ");
@@ -172,7 +172,7 @@ void vTaskReadEDC(void *p)
sys_log_print_msg(" dBm");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_EDC_NAME, "\tUser message: ");
- sys_log_dump_hex(ptt->user_msg, ptt->msg_byte_length);
+ sys_log_dump_hex(edc->ptt.user_msg, edc->ptt.msg_byte_length);
sys_log_new_line();
}
else
@@ -197,30 +197,25 @@ void vTaskReadEDC(void *p)
}
}
-static void print_edc_hk(uint8_t *hk)
+static void print_edc_hk(edc_hk_t *hk)
{
- uint16_t curr_dig = (hk[10] << 8U) | hk[9];
- uint16_t curr_rf = (hk[12] << 8U) | hk[11];
- uint16_t volt = (hk[14] << 8U) | hk[13];
- int16_t temp = (int16_t)hk[15] - 40;
-
sys_log_print_event_from_module(SYS_LOG_INFO, "EDC Status", "Current(Dig): ");
- sys_log_print_uint((uint32_t) curr_dig);
+ sys_log_print_uint((uint32_t) hk->current_supply_d);
sys_log_print_msg(" mA");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, "EDC Status", "Current(RF): ");
- sys_log_print_uint((uint32_t) curr_rf);
+ sys_log_print_uint((uint32_t) hk->current_supply_a);
sys_log_print_msg(" mA");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, "EDC Status", "Sys Voltage: ");
- sys_log_print_uint((uint32_t) volt);
+ sys_log_print_uint((uint32_t) hk->voltage_supply);
sys_log_print_msg(" mV");
sys_log_new_line();
sys_log_print_event_from_module(SYS_LOG_INFO, "EDC Status", "Board Temp: ");
- sys_log_print_int((int32_t) temp);
+ sys_log_print_int((int32_t) hk->temp);
sys_log_print_msg(" oC");
sys_log_new_line();
}
diff --git a/firmware/app/tasks/read_edc.h b/firmware/app/tasks/read_edc.h
index fac93d63..1f98b18d 100644
--- a/firmware/app/tasks/read_edc.h
+++ b/firmware/app/tasks/read_edc.h
@@ -40,19 +40,20 @@
#include
#include
+#include
#define TASK_READ_EDC_NAME "EDC Task" /**< Task name. */
#define TASK_READ_EDC_STACK_SIZE 300 /**< Stack size in bytes. */
#define TASK_READ_EDC_PRIORITY 3 /**< Task priority. */
#define TASK_READ_EDC_PERIOD_MS (60000) /**< Task period in milliseconds. */
#define TASK_READ_EDC_INIT_TIMEOUT_MS 5000 /**< Wait time to initialize the task in milliseconds. */
-#define TASK_READ_EDC_INITIAL_DELAY_MS 5500 /**< Delay, in milliseconds, before the first execution. */
+#define TASK_READ_EDC_INITIAL_DELAY_MS 15000 /**< Delay, in milliseconds, before the first execution. */
/**
* \brief EDC housekeeping raw data type.
*/
typedef struct
{
- uint8_t buffer[30];
+ uint8_t buffer[sizeof(edc_hk_t)];
int32_t length;
} pl_edc_hk_raw_t;
diff --git a/firmware/app/tasks/read_eps.c b/firmware/app/tasks/read_eps.c
index 6c67c212..e48bdb46 100644
--- a/firmware/app/tasks/read_eps.c
+++ b/firmware/app/tasks/read_eps.c
@@ -1,34 +1,34 @@
/*
* read_eps.c
- *
+ *
* Copyright (C) 2021, SpaceLab.
- *
+ *
* This file is part of OBDH 2.0.
- *
+ *
* OBDH 2.0 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* OBDH 2.0 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with OBDH 2.0. If not, see .
- *
+ *
*/
/**
* \brief Read EPS data task implementation.
- *
+ *
* \author Gabriel Mariano Marcelino
- *
+ *
* \version 1.0.0
- *
+ *
* \date 2021/05/08
- *
+ *
* \addtogroup read_eps
* \{
*/
@@ -40,10 +40,11 @@
#include
#include "read_eps.h"
+#include "mission_manager.h"
#include "startup.h"
-#define READ_EPS_MAX_RETRIES (3U)
-#define READ_EPS_RETRY_DELAY_MS (500U)
+#define READ_EPS_MAX_RETRIES (10U)
+#define READ_EPS_RETRY_DELAY_MS (400U)
xTaskHandle xTaskReadEPSHandle;
@@ -87,14 +88,48 @@ void vTaskReadEPS(void *p)
{
sat_data_buf.eps.timestamp = system_get_time();
}
- else
+ else
{
retry_count--;
vTaskDelay(pdMS_TO_TICKS(READ_EPS_RETRY_DELAY_MS));
}
} while ((err != 0) && (retry_count > 0U));
- if (retry_count == 0U)
+ if (retry_count != 0U)
+ {
+ if (sat_data_buf.eps.data.battery_voltage <= sat_data_buf.obdh.data.batt_crit_level_mv)
+ {
+ const struct conops_event fdir = {
+ .callback = NULL,
+ .ev_name = "FDIR",
+ .src = 0U,
+ .ev_id = EV_BATTERY_LEVEL_CRITICAL,
+ };
+
+ if (notify_event_to_mission_manager(&fdir) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_READ_EPS_NAME, "Failed to notify Mission Manager of critical level on batteries!");
+ sys_log_new_line();
+ }
+ }
+
+ if ((sat_data_buf.obdh.data.mode == OBDH_MODE_FDIR) && (sat_data_buf.eps.data.battery_voltage >= (sat_data_buf.obdh.data.batt_crit_level_mv + 150U)) && (sat_data_buf.obdh.data.last_tran_ev_id == EV_BATTERY_LEVEL_CRITICAL))
+ {
+ const struct conops_event fdir_res = {
+ .callback = NULL,
+ .ev_name = "FDIR-RES",
+ .src = 0U,
+ .ev_id = EV_FDIR_RESOLVED,
+ };
+
+ if (notify_event_to_mission_manager(&fdir_res) != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_READ_EPS_NAME, "Failed to notify Mission Manager of FDIR resolution!");
+ sys_log_new_line();
+ }
+ }
+ }
+ else
{
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_READ_EPS_NAME, "Max retries reached trying to read data from EPS!!!");
sys_log_new_line();
diff --git a/firmware/app/tasks/read_px.c b/firmware/app/tasks/read_px.c
index 94d8368d..bb4497fe 100644
--- a/firmware/app/tasks/read_px.c
+++ b/firmware/app/tasks/read_px.c
@@ -66,7 +66,6 @@ void vTaskReadPX(void *p)
while(1)
{
- uint32_t cancel_flag;
uint32_t active_period_ms;
BaseType_t result = xTaskNotifyWait(0UL, UINT32_MAX, &active_period_ms, pdMS_TO_TICKS(TASK_READ_PX_MAX_WAIT_TIME_MS));
@@ -79,16 +78,6 @@ void vTaskReadPX(void *p)
while (active_period_ms > 0U)
{
- /* Check notifications to break out of the loop if requested */
- if (xTaskNotifyWait(0UL, PAYLOAD_X_CANCEL_EXPERIMENT_FLAG, &cancel_flag, 0U) == pdTRUE)
- {
- if ((cancel_flag & PAYLOAD_X_CANCEL_EXPERIMENT_FLAG) != 0U)
- {
- active_period_ms = 0U;
- break;
- }
- }
-
/* Read data */
if (payload_get_data(pl_px_active, PAYLOAD_X_PONG, px_buf.buffer, &px_buf.length) != 0)
{
@@ -123,7 +112,12 @@ void vTaskReadPX(void *p)
vTaskDelayUntil(&last_cycle, pdMS_TO_TICKS(TASK_READ_PX_PERIOD_MS));
}
- const event_t px_end = { .event = EV_NOTIFY_PX_FINISHED, .args[0] = 0U, .args[1] = 0U, .args[2] = 0U };
+ const struct conops_event px_end = {
+ .ev_id = EV_PX_FINISHED,
+ .ev_name = "EXP-END",
+ .callback = NULL,
+ .src = 0U,
+ };
if (notify_event_to_mission_manager(&px_end) != 0)
{
diff --git a/firmware/app/tasks/read_sensors.c b/firmware/app/tasks/read_sensors.c
index fbd7381c..7fa5a65d 100644
--- a/firmware/app/tasks/read_sensors.c
+++ b/firmware/app/tasks/read_sensors.c
@@ -63,7 +63,7 @@ void vTaskReadSensors(void *p)
{
sat_data_buf.obdh.data.current = buf;
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_SENSORS_NAME, "Current input current: ");
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_SENSORS_NAME, "Current uC current: ");
sys_log_print_uint((uint32_t)buf);
sys_log_print_msg(" mA");
sys_log_new_line();
@@ -74,7 +74,7 @@ void vTaskReadSensors(void *p)
{
sat_data_buf.obdh.data.voltage = buf;
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_SENSORS_NAME, "Current input voltage: ");
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_READ_SENSORS_NAME, "Current uC voltage: ");
sys_log_print_uint((uint32_t)buf);
sys_log_print_msg(" mV");
sys_log_new_line();
diff --git a/firmware/app/tasks/sched_tc.c b/firmware/app/tasks/sched_tc.c
new file mode 100644
index 00000000..6efc73eb
--- /dev/null
+++ b/firmware/app/tasks/sched_tc.c
@@ -0,0 +1,176 @@
+/*
+ * sched_tc.c
+ *
+ * Copyright The OBDH 2.0 Contributors.
+ *
+ * This file is part of OBDH 2.0.
+ *
+ * OBDH 2.0 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OBDH 2.0 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OBDH 2.0. If not, see .
+ *
+ */
+
+/**
+ * \brief Scheduled TC Execution Task definition.
+ *
+ * \author Carlos Augusto Porto Freitas
+ *
+ * \version 1.0.0
+ *
+ * \date 2025/04/12
+ *
+ * \addtogroup sched_tc
+ * \{
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "sched_tc.h"
+#include "process_tc.h"
+#include "startup.h"
+
+TaskHandle_t xTaskSchedTCHandle;
+
+static struct conops_cmd_queue tc_queue;
+
+static void tc_queue_lock(void *lock)
+{
+ SemaphoreHandle_t sem = *(SemaphoreHandle_t*)lock; // cppcheck-suppress misra-c2012-11.2
+
+ if (xSemaphoreTake(sem, pdMS_TO_TICKS(TC_QUEUE_MUTEX_TIMEOUT_MS)) == pdFALSE)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_SCHED_TC_NAME, "Failed to acquire TC Queue lock!");
+ sys_log_new_line();
+ }
+}
+
+static void tc_queue_unlock(void *lock)
+{
+ SemaphoreHandle_t sem = *(SemaphoreHandle_t*)lock; // cppcheck-suppress misra-c2012-11.2
+
+ (void)xSemaphoreGive(sem);
+}
+
+void reset_sched_tc_queue(void)
+{
+ cmd_queue_reset(&tc_queue);
+}
+
+int save_sched_tc_queue_to_fram(void)
+{
+ return mem_mng_save_tc_queue_to_fram(&tc_queue);
+}
+
+int schedule_tc(uint8_t *pkt, uint16_t pkt_size)
+{
+ struct conops_cmd tc = {0};
+
+ tc.timestamp = ((uint32_t)pkt[8] << 24U) |
+ ((uint32_t)pkt[9] << 16U) |
+ ((uint32_t)pkt[10] << 8U) |
+ ((uint32_t)pkt[11] << 0U);
+
+ /* Remove packet ID, callsign, timestamp and hmac hash from the packet size before copying */
+ (void)memcpy(tc.payload, &pkt[12], pkt_size - 1U - 7U - 4U - 20U);
+
+ return cmd_queue_enqueue(&tc_queue, &tc);
+}
+
+void vTaskSchedTC(void* p)
+{
+ (void)p;
+
+ SemaphoreHandle_t xSemQueuelock = NULL;
+ uint16_t qsize = 0U;
+ int err = 0;
+
+ (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_SCHED_TC_STARTUP_TIMEOUT_MS));
+
+ if (mem_mng_load_tc_queue_from_fram(&tc_queue) == 0)
+ {
+ qsize = tc_queue.size;
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_SCHED_TC_NAME, "Failed to load TC queue from FRAM!");
+ sys_log_new_line();
+ }
+
+ xSemQueuelock = xSemaphoreCreateMutex();
+
+ if (xSemQueuelock != NULL)
+ {
+ cmd_queue_init(&tc_queue, &xSemQueuelock, tc_queue_lock, tc_queue_unlock);
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_SCHED_TC_NAME, "Failed to create TC Queue lock! Using lockless impl...");
+ sys_log_new_line();
+
+ cmd_queue_init(&tc_queue, NULL, NULL, NULL);
+ }
+
+ /* The cmd_queue_init function resets the queue size, thus this step is needed to preserve its size */
+ if (qsize != 0U)
+ {
+ tc_queue.size = qsize;
+ }
+
+ TickType_t last_cycle = xTaskGetTickCount();
+
+ while (1)
+ {
+ struct conops_cmd tc = {0};
+
+ uint32_t now = system_get_time();
+
+ while (cmd_queue_dequeue(&tc_queue, now, &tc) == 1)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_SCHED_TC_NAME, "Executing TC scheduled for: ");
+ sys_log_print_uint(tc.timestamp);
+ sys_log_new_line();
+
+ err = execute_tc(tc.payload, sizeof(tc.payload), true);
+
+ if (err != 0)
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_SCHED_TC_NAME, "Invalid TC was scheduled!");
+ sys_log_new_line();
+ }
+ }
+
+ sat_data_buf.obdh.data.tc_queue_size = (uint8_t)tc_queue.size;
+ sat_data_buf.obdh.data.ts_next_sched_tc = (tc_queue.size > 0U) ? ((uint32_t)tc_queue.buffer[0].timestamp) : (0U);
+
+ vTaskDelayUntil(&last_cycle, pdMS_TO_TICKS(TASK_SCHED_TC_PERIOD_MS));
+ }
+}
+
+/** \} End of sched_tc group */
diff --git a/firmware/app/tasks/sched_tc.h b/firmware/app/tasks/sched_tc.h
new file mode 100644
index 00000000..ccc14a22
--- /dev/null
+++ b/firmware/app/tasks/sched_tc.h
@@ -0,0 +1,92 @@
+/*
+ * sched_tc.h
+ *
+ * Copyright The OBDH 2.0 Contributors.
+ *
+ * This file is part of OBDH 2.0.
+ *
+ * OBDH 2.0 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OBDH 2.0 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OBDH 2.0. If not, see .
+ *
+ */
+
+/**
+ * \brief Scheduled TC Execution Task definition.
+ *
+ * \author Carlos Augusto Porto Freitas
+ *
+ * \version 1.0.0
+ *
+ * \date 2025/04/12
+ *
+ * \defgroup sched_tc Scheduled TC
+ * \ingroup tasks
+ * \{
+ */
+
+#ifndef SCHED_TC_H_
+#define SCHED_TC_H_
+
+#include
+
+#include
+#include
+
+#define TASK_SCHED_TC_NAME "Sched-TC" /**< Task name. */
+#define TASK_SCHED_TC_STACK_SIZE 1024U /**< Stack size in bytes. */
+#define TASK_SCHED_TC_PRIORITY 2U /**< Task priority. */
+#define TASK_SCHED_TC_PERIOD_MS 1000U /**< Task period. */
+#define TASK_SCHED_TC_STARTUP_TIMEOUT_MS (5000UL) /**< Task startup event group notification timeout */
+
+#define TC_QUEUE_MUTEX_TIMEOUT_MS 10000UL /**< TC Queue mutex max wait time */
+
+/**
+ * \brief Scheduled TC Execution Task Handle.
+ */
+extern TaskHandle_t xTaskSchedTCHandle;
+
+/**
+ * \brief Scheduled TC Execution Task.
+ *
+ * \return None.
+ */
+void vTaskSchedTC(void* p);
+
+/**
+ * \brief Resets TC Queue.
+ *
+ * \return None.
+ */
+void reset_sched_tc_queue(void);
+
+/**
+ * \brief Saves TC Queue to FRAM.
+ *
+ * \return The status/error code.
+ */
+int save_sched_tc_queue_to_fram(void);
+
+/**
+ * \brief Schedule TC.
+ *
+ * \param[in] pkt is the received 'Schedule TC' telecommand packet.
+ *
+ * \param[in] pkt_len is the packet size.
+ *
+ * \return The status/error code.
+ */
+int schedule_tc(uint8_t *pkt, uint16_t pkt_size);
+
+#endif
+
+/** \} End of sched_tc group */
diff --git a/firmware/app/tasks/startup.c b/firmware/app/tasks/startup.c
index 0f0cee31..ea410c1a 100644
--- a/firmware/app/tasks/startup.c
+++ b/firmware/app/tasks/startup.c
@@ -61,7 +61,93 @@ xTaskHandle xTaskStartupHandle;
EventGroupHandle_t task_startup_status;
-static int media_nor_clean(void);
+static int media_nor_clean(void)
+{
+ int err = 0;
+ int die0_err = -1;
+ int die1_err = -1;
+ uint8_t retries = 5U;
+
+ do
+ {
+ if (die0_err != 0)
+ {
+ die0_err = media_erase(MEDIA_NOR, MEDIA_ERASE_DIE, 0U);
+ }
+
+ if (die1_err != 0)
+ {
+ die1_err = media_erase(MEDIA_NOR, MEDIA_ERASE_DIE, 1U);
+ }
+
+ if ((die0_err != 0) || (die0_err != 0))
+ {
+ err = -1;
+ }
+ else
+ {
+ err = 0;
+ }
+
+ --retries;
+ } while((err != 0) && (retries > 0U));
+
+ return err;
+}
+
+static void sys_log_print_obdh_parameters(obdh_telemetry_t *params)
+{
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Operation Mode: ");
+ sys_log_print_hex((uint32_t)params->data.mode);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Antenna Deployment Params: deploy_counter (");
+ sys_log_print_uint((uint32_t)params->data.ant_deployment_counter);
+ sys_log_print_msg("), deploy_exec (");
+ sys_log_print_uint((uint32_t)params->data.ant_deployment_executed);
+ sys_log_print_msg("), init_hib_count (");
+ sys_log_print_uint((uint32_t)params->data.initial_hib_time_count);
+ sys_log_print_msg("), init_hib_exec (");
+ sys_log_print_uint((uint32_t)params->data.initial_hib_executed);
+ sys_log_print_msg(")");
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Used flash pages: ");
+ sys_log_print_uint(params->data.media.last_page_obdh_data);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Last flash update timestamp: ");
+ sys_log_print_uint(params->timestamp);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Main EDC: ");
+ sys_log_print_hex((uint32_t)params->data.main_edc);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Main payload state: ");
+ sys_log_print_hex((uint32_t)params->data.main_payload_state);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Secondary payload state: ");
+ sys_log_print_hex((uint32_t)params->data.sec_payload_state);
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Battery Critical Level: ");
+ sys_log_print_uint((uint32_t)params->data.batt_crit_level_mv);
+ sys_log_print_msg(" mV");
+ sys_log_new_line();
+
+ sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Operation flags: hibernation_on (");
+ sys_log_print_uint((uint32_t)params->data.hibernation_on);
+ sys_log_print_msg("), general_telemetry_on (");
+ sys_log_print_uint((uint32_t)params->data.general_telemetry_on);
+ sys_log_print_msg("), eps_beacon (");
+ sys_log_print_uint((uint32_t)params->data.eps_beacon_on);
+ sys_log_print_msg("), manual_experiments (");
+ sys_log_print_uint((uint32_t)params->data.manual_experiments);
+ sys_log_print_msg(")");
+ sys_log_new_line();
+}
void vTaskStartup(void *p)
{
@@ -164,6 +250,11 @@ void vTaskStartup(void *p)
sys_log_print_event_from_module(SYS_LOG_ERROR, TASK_STARTUP_NAME, "Failed to load OBDH data correctly!");
sys_log_new_line();
+ sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_STARTUP_NAME, "Cleaning NOR memory...");
+ sys_log_new_line();
+
+ (void)media_nor_clean();
+
sys_log_print_event_from_module(SYS_LOG_WARNING, TASK_STARTUP_NAME, "Loading default values to memory...");
sys_log_new_line();
@@ -221,6 +312,14 @@ void vTaskStartup(void *p)
}
#endif /* CONFIG_DEV_MEDIA_FRAM_ENABLED */
+ /* FRAM initialization status = Done */
+ (void)xEventGroupSetBits(task_startup_status, FRAM_INIT_DONE);
+
+ /* Print OBDH parameters */
+#if defined(CONFIG_PRINT_OBDH_PARAMS) && (CONFIG_PRINT_OBDH_PARAMS == 1)
+ sys_log_print_obdh_parameters(&sat_data_buf.obdh);
+#endif
+
#if defined(CONFIG_DEV_LEDS_ENABLED) && (CONFIG_DEV_LEDS_ENABLED == 1)
/* LEDs device initialization */
if (leds_init() != 0)
@@ -329,16 +428,7 @@ void vTaskStartup(void *p)
sat_data_buf.obdh.data.hw_version = system_get_hw_version();
-#if defined (CONFIG_TASK_ANTENNA_DEPLOYMENT_ENABLED) && (CONFIG_TASK_ANTENNA_DEPLOYMENT_ENABLED == 1)
- if (!sat_data_buf.obdh.data.initial_hib_executed)
- {
- const event_t initial_hib = { .event = EV_NOTIFY_MODE_CHANGE_RQ, .args[0] = OBDH_MODE_HIBERNATION, .args[1] = 0U, .args[2] = 1U };
- notify_event_to_mission_manager(&initial_hib);
-
- sys_log_print_event_from_module(SYS_LOG_INFO, TASK_STARTUP_NAME, "Sent initial hibernation event to Mission Manager!");
- sys_log_new_line();
- }
-#endif
+ sat_data_buf.obdh.data.last_reset_cause = system_get_reset_cause();
/* Startup task status = Done */
(void)xEventGroupSetBits(task_startup_status, TASK_STARTUP_DONE);
@@ -346,21 +436,4 @@ void vTaskStartup(void *p)
vTaskSuspend(xTaskStartupHandle);
}
-static int media_nor_clean(void)
-{
- int err = 0;
-
- if (media_erase(MEDIA_NOR, MEDIA_ERASE_DIE, 0U) != 0)
- {
- err--;
- }
-
- if (media_erase(MEDIA_NOR, MEDIA_ERASE_DIE, 1U) != 0)
- {
- err--;
- }
-
- return err;
-}
-
/** \} End of startup group */
diff --git a/firmware/app/tasks/startup.h b/firmware/app/tasks/startup.h
index 5c978e49..f8cec505 100644
--- a/firmware/app/tasks/startup.h
+++ b/firmware/app/tasks/startup.h
@@ -47,6 +47,7 @@
/* Status done bit position */
#define TASK_STARTUP_DONE (1U << 0)
+#define FRAM_INIT_DONE (1U << 1)
/**
* \brief Startup task handle.
diff --git a/firmware/app/tasks/system_reset.c b/firmware/app/tasks/system_reset.c
index 4533f07c..699cff8b 100644
--- a/firmware/app/tasks/system_reset.c
+++ b/firmware/app/tasks/system_reset.c
@@ -37,6 +37,7 @@
#include
#include
+#include "time_control.h"
#include "system_reset.h"
xTaskHandle xTaskSystemResetHandle;
@@ -45,12 +46,15 @@ void vTaskSystemReset(void *p)
{
(void)p;
- TickType_t reset_period_ticks = pdMS_TO_TICKS_64((TickType_t) TASK_SYSTEM_RESET_PERIOD_MS);
+ const TickType_t reset_period_ticks = pdMS_TO_TICKS_64((TickType_t) TASK_SYSTEM_RESET_PERIOD_MS);
while(1)
{
vTaskDelay(reset_period_ticks);
+ /* Saving system time to FRAM before reset */
+ (void)time_control_save_sys_time(system_get_time());
+
sys_log_print_event_from_module(SYS_LOG_INFO, TASK_SYSTEM_RESET_NAME, "Restarting the system...");
sys_log_new_line();
diff --git a/firmware/app/tasks/tasks.c b/firmware/app/tasks/tasks.c
index 5e082258..bfc12349 100644
--- a/firmware/app/tasks/tasks.c
+++ b/firmware/app/tasks/tasks.c
@@ -39,6 +39,7 @@
#include
#include
+#include
#include "tasks.h"
#include "startup.h"
@@ -60,6 +61,8 @@
#include "mem_check.h"
#include "mission_manager.h"
#include "mode_check.h"
+#include "antenna_deployment.h"
+#include "sched_tc.h"
static void create_queues(void);
@@ -248,6 +251,15 @@ void create_tasks(void)
}
#endif /* CONFIG_TASK_HEALTH_CHECK_MODE_ENABLED */
+#if defined(CONFIG_TASK_SCHED_TC_ENABLED) && (CONFIG_TASK_SCHED_TC_ENABLED == 1)
+ (void)xTaskCreate(vTaskSchedTC, TASK_SCHED_TC_NAME, TASK_SCHED_TC_STACK_SIZE, NULL, TASK_SCHED_TC_PRIORITY, &xTaskSchedTCHandle);
+
+ if (xTaskSchedTCHandle == NULL)
+ {
+ /* Error creating the Scheduled TC task */
+ }
+#endif /* CONFIG_TASK_MISSION_MANAGER_ENABLED */
+
create_queues();
create_event_groups();
}
@@ -264,7 +276,7 @@ void create_event_groups(void)
static void create_queues(void)
{
- event_queue = xQueueCreate(10U, sizeof(event_t));
+ event_queue = xQueueCreate(20U, sizeof(struct conops_event));
if (event_queue == NULL)
{
diff --git a/firmware/app/tasks/time_control.c b/firmware/app/tasks/time_control.c
index deacf949..d00a345b 100644
--- a/firmware/app/tasks/time_control.c
+++ b/firmware/app/tasks/time_control.c
@@ -59,15 +59,6 @@ xTaskHandle xTaskTimeControlHandle;
*/
static int time_control_load_sys_time(sys_time_t *tm);
-/**
- * \brief Saves a given system time to the non-volatile memory.
- *
- * \param[in] tm is the system time value to save.
- *
- * \return The status/error code.
- */
-static int time_control_save_sys_time(sys_time_t tm);
-
/**
* \brief Computes the CRC-8 of a sequence of bytes.
*
@@ -84,7 +75,7 @@ void vTaskTimeControl(void *p)
(void)p;
/* Wait startup task to finish */
- (void)xEventGroupWaitBits(task_startup_status, TASK_STARTUP_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_TIME_CONTROL_INIT_TIMEOUT_MS));
+ (void)xEventGroupWaitBits(task_startup_status, FRAM_INIT_DONE, pdFALSE, pdTRUE, pdMS_TO_TICKS(TASK_TIME_CONTROL_INIT_TIMEOUT_MS));
/* Load the last saved system time */
sys_time_t last_sys_time = 0;
@@ -168,7 +159,7 @@ static int time_control_load_sys_time(sys_time_t *tm)
return err;
}
-static int time_control_save_sys_time(sys_time_t tm)
+int time_control_save_sys_time(sys_time_t tm)
{
int err = 0;
diff --git a/firmware/app/tasks/time_control.h b/firmware/app/tasks/time_control.h
index fb926118..f4f020e6 100644
--- a/firmware/app/tasks/time_control.h
+++ b/firmware/app/tasks/time_control.h
@@ -39,6 +39,7 @@
#include
#include
+#include
#define TASK_TIME_CONTROL_NAME "Time Control" /**< Task name. */
#define TASK_TIME_CONTROL_STACK_SIZE 128 /**< Stack size in bytes. */
@@ -58,6 +59,15 @@ extern xTaskHandle xTaskTimeControlHandle;
*/
void vTaskTimeControl(void *p);
+/**
+ * \brief Saves a given system time to the non-volatile memory.
+ *
+ * \param[in] tm is the system time value to save.
+ *
+ * \return The status/error code.
+ */
+int time_control_save_sys_time(sys_time_t tm);
+
#endif /* TIME_CONTROL_H_ */
/** \} End of time_control group */
diff --git a/firmware/app/utils/mem_mng.c b/firmware/app/utils/mem_mng.c
index 5042b3fc..c8272f4e 100644
--- a/firmware/app/utils/mem_mng.c
+++ b/firmware/app/utils/mem_mng.c
@@ -121,13 +121,20 @@ void mem_mng_load_obdh_data_from_default_values(obdh_telemetry_t *tel)
tel->data.initial_hib_time_count = OBDH_PARAM_INITIAL_HIB_TIME_COUNT_DEFAULT_VAL;
tel->data.ant_deployment_executed = OBDH_PARAM_ANT_DEPLOYMENT_EXECUTED_DEFAULT_VAL;
tel->data.ant_deployment_counter = OBDH_PARAM_ANT_DEPLOYMENT_COUNTER_DEFAULT_VAL;
- tel->data.manual_mode_on = OBDH_PARAM_MANUAL_MODE_ON_DEFAULT_VAL;
+ tel->data.hibernation_on = OBDH_PARAM_HIBERNATION_ON_DEFAULT_VAL;
tel->data.main_edc = OBDH_PARAM_MAIN_EDC_DEFAULT_VAL;
tel->data.general_telemetry_on = OBDH_PARAM_GENERAL_TELEMETRY_ON_DEFAUL_VAL;
tel->data.ts_read_sensors = OBDH_PARAM_TS_READ_SENSORS_DEFAULT_VAL;
tel->data.main_payload_state = OBDH_PARAM_MAIN_PAYLOAD_STATE_DEFAULT_VAL;
tel->data.sec_payload_state = OBDH_PARAM_SEC_PAYLOAD_STATE_DEFAULT_VAL;
tel->data.ts_last_contact = OBDH_PARAM_TS_LAST_CONTACT_TIME_DEFAULT_VAL;
+ tel->data.last_tran_ev_id = OBDH_PARAM_LAST_TRAN_EV_ID_DEFAULT_VAL;
+ tel->data.ts_commission_timeout = OBDH_PARAM_TS_COMMISSION_TIMEOUT_DEFAULT_VAL;
+ tel->data.eps_beacon_on = OBDH_PARAM_EPS_BEACON_ON_DEFAULT_VAL;
+ tel->data.batt_crit_level_mv = OBDH_PARAM_BATT_CRITICAL_LEVEL_MV_DEFAULT_VAL;
+ tel->data.manual_experiments = OBDH_PARAM_MANUAL_EXPERIMENT_ON_DEFAUL_VAL;
+ tel->data.tc_queue_size = OBDH_PARAM_TC_QUEUE_SIZE_DEFAULT_VAL;
+ tel->data.ts_next_sched_tc = OBDH_PARAM_TS_NEXT_SCHED_TC_DEFAULT_VAL;
uint8_t buf[50] = OBDH_PARAM_POSITION_BIN_TLE_DEFAULT_VAL;
@@ -192,6 +199,20 @@ int mem_mng_load_obdh_data_from_fram(obdh_telemetry_t *tel)
int mem_mng_write_data_to_flash_page(uint8_t *data, uint32_t *page, uint32_t page_size, uint32_t start_page, uint32_t end_page)
{
int err = -1;
+ (void)start_page;
+
+ if ((*page) > end_page)
+ {
+ sys_log_print_event_from_module(SYS_LOG_INFO, MEM_MNG_NAME, "Module sector will overflow! Cleaning memory to avoid corruption...");
+ sys_log_new_line();
+
+ uint8_t retry_count = 5U;
+
+ do
+ {
+ err = mem_mng_erase_flash(&sat_data_buf.obdh);
+ } while ((err < 0) && (retry_count > 0U));
+ }
if (media_write(MEDIA_NOR, (*page) * page_size, data, page_size) == 0)
{
@@ -199,11 +220,6 @@ int mem_mng_write_data_to_flash_page(uint8_t *data, uint32_t *page, uint32_t pag
(*page)++; // cppcheck-suppress misra-c2012-17.8
- if (*page > end_page)
- {
- *page = start_page;
- }
-
portEXIT_CRITICAL();
err = 0;
@@ -235,7 +251,7 @@ int mem_mng_load_obdh_data_bak(obdh_telemetry_t *tel)
{
int err = -1;
- uintptr_t base_addr = CONFIG_MEM_ADR_SYS_PARAM_BAK;
+ const uintptr_t base_addr = CONFIG_MEM_ADR_SYS_PARAM_BAK;
uint8_t buf[BAK_DATA_SIZE + 2U];
for (uint8_t i = 0U; i < BAK_DATA_SIZE + 2U; ++i)
@@ -292,6 +308,51 @@ int mem_mng_erase_flash(obdh_telemetry_t *tel)
return err;
}
+int mem_mng_load_tc_queue_from_fram(struct conops_cmd_queue *queue)
+{
+ int err = -1;
+
+ uint8_t sys_par[sizeof(*queue) + 1U];
+
+ if (media_read(MEDIA_FRAM, CONFIG_MEM_ADR_TC_QUEUE, sys_par, (sizeof(*queue) + 1U)) == 0)
+ {
+ if (crc_is_valid(sys_par, sizeof(*queue), sys_par[sizeof(*queue)]))
+ {
+ (void)memcpy((void*)queue, sys_par, sizeof(*queue));
+ err = 0;
+ }
+ else
+ {
+ sys_log_print_event_from_module(SYS_LOG_ERROR, MEM_MNG_NAME, "TC queue CRC wasn't valid!");
+ sys_log_new_line();
+ }
+ }
+
+ return err;
+}
+
+int mem_mng_save_tc_queue_to_fram(struct conops_cmd_queue *queue)
+{
+ int err = -1;
+
+ uint8_t buf[sizeof(*queue) + 1U];
+
+ queue->queue_lock(queue->lock);
+
+ (void)memcpy(buf, (void*)queue, sizeof(*queue));
+
+ queue->queue_unlock(queue->lock);
+
+ buf[sizeof(*queue)] = crc8(buf, sizeof(*queue));
+
+ if (media_write(MEDIA_FRAM, CONFIG_MEM_ADR_TC_QUEUE, buf, (sizeof(*queue) + 1U)) == 0)
+ {
+ err = 0;
+ }
+
+ return err;
+}
+
static uint8_t crc8(uint8_t *data, uint8_t len)
{
uint8_t crc = CRC8_INITIAL_VAL;
diff --git a/firmware/app/utils/mem_mng.h b/firmware/app/utils/mem_mng.h
index 945ec6eb..812e2082 100644
--- a/firmware/app/utils/mem_mng.h
+++ b/firmware/app/utils/mem_mng.h
@@ -39,6 +39,7 @@
#define MEM_MNG_H_
#include
+#include
#include
@@ -148,6 +149,24 @@ void mem_mng_reset_page_count(media_data_t *media);
*/
int mem_mng_erase_flash(obdh_telemetry_t *tel);
+/**
+ * \brief Loads the scheduled telecommands queue from FRAM.
+ *
+ * \param[in] queue is a pointer to store the read data.
+ *
+ * \return The status/error code.
+ */
+int mem_mng_load_tc_queue_from_fram(struct conops_cmd_queue *queue);
+
+/**
+ * \brief Saves the scheduled telecommands queue to FRAM.
+ *
+ * \param[in] queue is the Scheduled TC queue to be saved.
+ *
+ * \return The status/error code.
+ */
+int mem_mng_save_tc_queue_to_fram(struct conops_cmd_queue *queue);
+
#endif /* MEM_MNG_H_ */
/** \} End of mem_mng group */
diff --git a/firmware/config/config.h b/firmware/config/config.h
index 6a36f2d4..f4f222fe 100644
--- a/firmware/config/config.h
+++ b/firmware/config/config.h
@@ -46,7 +46,7 @@
#define CONFIG_TASK_HEARTBEAT_ENABLED 1
#define CONFIG_TASK_SYSTEM_RESET_ENABLED 1
#define CONFIG_TASK_READ_SENSORS_ENABLED 1
-#define CONFIG_TASK_GENERAL_TELEMETRY_ENABLED 0
+#define CONFIG_TASK_GENERAL_TELEMETRY_ENABLED 1
#define CONFIG_TASK_TIME_CONTROL_ENABLED 1
#define CONFIG_TASK_READ_EDC_ENABLED 1
#define CONFIG_TASK_READ_EPS_ENABLED 1
@@ -55,10 +55,11 @@
#define CONFIG_TASK_DATA_LOG_ENABLED 1
#define CONFIG_TASK_PROCESS_TC_ENABLED 1
#define CONFIG_TASK_ANTENNA_DEPLOYMENT_ENABLED 0
-#define CONFIG_TASK_POSITION_DETERMINATION_ENABLED 1
+#define CONFIG_TASK_POSITION_DETERMINATION_ENABLED 0
#define CONFIG_TASK_PAYLOAD_X_ENABLED 1
#define CONFIG_TASK_HOUSEKEEPING_ENABLED 1
#define CONFIG_TASK_MISSION_MANAGER_ENABLED 1
+#define CONFIG_TASK_SCHED_TC_ENABLED 1
#define CONFIG_TASK_HEALTH_CHECK_MEM_ENABLED 0
#define CONFIG_TASK_HEALTH_CHECK_MODE_ENABLED 0
@@ -85,6 +86,7 @@
/* Debug and log messages */
#define CONFIG_DRIVERS_DEBUG_ENABLED 0
+#define CONFIG_PRINT_OBDH_PARAMS 1
#define CONFIG_SATELLITE_CALLSIGN "PY0EFS"
@@ -101,6 +103,7 @@
#define CONFIG_MEM_ADR_INIT_WORD 0
#define CONFIG_MEM_ADR_SYS_TIME 256
#define CONFIG_MEM_ADR_SYS_PARAM 512
+#define CONFIG_MEM_ADR_TC_QUEUE 1024
#define CONFIG_MEM_INIT_WORD {228, 80, 142, 227, 77, 121, 176, 244}
#define CONFIG_MEM_OBDH_DATA_START_PAGE 0U
#define CONFIG_MEM_OBDH_DATA_END_PAGE 56999U
diff --git a/firmware/config/keys.h b/firmware/config/keys.h
index 0ed6d8c1..414210b4 100644
--- a/firmware/config/keys.h
+++ b/firmware/config/keys.h
@@ -51,11 +51,12 @@
#define CONFIG_TC_KEY_DEACTIVATE_PAYLOAD_PAYLOAD_X "fna%&wM|Y(wIF32J"
#define CONFIG_TC_KEY_ERASE_MEMORY "C:8RkJE${^>%wYVR"
#define CONFIG_TC_KEY_FORCE_RESET "@A)Z-t(x+@nDHpKF"
-#define CONFIG_TC_KEY_GET_PAYLOAD_DATA "BkN&a):^fr(@(5x?"
+#define CONFIG_TC_KEY_GET_SUBSYSTEM_TABLE "BkN&a):^fr(@(5x?"
#define CONFIG_TC_KEY_SET_PARAMETER "x&veg;r[y{z{{T;7"
#define CONFIG_TC_KEY_GET_PARAMETER "EB'YThpxu7,yla,m"
#define CONFIG_TC_KEY_UPDATE_TLE "LJ(@y#xd7%@|#@;g" // cppcheck-suppress misra-c2012-20.10
#define CONFIG_TC_KEY_TRANSMIT_PACKET "($%87<#{E:?Gwd3*" // cppcheck-suppress misra-c2012-20.10
+#define CONFIG_TC_KEY_SCHEDULE_TC "iT>&H);^f)(|1y?C"
#endif /* KEYS_H_ */
diff --git a/firmware/devices/payload/payload.c b/firmware/devices/payload/payload.c
index 37481d79..b0d38bf8 100644
--- a/firmware/devices/payload/payload.c
+++ b/firmware/devices/payload/payload.c
@@ -300,7 +300,7 @@ int payload_write_cmd(payload_t pl, payload_cmd_t cmd)
{
case PAYLOAD_EDC_0:
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, PAYLOAD_MODULE_NAME, "EDC 0: ");
+ sys_log_print_event_from_module(SYS_LOG_INFO, PAYLOAD_MODULE_NAME, "EDC 0: ");
sys_log_print_hex(cmd);
sys_log_print_msg(" command received!");
sys_log_new_line();
@@ -340,7 +340,7 @@ int payload_write_cmd(payload_t pl, payload_cmd_t cmd)
}
case PAYLOAD_EDC_1:
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, PAYLOAD_MODULE_NAME, "EDC 1: ");
+ sys_log_print_event_from_module(SYS_LOG_INFO, PAYLOAD_MODULE_NAME, "EDC 1: ");
sys_log_print_hex(cmd);
sys_log_print_msg(" command received!");
sys_log_new_line();
diff --git a/firmware/devices/ttc/ttc.h b/firmware/devices/ttc/ttc.h
index 4887c25f..8c41f253 100644
--- a/firmware/devices/ttc/ttc.h
+++ b/firmware/devices/ttc/ttc.h
@@ -45,7 +45,7 @@
#define TTC_MODULE_NAME "TTC"
-#define TTC_MAX_FAILED_PACKETS 5U
+#define TTC_MAX_FAILED_PACKETS 2U
/**
* \brief TTC configuration parameters.
diff --git a/firmware/drivers/sl_ttc2/sl_ttc2.c b/firmware/drivers/sl_ttc2/sl_ttc2.c
index 4518d3f6..39b55c79 100644
--- a/firmware/drivers/sl_ttc2/sl_ttc2.c
+++ b/firmware/drivers/sl_ttc2/sl_ttc2.c
@@ -310,8 +310,10 @@ int sl_ttc2_read_reg(sl_ttc2_config_t *config, uint8_t adr, uint32_t *val)
}
else
{
- sys_log_print_event_from_module(SYS_LOG_ERROR, SL_TTC2_MODULE_NAME, "Received invalid CRC!");
- sys_log_new_line();
+ #if defined(CONFIG_DRIVERS_DEBUG_ENABLED) && (CONFIG_DRIVERS_DEBUG_ENABLED == 1)
+ sys_log_print_event_from_module(SYS_LOG_ERROR, SL_TTC2_MODULE_NAME, "Received invalid CRC!");
+ sys_log_new_line();
+ #endif /* CONFIG_DRIVERS_DEBUG_ENABLED */
}
}
else
diff --git a/firmware/drivers/sl_ttc2/sl_ttc2.h b/firmware/drivers/sl_ttc2/sl_ttc2.h
index 8a907eaa..2a75098c 100644
--- a/firmware/drivers/sl_ttc2/sl_ttc2.h
+++ b/firmware/drivers/sl_ttc2/sl_ttc2.h
@@ -54,7 +54,7 @@
/* TTC 2.0 Protocol timing */
#define SL_TTC2_TRANSACTION_DELAY_MS 110U /**< TTC 2.0 protocol transaction delay. */
-#define SL_TTC2_EXTRA_MUTEX_DELAY_MS 0U /**< Delay after transaction, used to give TTC 2.0 more time to process next request. */
+#define SL_TTC2_EXTRA_MUTEX_DELAY_MS 100U /**< Delay after transaction, used to give TTC 2.0 more time to process next request. */
/* TTC 2.0 Preamble byte */
#define SL_TTC2_PKT_PREAMBLE 0x7EU /**< Preamble byte value. */