33 PX_C1098_STATE_DONE = 0,
35 PX_C1098_STATE_WAIT_ACK,
36 PX_C1098_STATE_WAIT_AFTER_ACK,
38 PX_C1098_STATE_SYNC_WAIT_ACK,
39 PX_C1098_STATE_SYNC_WAIT_SYNC,
40 PX_C1098_STATE_GET_PIC_WAIT_ACK,
41 PX_C1098_STATE_WAIT_DATA_LENGTH,
42 PX_C1098_STATE_WAIT_DATA_PACKAGE,
61 uint8_t data_size_lo8;
62 uint8_t data_size_hi8;
63 uint8_t image_data[PX_C1098_DATA_BLOCK_SIZE];
64 uint8_t verify_code_lo8;
65 uint8_t verify_code_hi8;
68#define PX_C1098_RX_DATA_BUFFER_SIZE 256
71#define PX_C1098_START 0xaa
74#define PX_C1098_ID_INITIAL 0x01
75#define PX_C1098_ID_GET_PICTURE 0x04
76#define PX_C1098_ID_SNAPSHOT 0x05
77#define PX_C1098_ID_SET_PACKAGE_SIZE 0x06
78#define PX_C1098_ID_RESET 0x08
79#define PX_C1098_ID_DATA_LENGTH 0x0a
80#define PX_C1098_ID_SYNC 0x0d
81#define PX_C1098_ID_ACK 0x0e
82#define PX_C1098_ID_NAK 0x0f
90static px_c1098_state_t px_c1098_state;
94static uint8_t px_c1098_retry_cntr;
103static uint16_t px_c1098_rx_data_index;
105static uint32_t px_c1098_data_length;
106static uint16_t px_c1098_package_id;
111const char * px_c1098_state_to_str(px_c1098_state_t state)
115 case PX_C1098_STATE_DONE:
return "DONE");
116 case PX_C1098_STATE_ERROR:
return "ERROR");
117 case PX_C1098_STATE_WAIT_ACK:
return "WAIT_ACK");
118 case PX_C1098_STATE_WAIT_AFTER_ACK:
return "WAIT_AFTER_ACK");
119 case PX_C1098_STATE_SYNC:
return "SYNC");
120 case PX_C1098_STATE_SYNC_WAIT_ACK:
return "SYNC_WAIT_ACK");
121 case PX_C1098_STATE_SYNC_WAIT_SYNC:
return "SYNC_WAIT_SYNC");
122 case PX_C1098_STATE_GET_PIC_WAIT_ACK:
return "GET_PIC_WAIT_ACK");
123 case PX_C1098_STATE_WAIT_DATA_LENGTH:
return "WAIT_DATA_LENGTH");
124 case PX_C1098_STATE_WAIT_DATA_PACKAGE:
return "WAIT_DATA_PACKAGE");
125 default:
return "???");
128static void px_c1098_tx_data(uint8_t * data, uint8_t nr_of_bytes)
130 while(nr_of_bytes != 0)
137static void px_c1098_tx_cmd(uint8_t
id,
143 px_c1098_tx_cmd_packet.start = PX_C1098_START;
144 px_c1098_tx_cmd_packet.id = id;
145 px_c1098_tx_cmd_packet.param1 = param1;
146 px_c1098_tx_cmd_packet.param2 = param2;
147 px_c1098_tx_cmd_packet.param3 = param3;
148 px_c1098_tx_cmd_packet.param4 = param4;
150 PX_LOG_D(
"TX %02X %02X %02X %02X %02X %02X", px_c1098_tx_cmd_packet.start,
151 px_c1098_tx_cmd_packet.id,
152 px_c1098_tx_cmd_packet.param1,
153 px_c1098_tx_cmd_packet.param2,
154 px_c1098_tx_cmd_packet.param3,
155 px_c1098_tx_cmd_packet.param4);
157 px_c1098_tx_data((uint8_t *)&px_c1098_tx_cmd_packet,
sizeof(px_c1098_tx_cmd_packet));
160static void px_c1098_change_state(px_c1098_state_t new_state)
163 px_c1098_state = new_state;
165 px_c1098_rx_data_index = 0;
169 px_c1098_state_to_str(px_c1098_state));
172static void px_c1098_ack_data_package(
void)
175 px_c1098_tx_cmd(PX_C1098_ID_ACK, 0x00, 0x00,
PX_U16_LO8(px_c1098_package_id),
178 px_c1098_change_state(PX_C1098_STATE_WAIT_DATA_PACKAGE);
181static bool px_c1098_package_data_checksum_ok(uint16_t data_size)
183 uint16_t checksum = 0;
186 for(i = 0; i < (data_size + 4); i++)
188 checksum += px_c1098_rx_packet.data[i];
191 if( (px_c1098_rx_packet.data[i] ==
PX_U16_LO8(checksum))
192 &&(px_c1098_rx_packet.data[i + 1] == 0x00 ) )
202static void px_c1098_on_rx_byte(uint8_t data)
208 if(px_c1098_rx_data_index == 0)
219 if(px_c1098_rx_data_index >=
sizeof(px_c1098_rx_packet))
225 px_c1098_rx_packet.data[px_c1098_rx_data_index++] = data;
227 if( (px_c1098_state != PX_C1098_STATE_WAIT_DATA_PACKAGE)
229 &&(px_c1098_rx_packet.cmd.start == PX_C1098_START ) )
232 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_NAK)
233 &&(px_c1098_rx_packet.cmd.param4 == 0x00 ) )
236 px_c1098_change_state(PX_C1098_STATE_ERROR);
240 switch(px_c1098_state)
242 case PX_C1098_STATE_WAIT_ACK:
243 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_ACK )
244 &&(px_c1098_rx_packet.cmd.param1 == px_c1098_tx_cmd_packet.id)
245 &&(px_c1098_rx_packet.cmd.param3 == 0x00 )
246 &&(px_c1098_rx_packet.cmd.param4 == 0x00 ) )
248 if(px_c1098_delay_after_ack_in_ticks != 0)
250 px_systmr_start(&px_c1098_state_tmr, px_c1098_delay_after_ack_in_ticks);
251 px_c1098_change_state(PX_C1098_STATE_WAIT_AFTER_ACK);
255 px_c1098_change_state(PX_C1098_STATE_DONE);
260 case PX_C1098_STATE_SYNC_WAIT_ACK:
261 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_ACK )
262 &&(px_c1098_rx_packet.cmd.param1 == PX_C1098_ID_SYNC)
263 &&(px_c1098_rx_packet.cmd.param3 == 0x00 )
264 &&(px_c1098_rx_packet.cmd.param4 == 0x00 ) )
266 px_c1098_change_state(PX_C1098_STATE_SYNC_WAIT_SYNC);
270 case PX_C1098_STATE_SYNC_WAIT_SYNC:
271 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_SYNC)
272 &&(px_c1098_rx_packet.cmd.param1 == 0x00 )
273 &&(px_c1098_rx_packet.cmd.param2 == 0x00 )
274 &&(px_c1098_rx_packet.cmd.param3 == 0x00 )
275 &&(px_c1098_rx_packet.cmd.param4 == 0x00 ) )
278 px_c1098_tx_cmd(PX_C1098_ID_ACK, 0x00, 0x00, 0x00, 0x00);
279 px_c1098_change_state(PX_C1098_STATE_DONE);
284 case PX_C1098_STATE_GET_PIC_WAIT_ACK:
285 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_ACK )
286 &&(px_c1098_rx_packet.cmd.param1 == px_c1098_tx_cmd_packet.id)
287 &&(px_c1098_rx_packet.cmd.param3 == 0x00 )
288 &&(px_c1098_rx_packet.cmd.param4 == 0x00 ) )
290 px_c1098_change_state(PX_C1098_STATE_WAIT_DATA_LENGTH);
294 case PX_C1098_STATE_WAIT_DATA_LENGTH:
295 if( (px_c1098_rx_packet.cmd.id == PX_C1098_ID_DATA_LENGTH)
296 &&(px_c1098_rx_packet.cmd.param1 == 0x01 ) )
299 px_c1098_rx_packet.cmd.param4,
300 px_c1098_rx_packet.cmd.param3,
301 px_c1098_rx_packet.cmd.param2);
302 PX_LOG_D(
"Data Length = %u bytes", px_c1098_data_length);
303 px_c1098_ack_data_package();
312 if(px_c1098_rx_data_index < 4)
317 if( (px_c1098_rx_packet.package_data.id_hi8 !=
PX_U16_HI8(px_c1098_package_id))
318 ||(px_c1098_rx_packet.package_data.id_lo8 !=
PX_U16_LO8(px_c1098_package_id)) )
324 px_c1098_rx_packet.package_data.data_size_lo8);
326 if(data_size > PX_C1098_DATA_BLOCK_SIZE)
330 if(data_size != PX_C1098_DATA_BLOCK_SIZE)
332 if(data_size != px_c1098_data_length)
338 if(px_c1098_rx_data_index < (data_size+6))
343 if(!px_c1098_package_data_checksum_ok(data_size))
349 (*px_c1098_on_rx_data)(px_c1098_rx_packet.package_data.image_data, data_size);
351 if(px_c1098_data_length == data_size)
353 px_c1098_data_length = 0;
355 px_c1098_change_state(PX_C1098_STATE_DONE);
359 px_c1098_data_length -= data_size;
360 PX_LOG_D(
"Data Length = %u", px_c1098_data_length);
362 px_c1098_package_id++;
364 px_c1098_retry_cntr = 3;
366 px_c1098_ack_data_package();
374 px_c1098_uart_handle = handle;
375 px_c1098_state = PX_C1098_STATE_DONE;
376 px_c1098_on_rx_data =
NULL;
377 px_c1098_rx_data_index = 0;
378 px_c1098_delay_after_ack_in_ticks = 0;
382void px_c1098_task(
void)
389 px_c1098_on_rx_byte(data);
392 switch(px_c1098_state)
394 case PX_C1098_STATE_WAIT_ACK:
396 case PX_C1098_STATE_GET_PIC_WAIT_ACK:
398 case PX_C1098_STATE_WAIT_DATA_LENGTH:
403 px_c1098_change_state(PX_C1098_STATE_ERROR);
407 case PX_C1098_STATE_WAIT_DATA_PACKAGE:
412 if(px_c1098_retry_cntr > 0)
415 px_c1098_retry_cntr--;
416 px_c1098_ack_data_package();
421 px_c1098_change_state(PX_C1098_STATE_ERROR);
426 case PX_C1098_STATE_WAIT_AFTER_ACK:
431 px_c1098_change_state(PX_C1098_STATE_DONE);
435 case PX_C1098_STATE_SYNC:
437 px_c1098_tx_cmd(PX_C1098_ID_SYNC, 0x00, 0x00, 0x00, 0x00);
441 px_c1098_change_state(PX_C1098_STATE_SYNC_WAIT_ACK);
444 case PX_C1098_STATE_SYNC_WAIT_ACK:
449 if(px_c1098_retry_cntr > 0)
452 px_c1098_retry_cntr--;
453 px_c1098_change_state(PX_C1098_STATE_SYNC);
458 px_c1098_change_state(PX_C1098_STATE_ERROR);
468bool px_c1098_busy(
void)
470 if( (px_c1098_state != PX_C1098_STATE_DONE )
471 &&(px_c1098_state != PX_C1098_STATE_ERROR) )
481bool px_c1098_error(
void)
483 if(px_c1098_state == PX_C1098_STATE_ERROR)
492bool px_c1098_task_execute(
void)
494 while(px_c1098_busy())
499 return px_c1098_error();
502void px_c1098_initial(uint8_t if_speed, uint8_t jpeg_res)
506 px_c1098_tx_cmd(PX_C1098_ID_INITIAL, if_speed, 0x07, 0x00, jpeg_res);
512 px_c1098_change_state(PX_C1098_STATE_WAIT_ACK);
515void px_c1098_set_package_size(
void)
519 px_c1098_tx_cmd(PX_C1098_ID_SET_PACKAGE_SIZE, 0x08,
PX_U16_LO8(PX_C1098_DATA_BLOCK_SIZE + 6),
PX_U16_HI8(PX_C1098_DATA_BLOCK_SIZE + 6), 0x00);
523 px_c1098_delay_after_ack_in_ticks = 0;
525 px_c1098_change_state(PX_C1098_STATE_WAIT_ACK);
528void px_c1098_reset(uint8_t rst_priority)
532 px_c1098_tx_cmd(PX_C1098_ID_RESET, 0x00, 0x00, 0x00, rst_priority);
538 px_c1098_change_state(PX_C1098_STATE_WAIT_ACK);
541void px_c1098_sync(
void)
544 px_c1098_retry_cntr = 10;
545 px_c1098_change_state(PX_C1098_STATE_SYNC);
548void px_c1098_snapshot(
void)
552 px_c1098_tx_cmd(PX_C1098_ID_SNAPSHOT, 0x00, 0x00, 0x00, 0x00);
555 px_c1098_change_state(PX_C1098_STATE_WAIT_ACK);
558uint32_t px_c1098_get_picture_size(
void)
560 return px_c1098_data_length;
566 px_c1098_on_rx_data = on_rx_data;
568 px_c1098_package_id = 0;
570 px_c1098_retry_cntr = 3;
573 px_c1098_tx_cmd(PX_C1098_ID_GET_PICTURE, 0x01, 0x00, 0x00, 0x00);
576 px_c1098_change_state(PX_C1098_STATE_GET_PIC_WAIT_ACK);
void(* px_c1098_on_rx_data_t)(const uint8_t *data, uint16_t bytes_received)
Definition for a pointer to a function that will be called once a block of data has been received.
#define NULL
NULL pointer.
#define PX_U16_HI8(data)
Extract the high 8 bits of a 16-bit value (Most Significant Byte)
#define PX_U16_CONCAT_U8(hi8, lo8)
Concatenate 2 x 8 bits to form 16-bit value.
#define PX_U32_CONCAT_U8(hi8, mh8, ml8, lo8)
Concatenate 4 x 8 bits to form 32-bit value.
#define PX_U16_LO8(data)
Extract the low 8 bits of a 16-bit value (Least Significant Byte)
#define PX_LOG_D(format,...)
Macro to display a formatted DEBUG message.
#define PX_LOG_TRACE(format,...)
Macro to output a user format string if PX_LOG=1.
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
#define PX_LOG_LEVEL_IS_D()
Debug level enabled?
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
void px_systmr_stop(px_systmr_t *systmr)
Stop a running timer.
void px_systmr_start(px_systmr_t *systmr, const px_systmr_ticks_t delay_in_ticks)
Start a timer.
px_sysclk_ticks_t px_systmr_ticks_t
Size definition of the tick counter.
#define PX_SYSTMR_MS_TO_TICKS(delay_in_ms)
Macro used to convert a timeout in milliseconds to timer ticks.
bool px_systmr_has_expired(px_systmr_t *systmr)
See if a timer has expired.
Structure to track state of a timer.
px_sysclk_ticks_t px_sysclk_get_tick_count(void)
Return number of ticks since system clock started.
bool px_uart_rd_u8(px_uart_handle_t *handle, uint8_t *data)
See if a received byte is available and store it in the specified location.
void px_uart_putchar(px_uart_handle_t *handle, char data)
Write one byte.