From 3b2c2cf6b2af9e76b343a5a8fc8e9245f240690d Mon Sep 17 00:00:00 2001 From: lonkaars Date: Sun, 29 May 2022 16:27:29 +0200 Subject: serial parsing working on client --- shared/errcatch.c | 46 ++++++++++++++++++++++++ shared/errcatch.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ shared/errors.h | 64 --------------------------------- shared/serial_parse.c | 21 +++++++++++ 4 files changed, 165 insertions(+), 64 deletions(-) create mode 100644 shared/errcatch.c create mode 100644 shared/errcatch.h delete mode 100644 shared/errors.h (limited to 'shared') diff --git a/shared/errcatch.c b/shared/errcatch.c new file mode 100644 index 0000000..ff7fc93 --- /dev/null +++ b/shared/errcatch.c @@ -0,0 +1,46 @@ +#include +#include + +#include "errcatch.h" + +w2_s_error *g_w2_error_buffer[W2_ERROR_BUFFER_SIZE] = {}; +uint8_t g_w2_error_index = 0; +uint8_t g_w2_error_offset = 0; +bool g_w2_error_buffer_full = 0; +bool g_w2_error_uncaught = 0; + +void w2_errcatch_main() { + while (g_w2_error_offset != g_w2_error_index) { + w2_s_error *error = g_w2_error_buffer[g_w2_error_offset]; + w2_errcatch_handle_error(error); + g_w2_error_offset = (g_w2_error_offset + 1) % W2_ERROR_BUFFER_SIZE; + } + if (g_w2_error_buffer_full) { + w2_errcatch_throw(W2_E_WARN_ERR_BUFFER_FULL); + g_w2_error_buffer_full = 0; + } + if (g_w2_error_uncaught) { + w2_errcatch_throw(W2_E_WARN_UNCAUGHT_ERROR); + g_w2_error_uncaught = 0; + } +} + +w2_s_error *w2_alloc_error(w2_e_errorcode code, uint16_t length, const char *message) { + w2_s_error *error = malloc(sizeof(w2_s_error) + length); + memcpy(error, &(w2_s_error const){.code = code, .message_length = length}, sizeof(w2_s_error)); + strncpy(error->message, message, length); + + return error; +} + +void w2_errcatch_throw(w2_e_errorcode code) { w2_errcatch_throw_msg(code, 0, ""); } +void w2_errcatch_throw_msg(w2_e_errorcode code, uint16_t length, const char *message) { + uint8_t next_index = (g_w2_error_index + 1) % W2_ERROR_BUFFER_SIZE; + g_w2_error_buffer_full = next_index == g_w2_error_offset; + free(g_w2_error_buffer[g_w2_error_index]); + w2_s_error *error = w2_alloc_error(code, length, message); + g_w2_error_buffer[g_w2_error_index] = error; + if (g_w2_error_buffer_full) return; + g_w2_error_index = next_index; +} + diff --git a/shared/errcatch.h b/shared/errcatch.h new file mode 100644 index 0000000..9b14cc2 --- /dev/null +++ b/shared/errcatch.h @@ -0,0 +1,98 @@ +#pragma once + +/** @file errcatch.h */ + +#include + +#include "consts.h" +#include "bool.h" + +#define W2_E_TYPE_MASK (0b11 << 6) + +#define W2_E_TYPE_CRIT (0b00 << 6) +#define W2_E_TYPE_WARN (0b01 << 6) +#define W2_E_TYPE_INFO (0b10 << 6) +#define W2_E_TYPE_VERB (0b11 << 6) + +/** + * enum storing all error codes + * + * error codes are between 0-63 because the two most significant bits are + * reserved for error type checking + */ +typedef enum { + /** wireless connection lost from either robot or client-side */ + W2_E_CRIT_CONN_LOST = 0x00 | W2_E_TYPE_CRIT, + /** serial COM-port unavalable. client-side only */ + W2_E_CRIT_COM_UNAVAILABLE = 0x01 | W2_E_TYPE_CRIT, + /** line unable to be found automatically */ + W2_E_CRIT_LINE_LOST = 0x02 | W2_E_TYPE_CRIT, + /** obstacle unavoidable, robot stuck */ + W2_E_CRIT_OBSTACLE_STUCK = 0x03 | W2_E_TYPE_CRIT, + /** semver major version doesn't match */ + W2_E_CRIT_VERSION_INCOMPATIBLE = 0x04 | W2_E_TYPE_CRIT, + + /** battery low, returning to charging station */ + W2_E_WARN_BATTERY_LOW = 0x00 | W2_E_TYPE_WARN, + /** obstacle detected, waiting then trying other route */ + W2_E_WARN_OBSTACLE_DETECTED = 0x01 | W2_E_TYPE_WARN, + /** logic cycle took longer than `W2_MAX_MODULE_CYCLE_MS` */ + W2_E_WARN_CYCLE_EXPIRED = 0x02 | W2_E_TYPE_WARN, + /** error thrown without handler, gets thrown on next cycle */ + W2_E_WARN_UNCAUGHT_ERROR = 0x03 | W2_E_TYPE_WARN, + /** error buffer full, gets thrown on next cycle */ + W2_E_WARN_ERR_BUFFER_FULL = 0x04 | W2_E_TYPE_WARN, + /** line lost, trying to calibrate */ + W2_E_WARN_LINE_LOST = 0x05 | W2_E_TYPE_WARN, + /** serial buffer full, gets thrown on next cycle */ + W2_E_WARN_SERCOMM_BUFFER_FULL = 0x06 | W2_E_TYPE_WARN, + /** semver minor version doesn't match */ + W2_E_WARN_VERSION_INCOMPATIBLE = 0x07 | W2_E_TYPE_WARN, + /** unknown message encountered (noisy channel?) */ + W2_E_WARN_SERIAL_NOISY = 0x09 | W2_E_TYPE_WARN, + /** mode history index out of bounds */ + W2_E_WARN_MODE_HISTORY_BUFFER_IOB = 0x0a | W2_E_TYPE_WARN, +} w2_e_errorcode; + +/** + * error struct + * + * holds an error with type `code`, and an optional `message` with length + * `message_length` + */ +typedef struct { + w2_e_errorcode code; + uint8_t message_length; + char message[]; +} w2_s_error; + +/** error ring buffer */ +extern w2_s_error *g_w2_error_buffer[W2_ERROR_BUFFER_SIZE]; +/** stores head of ring buffer */ +extern uint8_t g_w2_error_index; +/** stores start of ring buffer */ +extern uint8_t g_w2_error_offset; +/** error buffer full flag */ +extern bool g_w2_error_buffer_full; +/** uncaught error flag */ +extern bool g_w2_error_uncaught; + +/** error-handler module main */ +void w2_errcatch_main(); + +/** handle error */ +void w2_errcatch_handle_error(w2_s_error *error); + +/** append error to error buffer */ +void w2_errcatch_throw(w2_e_errorcode code); + +/** append error to error buffer (with debug message) */ +void w2_errcatch_throw_msg(w2_e_errorcode code, uint16_t length, const char *message); + +/** + * allocate and initialize error struct + * + * TODO: doesn't handle null pointers from malloc + */ +w2_s_error *w2_alloc_error(w2_e_errorcode code, uint16_t length, const char *message); + diff --git a/shared/errors.h b/shared/errors.h deleted file mode 100644 index 344a506..0000000 --- a/shared/errors.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -/** @file errors.h */ - -#include - -#define W2_E_TYPE_MASK (0b11 << 6) - -#define W2_E_TYPE_CRIT (0b00 << 6) -#define W2_E_TYPE_WARN (0b01 << 6) -#define W2_E_TYPE_INFO (0b10 << 6) -#define W2_E_TYPE_VERB (0b11 << 6) - -/** - * enum storing all error codes - * - * error codes are between 0-63 because the two most significant bits are - * reserved for error type checking - */ -typedef enum { - /** wireless connection lost from either robot or client-side */ - W2_E_CRIT_CONN_LOST = 0x00 | W2_E_TYPE_CRIT, - /** serial COM-port unavalable. client-side only */ - W2_E_CRIT_COM_UNAVAILABLE = 0x01 | W2_E_TYPE_CRIT, - /** line unable to be found automatically */ - W2_E_CRIT_LINE_LOST = 0x02 | W2_E_TYPE_CRIT, - /** obstacle unavoidable, robot stuck */ - W2_E_CRIT_OBSTACLE_STUCK = 0x03 | W2_E_TYPE_CRIT, - /** semver major version doesn't match */ - W2_E_CRIT_VERSION_INCOMPATIBLE = 0x04 | W2_E_TYPE_CRIT, - - /** battery low, returning to charging station */ - W2_E_WARN_BATTERY_LOW = 0x00 | W2_E_TYPE_WARN, - /** obstacle detected, waiting then trying other route */ - W2_E_WARN_OBSTACLE_DETECTED = 0x01 | W2_E_TYPE_WARN, - /** logic cycle took longer than `W2_MAX_MODULE_CYCLE_MS` */ - W2_E_WARN_CYCLE_EXPIRED = 0x02 | W2_E_TYPE_WARN, - /** error thrown without handler, gets thrown on next cycle */ - W2_E_WARN_UNCAUGHT_ERROR = 0x03 | W2_E_TYPE_WARN, - /** error buffer full, gets thrown on next cycle */ - W2_E_WARN_ERR_BUFFER_FULL = 0x04 | W2_E_TYPE_WARN, - /** line lost, trying to calibrate */ - W2_E_WARN_LINE_LOST = 0x05 | W2_E_TYPE_WARN, - /** serial buffer full, gets thrown on next cycle */ - W2_E_WARN_SERCOMM_BUFFER_FULL = 0x06 | W2_E_TYPE_WARN, - /** semver minor version doesn't match */ - W2_E_WARN_VERSION_INCOMPATIBLE = 0x07 | W2_E_TYPE_WARN, - /** unknown message encountered (noisy channel?) */ - W2_E_WARN_SERIAL_NOISY = 0x09 | W2_E_TYPE_WARN, - /** mode history index out of bounds */ - W2_E_WARN_MODE_HISTORY_BUFFER_IOB = 0x0a | W2_E_TYPE_WARN, -} w2_e_errorcode; - -/** - * error struct - * - * holds an error with type `code`, and an optional `message` with length - * `message_length` - */ -typedef struct { - w2_e_errorcode code; - uint8_t message_length; - char message[]; -} w2_s_error; diff --git a/shared/serial_parse.c b/shared/serial_parse.c index b1b4f50..49f4cbf 100644 --- a/shared/serial_parse.c +++ b/shared/serial_parse.c @@ -2,6 +2,10 @@ #include "consts.h" #include "serial_parse.h" +#include "errcatch.h" +#ifdef W2_SIM +#include "../robot/orangutan_shim.h" +#endif bool w2_serial_parse(uint8_t byte) { static uint8_t current_message[W2_SERIAL_READ_BUFFER_SIZE] = {0}; @@ -38,3 +42,20 @@ bool w2_serial_parse(uint8_t byte) { return W2_SERIAL_READ_SUCCESS; } + +void w2_cmd_handler(uint8_t data[W2_SERIAL_READ_BUFFER_SIZE], uint8_t data_length) { + w2_s_bin *copy = w2_bin_s_alloc(data_length, data); + void (*handler)(w2_s_bin *) = g_w2_cmd_handlers[data[0]]; + + if (handler == NULL) { + w2_errcatch_throw(W2_E_WARN_SERIAL_NOISY); + } else { +#ifdef W2_SIM + w2_sim_print_serial(copy); +#endif + handler(copy); + } + + free(copy); +} + -- cgit v1.2.3