1- /**
2- * @author Sasha Luchyn + Michael Dalva
3- * @date 2024-09-11
4- *
5- * Task to parse incoming bitstream and allocate data for according tasks
6- */
7-
8- /* How to add new command (using an example of some task1")
9- 1. add a mnemonic code for the command
10- eg: #define COMMAND1_ID 1
11-
12- 2. create or choose an existing data structure for this command. Define it in
13- the packet.h file. eg: struct TASK1_DATA_STRUCT_FORMAT
14-
15- 3. create a queue in the slate.h file
16- eg: queue_t task1_data;
17-
18- 4. create a struct for a new command
19- eg: struct TASK1_DATA_STRUCT_FORMAT current_data_holder_task1;
20-
21- 5. initialize queue in the command_switch_task_init
22- eg: queue_init(&slate->task1_data, sizeof(current_data_holder_task1),
23- TASK1_QUEUE_LENGTH);
24-
25- *note the TASK1_QUEUE_LENGTH is the length of the queu, in other words
26- how many calls for that command can be queued simultaniously*
27-
28-
29- 6. add a case to the switch case in command_switch_dispatch
30- eg:
31- case COMMAND1_ID:{
32- struct TASK1_DATA_STRUCT_FORMAT task;
33- uint16_t task_size = sizeof(task);
34- parse_packets_as_command(slate, task_size, COMMAND1_ID,
35- &slate->task1_data); }break;
36-
37-
38- 7. All set! (hopefully)
39- */
40-
41- #include "command_task.h"
42- #include "macros.h"
43- #include "packet.h"
44- #include "pico/stdlib.h"
45- #include "slate.h"
46-
47- const int RADIO_PACKETS_OUT_MAX_LENGTH = 64 ; // max radio queue length
48- const int COMMAND_MNEMONIC_BYTE_SIZE =
49- 1 ; // how many bytes are used to identify the command
50- const int TASK1_QUEUE_LENGTH = 32 ; // max queue length for task 1
51-
52- #define PACKET_BYTE_LENGTH 251 // in bytes TODO check?/ get from driver mod?
53- #define STOP_BYTE \
54- 255 // stop byte is added on the last transmission of the packet (everything
55- // afterwards is disregarded in that packet)
56- #define COMMAND1_ID 1
57- #define COMMAND2_ID 2
58-
59- // in the end, we should replace these with just the size of the structs for
60- // each command, that way we don't need to create random structs just to get the
61- // size.
62- TASK1_DATA current_data_holder_task1 ;
63- TASK2_DATA current_data_holder_task2 ;
64-
65- /// @brief Initialize the command switch task
66- /// @param slate Address of the slate
67- void command_task_init (slate_t * slate )
68- {
69- // initialize queue for radio input data,TODO: assumed to be initialized in
70- // the radio module and comment out when merging
71- queue_init (& slate -> rx_queue , PACKET_BYTE_LENGTH * sizeof (uint8_t ),
72- RADIO_PACKETS_OUT_MAX_LENGTH );
73-
74- // Initialize queues for storing processed commands
75- queue_init (& slate -> task1_data , sizeof (current_data_holder_task1 ),
76- TASK1_QUEUE_LENGTH );
77- queue_init (& slate -> task2_data , sizeof (current_data_holder_task2 ),
78- TASK1_QUEUE_LENGTH );
79-
80- slate -> num_uploaded_bytes =
81- 0 ; // Number of bytes currently uploaded to buffer
82- slate -> packet_buffer_index = 0 ; // Index of the position in payload buffer
83- slate -> uploading_command_id = 0 ; // number of command that is currently
84- // being uploaded (0 if nothing uploading)
85- }
86-
87- /// @brief
88- /// @param slate
89- void command_task_dispatch (slate_t * slate )
90- {
91- int number_of_commands_to_process = 1 ;
92- for (int i = 0 ; i < number_of_commands_to_process ; i ++ )
93- {
94-
95- // This packet will store what is currently up next in the radio receive
96- // queue
97- packet_t packet ;
98-
99- // Peek at the upcoming item in the radio receive queue
100- bool successful_peek = queue_try_remove (& slate -> rx_queue , & packet );
101-
102- if (successful_peek )
103- {
104- if (!is_packet_authenticated (& packet , slate -> reboot_counter ))
105- {
106- // Packet is not authenticated, drop it
107- LOG_ERROR ("Packet authentication failed. Dropping packet." );
108- continue ;
109- }
110-
111- /**
112- * Update the command ID depending on if it was previously
113- * uploading. If previously not loading (command id == 0) then reset
114- * the task byte size.
115- */
116- uint8_t command_id = packet .data [0 ];
117- LOG_INFO ("Command ID Recieved: %i" , command_id );
118-
119- /**
120- * Pass specific structs and taks queues appropriate for each
121- * command
122- */
123- switch (command_id )
124- {
125- // COMMAND_ID NEED TO START FROM 1 BECAUSE 0 IS BEING USED AS
126- // THE "NOT UPLOADING" INDEX
127- case COMMAND1_ID :
128- {
129- TASK1_DATA task ;
130- memcpy (& task , packet .data + 1 , sizeof (task ));
131- queue_try_add (& slate -> task1_data , & task );
132- LOG_INFO ("struct 1: %i, %i" , task );
133- }
134- break ;
135- case COMMAND2_ID :
136- {
137- TASK2_DATA task ;
138- memcpy (& task , packet .data + 1 , sizeof (task ));
139- queue_try_add (& slate -> task2_data , & task );
140- LOG_INFO ("struct 2: %i, %i" , task .number , task .yes_no );
141- }
142- break ;
143- default :
144- break ;
145- }
146- }
147- }
148- }
149-
150- sched_task_t command_task = {.name = "command" ,
151- .dispatch_period_ms = 100 ,
152- .task_init = & command_task_init ,
153- .task_dispatch = & command_task_dispatch ,
154- /* Set to an actual value on init */
155- .next_dispatch = 0 };
1+ /**
2+ * @author Thomas Haile
3+ * @date 2025-05-24
4+ *
5+ * Task management for command processing
6+ */
7+
8+ #include "command_task.h"
9+ #include "command_parser.h"
10+ #include "macros.h"
11+ #include "pico/stdlib.h"
12+ #include "slate.h"
13+
14+ #define PACKET_BYTE_LENGTH 251 // in bytes TODO check?/ get from driver mod?
15+
16+ const int RADIO_PACKETS_OUT_MAX_LENGTH = 64 ;
17+ const int PAYLOAD_DATA_CAPACITY = 32 ;
18+
19+ /// @brief Initialize the command switch task
20+ /// @param slate Slate
21+ void command_task_init (slate_t * slate )
22+ {
23+ // Initialize queue for radio input data
24+ queue_init (& slate -> rx_queue , PACKET_BYTE_LENGTH * sizeof (uint8_t ),
25+ RADIO_PACKETS_OUT_MAX_LENGTH );
26+
27+ // Initialize queues for storing processed commands
28+ queue_init (& slate -> payload_command_data , sizeof (PAYLOAD_COMMAND_DATA ),
29+ PAYLOAD_DATA_CAPACITY );
30+
31+ slate -> num_uploaded_bytes = 0 ;
32+ slate -> packet_buffer_index = 0 ;
33+ slate -> uploading_command_id = 0 ;
34+ slate -> number_commands_processed = 0 ;
35+ }
36+
37+ /// @brief Process incoming radio packets and dispatch commands
38+ void command_task_dispatch (slate_t * slate )
39+ {
40+ packet_t packet ;
41+
42+ // Process one packet per dispatch cycle
43+ if (queue_try_remove (& slate -> rx_queue , & packet ))
44+ {
45+ if (!is_packet_authenticated (& packet , slate -> reboot_counter ))
46+ {
47+ LOG_ERROR ("Packet authentication failed. Dropping packet." );
48+ return ;
49+ }
50+
51+ // Parse and process the command
52+ dispatch_command (slate , & packet );
53+ }
54+ }
55+
56+ sched_task_t command_task = {.name = "command" ,
57+ .dispatch_period_ms = 100 ,
58+ .task_init = & command_task_init ,
59+ .task_dispatch = & command_task_dispatch ,
60+ .next_dispatch = 0 };
0 commit comments