Loading...
Searching...
No Matches
debug_state.c
1/***********************************************************************************
2 * @file debug_state.c *
3 * @author Matt Ricci *
4 * @addtogroup Shell *
5 * *
6 * @{ *
7 ***********************************************************************************/
8
9#include "AustralisConfig.h"
10
11#include "FreeRTOS.h"
12#include "event_groups.h"
13#include "groups.h"
14
15#include "stdio.h"
16#include "string.h"
17
18#include "parser.h"
19#include "state.h"
20#include "shell.h"
21
22static void State_exec(UART_t *uart, char *flags);
23static void State_help(UART_t *uart);
24
25DEFINE_PROGRAM_HANDLE("state", State_exec, State_help)
26
27extern EventGroupHandle_t xTaskEnableGroup;
28
29static void State_help(UART_t *uart) {
30 uart->println(uart, "NAME:");
31 uart->println(uart, "\tstate\n");
32 uart->println(uart, "USAGE:");
33 uart->println(uart, "\tstate print <state_variable> [--repeat]");
34 uart->println(uart, "\tstate reset\n");
35 uart->println(uart, "DESCRIPTION:");
36 uart->println(uart, "\tprint");
37 uart->println(uart, "\t Print the value of a state variable to the shell output.\n");
38 uart->println(uart, "\treset");
39 uart->println(uart, "\t Reset the global state to default and clear event groups.\n");
40 uart->println(uart, "OPTIONS:");
41 uart->println(uart, "\t-r, --repeat");
42 uart->println(uart, "\t Continue to print variable until interrupted. Can only be used with `print`");
43 uart->println(uart, "\t-h, --help");
44 uart->println(uart, "\t Print this help and exit");
45}
46
47/* ============================================================================================== */
54static void State_exec(UART_t *uart, char *flags) {
55
56 ArgParser parser = ArgParser_init();
57 int argResetIdx = parser.addArg(
58 &parser, "reset", 0, ARG_TYPE_BOOL, false
59 );
60 int argPrintIdx = parser.addArg(
61 &parser, "print", 0, ARG_TYPE_STRING, false
62 );
63 int argRepeatIdx = parser.addArg(
64 &parser, "--repeat", 'r', ARG_TYPE_BOOL, false
65 );
66 int argVerboseIdx = parser.addArg(
67 &parser, "--verbose", 'v', ARG_TYPE_BOOL, false
68 );
69
70 // clang-format off
71 int mutexResetPrintIdx = parser.addMutexGroup(
72 &parser, (int[]){
73 argResetIdx,
74 argPrintIdx,
75 }, 2
76 );
77 int mutexResetRepeatIdx = parser.addMutexGroup(
78 &parser, (int[]){
79 argResetIdx,
80 argRepeatIdx,
81 }, 2
82 );
83 // clang-format on
84
85 char *tokens[MAX_ARGS];
86 int numTokens = 0;
87
88 // Tokenize the input string
89 char *token = strtok(flags, " ");
90 while (token != NULL && numTokens < MAX_ARGS) {
91 tokens[numTokens++] = token;
92 token = strtok(NULL, " ");
93 }
94
95 // Parse input tokens
96 parser.parseArgs(&parser, numTokens, tokens);
97
98 // Early exit with error message
99 if (parser.error.status == PARSER_STATUS_ERROR) {
100 uart->println(uart, parser.error.msg);
101 return;
102 }
103
104 // Reset state variables to initial value
105 if (parser.args[argResetIdx].provided) {
106 xEventGroupClearBits(xTaskEnableGroup, 0xFF);
107 uart->println(uart, "Reset state parameters.");
108 State_init();
109 }
110
111 // Print requested state variable value
112 if (parser.args[argPrintIdx].provided) {
113 char *value = parser.args[argPrintIdx].value;
114 State *state = State_getState();
115
116 char *terminal = (parser.args[argRepeatIdx].provided) ? "\r" : "\r\n";
117 char str[50];
118
119 REPEAT:
120 // Print `flightState` state variable
121 if (!strcmp(value, "flightState")) {
122 switch (state->flightState) {
123 case PRELAUNCH:
124 snprintf(str, sizeof(str), "State: PRELAUNCH%s", terminal);
125 break;
126 case LAUNCH:
127 snprintf(str, sizeof(str), "State: LAUNCH%s", terminal);
128 break;
129 case COAST:
130 snprintf(str, sizeof(str), "State: COAST%s", terminal);
131 break;
132 case APOGEE:
133 snprintf(str, sizeof(str), "State: APOGEE%s", terminal);
134 break;
135 case DESCENT:
136 snprintf(str, sizeof(str), "State: DESCENT%s", terminal);
137 break;
138 }
139 }
140
141 // Print `altitude` state variable
142 else if (!strcmp(value, "altitude")) {
143 snprintf(
144 str, sizeof(str), "Altitude: %fm%s",
145 state->altitude,
146 terminal
147 );
148 }
149
150 // Print `velocity` state variable
151 else if (!strcmp(value, "velocity")) {
152 snprintf(
153 str, sizeof(str), "Velocity: %fm/(s^2)%s",
154 state->velocity,
155 terminal
156 );
157 }
158
159 // Print `tilt` state variable
160 else if (!strcmp(value, "tilt")) {
161 snprintf(
162 str, sizeof(str), "Tilt: %f degrees%s",
163 state->tilt,
164 terminal
165 );
166 }
167
168 // Print `flightTimeMs` state variable
169 else if (!strcmp(value, "flightTimeMs")) {
170 snprintf(
171 str, sizeof(str), "Flight time: %ums / %fs%s",
172 state->flightTimeMs,
173 state->flightTimeMs / 1000.0f,
174 terminal
175 );
176 }
177
178 // Requested state variable not found
179 else {
180 snprintf(str, sizeof(str), "Error: `%s` is not a state variable\n", value);
181 }
182
183 // Repeat if flag is set
184 if (parser.args[argVerboseIdx].provided) {
185 // Print timestamp
186 char timestamp[20];
187 snprintf(
188 timestamp, sizeof(timestamp), "[t=%fs] ",
189 state->flightTimeMs / 1000.0f
190 );
191 uart->print(uart, timestamp);
192 }
193
194 // Print resulting output
195 uart->print(uart, str);
196
197 // Continue until interrupted if specified
198 if (parser.args[argRepeatIdx].provided)
199 goto REPEAT;
200 }
201}
202
void State_init()
Definition state.c:45
State * State_getState()
Definition state.c:69
@ APOGEE
At least 2: velocity negative, pressure increasing, tilt > 90 degrees.
Definition state.h:28
@ PRELAUNCH
Initial boot condition.
Definition state.h:25
@ LAUNCH
Body reference Z-axis acceleration above threshold.
Definition state.h:26
@ COAST
Global reference Z-axis velocity decreasing.
Definition state.h:27
@ DESCENT
Altitude below main threshold.
Definition state.h:29
State variable struct.
Definition state.h:36
Struct definition for UART interface.
Definition uart.h:132