IRPyro messaging application
Communications program between IRPyro and IRPyro evaluation tool
message_unpack.c
Go to the documentation of this file.
1 /**
2 ******************************************************************************
3 * @file message_unpack.c
4 * @author _KEMET, Ltd
5 * @date March 2018
6 * @version Release 1.0.6
7 * @copyright (c) 2018 _KEMET, Ltd
8 * @brief IRPyro evaluation tool with API integration.
9 *
10 * @verbatim
11  ===============================================================================
12  ##### Description #####
13  ===============================================================================
14  [..]
15  From a stream of command bytes coming from a GUI the byte indicating a command
16  is found and broken down in it main components: wild card (sensor/ sensors to
17  be applied), payload and crc.
18  [..]
19  @endverbatim
20  ******************************************************************************
21  @attention <h2><center>&copy; COPYRIGHT 2018 _KEMET, Ltd</center></h2>
22  @verbatim
23  Copyright (c) 2018, _KEMET, Ltd
24  All rights reserved.
25 
26  THIS SOFTWARE IS PROVIDED BY _KEMET, Ltd ''AS IS'' AND ANY
27  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29  DISCLAIMED. IN NO EVENT SHALL _KEMET, Ltd BE LIABLE FOR ANY
30  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  @endverbatim
37 
38  ******************************************************************************
39  */
40 /* Includes ------------------------------------------------------------------*/
41 // #define USE_TEST_BUFFER
42 #ifndef MESSAGE_UNPACK
43 #include "message_unpack.h"
44 #endif
45 
46 /** @defgroup Message_Handler Message Handler
47  * @ingroup eevt_main
48  * @brief Packs and unpacks messages to and from the GUI
49  * @verbatim
50  *
51  * @endverbatim
52  * @note
53  * @{
54  */
55 /** @defgroup message_unpack Message Unpack
56  * @ingroup Message_Handler
57  * @brief Process a stream of bytes to find a valid GUI command
58  * @verbatim
59  *
60  * @endverbatim
61  * @note
62  * @{
63  */
64 /** @typedef decode_state_type
65 */
66 typedef enum
67 {
71  complete
73 /**
74  * @struct command_table
75  * @verbatim
76  * Individual commands have the following structure:
77  * <GUI command> ::= <cmd code> <xor validation byte>
78  * <GUI command> ::= <cmd code> <sensor address> <xor validation byte>
79  * <GUI command> ::= <cmd code> <sensor address> <payload> <xor validation byte>
80  * @endverbatim
81 */
83 {
84  uint8_t cmd_code; // unique value
85  uint8_t cmd_wildcard; // 0: no wild card. 1: sensor number or all sensors
86  uint8_t cmd_payload; // maximum number of bytes for expected payload.
87 };
88 /** @struct command_table
89  * Array with the commands recognized by the message unpack
90 */
91 static const struct command_table IRPyro_cmd[CMD_LIST_SIZE] =
92 {
93  {0x00,0x00,0x00}, // null test command
94  {0x01,0x00,0x00}, // send firmware version
95  {0x02,0x00,0x00}, // read asic version
96  {0x03,0x01,0x00}, // CCP read
97  {0x04,0x01,0x05}, // CCP write
98  {0x05,0x01,0x00}, // AFE read
99  {0x06,0x01,0x04}, // AFE write
100  {0x07,0x00,0x00}, // WUP read
101  {0x08,0x01,0x06}, // WUP write
102  {0x09,0x00,0x00}, // start streaming
103  {0x0A,0x00,0x00}, // dummy
104  {0x0B,0x00,0x00}, // dummy
105  {0x0C,0x00,0x00}, // start status
106  {0x0D,0x00,0x00}, // stop status
107  {0x0E,0x00,0x00}, // goto sleep - all sensors
108  {0x0F,0x00,0x00}, // wake up - all sensors
109  {0x10,0x00,0x00}, // reset soft - sensor
110  {0x11,0x00,0x00}, // reset hard - sensor
111  {0x12,0x00,0x00}, // reset hardware - board
112  {0x13,0x00,0x00}, // sampling rate read
113  {0x14,0x00,0x01}, // sampling rate write
114  {0x15,0x00,0x00}, // logical channels read
115  {0x16,0x00,0x07}, // logical channels write
116  {0x17,0x00,0x02}, // set emitter timings
117  {0x18,0x00,0x01}, // set emitter state
118  {0x19,0x00,0x00}, // get failure flags
119  {0x1A,0x00,0x00}, // board type read
120  {0x1B,0x00,0x00}, // unit id read
121  {0x1C,0x00,0x00}, // unit id write
122  {0x1D,0x00,0x00}, // second unit id read
123  {0x1E,0x00,0x00}, // get dark pixel state
124  {0x1F,0x00,0x00}, // set dark pixel state
125  {0x77,0x00,0x00}, // stop streaming
126  {0x21,0x00,0x00}, // report error
127  {0x22,0x00,0x00} // dummy
128 };
129 #ifdef USE_TEST_BUFFER
130 /* ----------------- BEGIN OF TEST DATA ----------------- */
131 static uint8_t byte_stream_index = 0; // for test only replace with getchar method
132 static const uint8_t byte_stream[] =
133 {
134  0x01, 0x01, 0x01
135 };
136 
137 /* ----------------- END OF TEST DATA ----------------- */
138 #endif
139 
140 #define CMD_BUFFER_SIZE 20
141 #define PAYLOAD_SIZE 7
142 
143 uint8_t cmd_completed, cmd_error, cmd_empty; // flags for the state machine
144 uint8_t cmd_input; // seed for the command byte stream
145 uint8_t cmd_search_result; // successfully decoded command code
146 uint8_t cmd_buffer[CMD_BUFFER_SIZE] = {0}; // command byte segment to process
147 uint8_t payload_array[PAYLOAD_SIZE] = {0}; // payload of the decoded command
149 uint8_t idx_buffer;
150 uint8_t max_reads;
151 uint8_t crc_calc;
154 decode_state_type next_state; // control for the state machine
155 
156 /**
157 * @brief gets a byte from the UART or the byte array
158 */
159 static uint8_t byte_get(uint8_t *output_byte)
160 {
161 #ifndef USE_TEST_BUFFER
162  get_char_result = message_getchar(output_byte);
163 #endif
164 #ifdef USE_TEST_BUFFER
165  static uint8_t byte_stream_index;
166  get_char_result = 1;
167  *output_byte = byte_stream[byte_stream_index]; // for test only replace with getchar method
168  if (byte_stream_index < sizeof(byte_stream))
169  ++byte_stream_index; // get the next byte in the test buffer
170  else
171  byte_stream_index=0;
172 #endif
173  return get_char_result;
174 }
175 /**
176 * @brief on valid crc assigns cmd_code
177 */
178 static void assign_cmd_code(void)
179 {
180  if (cmd_buffer[0] == 0x77)
181  {
182  cmd_search_result = 0x20;
183  }
184  else
185  {
187  }
190 }
191 /**
192 * @brief gets the next byte to process
193 */
194 static void process_next_byte(void)
195 {
196  ++idx_buffer;
198  if (crc_calc == cmd_input)
199  {
200  assign_cmd_code();
201  }
202  else
203  {
204  -- max_reads;
205  }
206 }
207 /**
208 * @brief process stream until crc checks or fails
209 */
210 static void process_stream(void)
211 {
212  uint8_t retries;
213  retries = 3;
215  do
216  {
218  if (get_char_result==0)
219  {
220  Micro_controller_delay_ms(10);
221  }
222  -- retries;
223  }
224  while (get_char_result == 0 && retries);
225 
226  if (get_char_result)
227  {
229  }
230  else
231  {
234  }
235 }
236 /**
237 * @brief looks for a command in the byte stream
238 */
239 static void search_for_command(void)
240 {
241  memset(cmd_buffer, 0x00, CMD_BUFFER_SIZE);
243  do
244  {
245  process_stream();
246  }
248 }
249 /**
250 * @brief On success returns a buffer with command and payload (if any)
251 * @return cmd_search_result code for the command currently in process
252 * @return cmd_buffer segment of the current byte stream with command and payload
253 * @return next_state index for the state machine
254 */
255 static void fn_decode_initialize(void)
256 {
257  cmd_completed = 0;
258  cmd_empty = 0;
259  cmd_error = 0;
260  get_char_result = 0;
261  idx_buffer = 0;
262  max_reads = 10;
263  crc_calc = 0xff; // seed crc calculation
265 
267  if (get_char_result)
268  {
270  }
271  else
272  {
273 // no command to process, do nothing
274  cmd_empty = 1;
276  }
277 }
278 /**
279 * @brief gets the payload from a command buffer array coming from the GUI
280 * @param[out] payload destination of cmd_buffer payload
281 * @param[in] cmd_buffer source byte array being decoded
282 * @param[in] cmd_tab_idx recovers the payload size from the look
283 */
284 static void payload_get( uint8_t *payload, uint8_t const *cmd_buffer, uint8_t cmd_tab_idx)
285 {
286  uint8_t payload_cnt = IRPyro_cmd[cmd_tab_idx].cmd_payload;
287  if (IRPyro_cmd[cmd_tab_idx].cmd_wildcard)
288  {
289  // +2 skips the command code plus the wild card
290  memmove(payload, cmd_buffer+2, payload_cnt);
291  }
292  else
293  {
294  // +1 skips the command code
295  memmove(payload, cmd_buffer+1, payload_cnt);
296  }
297 }
298 /**
299 * @brief fills the payload buffer if the command requires it
300 * @return payload payload buffer
301 * @return next_state index for the state machine
302 */
303 static void fn_decode_payload_get(void)
304 {
306  {
308  }
310 }
311 /**
312 * @brief sets the error flag
313 * @return cmd_error error flag
314 * @return next_state index for the state machine
315 */
316 static void fn_decode_error_report(void)
317 {
318  cmd_error = 1;
320 }
321 /**
322 * @brief sets the completion flag and the next state
323 * @return cmd_completed state machine end flag
324 * @return next_state index for the state machine
325 */
326 static void fn_decode_complete(void)
327 {
328  cmd_completed = 1;
330 }
331 /**
332 * @brief gives access to the command code and the corresponding payload (if any)
333 * @return cmd_code_result command processed successfully
334 * @return cmd_payload corresponding payload (if any)
335 */
336 void message_unpack_result(uint8_t *cmd_code_result, uint8_t *sensor_destination, uint8_t *cmd_payload)
337 {
338  *cmd_code_result = cmd_search_result;
341  {
343  }
344 }
345 /**
346 * @brief evaluates the result
347 */
348 static void decode_result_assign(void)
349 {
351  if (cmd_empty)
352  {
353  op_result = no_data;
354  }
355  if (cmd_error)
356  {
358  }
359 }
360 /**
361  * @brief FSM to decode a received command
362  * If the command is valid, the command code and the payload (if any)
363  * are made available for the caller function.
364 */
366 {
367  static void (* const pf[5])(void) =
368  {
373  };
375  do
376  {
377  (*pf[next_state])();
378  }
379  while (!cmd_completed && !cmd_error && !cmd_empty);
381  return op_result;
382 }
383 /** end of message unpack group
384  * @}
385  */
386 /** end of message_handler group
387  * @}
388  */
389 /* ********** Copyright (c) 2018 _KEMET, Ltd. **********END OF FILE************/
crc_calc
uint8_t crc_calc
Definition: message_unpack.c:151
payload_get
static void payload_get(uint8_t *payload, uint8_t const *cmd_buffer, uint8_t cmd_tab_idx)
gets the payload from a command buffer array coming from the GUI
Definition: message_unpack.c:284
fn_decode_complete
static void fn_decode_complete(void)
sets the completion flag and the next state
Definition: message_unpack.c:326
fn_decode_payload_get
static void fn_decode_payload_get(void)
fills the payload buffer if the command requires it
Definition: message_unpack.c:303
message_unpack_result
void message_unpack_result(uint8_t *cmd_code_result, uint8_t *sensor_destination, uint8_t *cmd_payload)
gives access to the command code and the corresponding payload (if any)
Definition: message_unpack.c:336
get_payload
@ get_payload
Definition: message_unpack.c:69
cmd_error
uint8_t cmd_error
Definition: message_unpack.c:143
continue_process_stream
uint8_t continue_process_stream
Definition: message_unpack.c:152
cmd_buffer
uint8_t cmd_buffer[CMD_BUFFER_SIZE]
Definition: message_unpack.c:146
message_unpack_decode
decode_result_type message_unpack_decode(void)
FSM to decode a received command If the command is valid, the command code and the payload (if any) a...
Definition: message_unpack.c:365
assign_cmd_code
static void assign_cmd_code(void)
on valid crc assigns cmd_code
Definition: message_unpack.c:178
cmd_search_result
uint8_t cmd_search_result
Definition: message_unpack.c:145
sensor_destination
uint8_t sensor_destination
Definition: main.c:297
decode_fail
@ decode_fail
Definition: message_unpack.h:39
cmd_completed
uint8_t cmd_completed
Definition: message_unpack.c:143
fn_decode_initialize
static void fn_decode_initialize(void)
On success returns a buffer with command and payload (if any)
Definition: message_unpack.c:255
max_reads
uint8_t max_reads
Definition: message_unpack.c:150
next_state
decode_state_type next_state
Definition: message_unpack.c:154
PAYLOAD_SIZE
#define PAYLOAD_SIZE
Definition: message_unpack.c:141
fn_decode_error_report
static void fn_decode_error_report(void)
sets the error flag
Definition: message_unpack.c:316
search_for_command
static void search_for_command(void)
looks for a command in the byte stream
Definition: message_unpack.c:239
payload_array
uint8_t payload_array[PAYLOAD_SIZE]
Definition: message_unpack.c:147
CMD_LIST_SIZE
#define CMD_LIST_SIZE
Definition: message_unpack.h:36
error_report
@ error_report
Definition: message_unpack.c:70
op_result
decode_result_type op_result
Definition: message_unpack.c:153
CMD_BUFFER_SIZE
#define CMD_BUFFER_SIZE
Definition: message_unpack.c:140
message_unpack.h
Decodes a byte stream from the GUI into a data structure applicable to the sensor.
get_char_result
uint8_t get_char_result
Definition: message_unpack.c:148
command_table::cmd_wildcard
uint8_t cmd_wildcard
Definition: message_unpack.c:85
cmd_input
uint8_t cmd_input
Definition: message_unpack.c:144
complete
@ complete
Definition: message_unpack.c:71
process_stream
static void process_stream(void)
process stream until crc checks or fails
Definition: message_unpack.c:210
byte_get
static uint8_t byte_get(uint8_t *output_byte)
gets a byte from the UART or the byte array
Definition: message_unpack.c:159
command_table::cmd_payload
uint8_t cmd_payload
Definition: message_unpack.c:86
command_table::cmd_code
uint8_t cmd_code
Definition: message_unpack.c:84
cmd_empty
uint8_t cmd_empty
Definition: message_unpack.c:143
initialize
@ initialize
Definition: message_unpack.c:68
decode_state_type
decode_state_type
Definition: message_unpack.c:67
IRPyro_cmd
static const struct command_table IRPyro_cmd[CMD_LIST_SIZE]
Definition: message_unpack.c:91
message_getchar
uint8_t message_getchar(uint8_t *c)
Gets a character from the receive queue.
Definition: queue_handle.c:114
command_table
Definition: message_unpack.c:83
no_data
@ no_data
Definition: message_unpack.h:41
process_next_byte
static void process_next_byte(void)
gets the next byte to process
Definition: message_unpack.c:194
decode_result_type
decode_result_type
Definition: message_unpack.h:38
decode_success
@ decode_success
Definition: message_unpack.h:40
idx_buffer
uint8_t idx_buffer
Definition: message_unpack.c:149
decode_result_assign
static void decode_result_assign(void)
evaluates the result
Definition: message_unpack.c:348