From 365dcc18fbd98645585cdbe009f537ecdaa90c1a Mon Sep 17 00:00:00 2001 From: lonkaars Date: Tue, 17 May 2022 21:21:00 +0200 Subject: WIP sercomm implementation - moved some module-specific constants to their respective header files - changed .clang-tidy to ignore global private global constants (starting with `_`) - suppressed some GCC warnings in bin.c and all pololu library warnings - added function signatures for sercomm protocol data generators - added endianness check in setup.c --- .clang-tidy | 10 ++++++---- protocol.md | 7 +++++-- robot/bin.c | 30 ++++++++++++++++++++++++++++++ robot/bin.h | 27 +++++++++++++++++++++++++++ robot/consts.h | 26 -------------------------- robot/errcatch.h | 27 +++++++++++++++++++++++++++ robot/orangutan_shim.h | 3 +++ robot/sercomm.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ robot/setup.c | 9 +++++++++ 9 files changed, 155 insertions(+), 32 deletions(-) create mode 100644 robot/bin.c create mode 100644 robot/bin.h diff --git a/.clang-tidy b/.clang-tidy index 054a943..4c8496f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,16 +1,18 @@ Checks: '-*,readability-identifier-naming' CheckOptions: + - { key: readability-identifier-naming.EnumCase, value: lower_case } + - { key: readability-identifier-naming.EnumPrefix, value: w2_e_ } - { key: readability-identifier-naming.FunctionCase, value: lower_case } - { key: readability-identifier-naming.FunctionPrefix, value: w2_ } - - { key: readability-identifier-naming.GlobalVariableCase, value: lower_case } - - { key: readability-identifier-naming.GlobalVariablePrefix, value: g_w2_ } - { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE } + - { key: readability-identifier-naming.GlobalConstantIgnoredRegexp, value: _.* } - { key: readability-identifier-naming.GlobalConstantPrefix, value: W2_ } + - { key: readability-identifier-naming.GlobalVariableCase, value: lower_case } + - { key: readability-identifier-naming.GlobalVariableIgnoredRegexp, value: _.* } + - { key: readability-identifier-naming.GlobalVariablePrefix, value: g_w2_ } - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } - { key: readability-identifier-naming.MacroDefinitionPrefix, value: W2_ } - { key: readability-identifier-naming.StructCase, value: lower_case } - { key: readability-identifier-naming.StructPrefix, value: w2_s_ } - - { key: readability-identifier-naming.EnumCase, value: lower_case } - - { key: readability-identifier-naming.EnumPrefix, value: w2_e_ } # vim: ft=yaml diff --git a/protocol.md b/protocol.md index f5bb0cc..d41b00f 100644 --- a/protocol.md +++ b/protocol.md @@ -25,8 +25,8 @@ is converted to a single `0xff` on the receiving end, so these duplicated bytes and the starting byte don't count towards message length. opcodes are picked sequentially, but the direction bit (LSB) is reserved to -indicate a transfer from robot to client. this means that the opcode for a -sensor data request would be `0x12`, but the response opcode would be `0x13`. +indicate a transfer from robot to client (`tx`). this means that the opcode for +a sensor data request would be `0x12`, but the response opcode would be `0x13`. these opcodes are stored as enum constants inside consts.h for code readability. @@ -54,6 +54,9 @@ a double stroke arrow means that the command can be initiated from either the robot or the client, while a single arrow indicates a request-response structure. +in *both* the robot and client code `r <-- c` is referred to as `rx` and `r +--> c` as `tx` (from the *robots* view). + ### PING #### ping (`r <=> c`) (2 bytes) diff --git a/robot/bin.c b/robot/bin.c new file mode 100644 index 0000000..4261b50 --- /dev/null +++ b/robot/bin.c @@ -0,0 +1,30 @@ +#include "bin.h" + +#define W2_ENDIAN_LITTLE (1) +#define W2_ENDIAN_BIG (0) + +#define _SHIFT_0B (8 * 0) +#define _SHIFT_1B (8 * 1) +#define _SHIFT_2B (8 * 2) +#define _SHIFT_3B (8 * 3) +#define _BYTE_0 ((uint32_t)(0xff << (_SHIFT_0B))) +#define _BYTE_1 ((uint32_t)(0xff << (_SHIFT_1B))) +#define _BYTE_2 ((uint32_t)(0xff << (_SHIFT_2B))) +#define _BYTE_3 ((uint32_t)(0xff << (_SHIFT_3B))) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshift-count-overflow" +uint32_t w2_bin_hton32(uint32_t h32) { + if(g_w2_endianness == W2_ENDIAN_BIG) return h32; + return ((h32 & _BYTE_0) << _SHIFT_3B) | ((h32 & _BYTE_1) << _SHIFT_1B) + | ((h32 & _BYTE_2) >> _SHIFT_1B) | ((h32 & _BYTE_3) >> _SHIFT_3B); +} +#pragma GCC diagnostic pop + +uint16_t w2_bin_hton16(uint16_t h16) { + if(g_w2_endianness == W2_ENDIAN_BIG) return h16; + return ((h16 & _BYTE_0) << _SHIFT_1B) | ((h16 & _BYTE_1) >> _SHIFT_1B); +} + +uint32_t w2_bin_ntoh32(uint32_t n32) { return w2_bin_hton32(n32); } +uint16_t w2_bin_ntoh16(uint16_t n16) { return w2_bin_hton16(n16); } diff --git a/robot/bin.h b/robot/bin.h new file mode 100644 index 0000000..1f21f64 --- /dev/null +++ b/robot/bin.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +typedef struct { + uint16_t bytes; + uint8_t data[]; +} w2_s_bin; + +extern uint8_t g_w2_endianness; + + +/** + * helper file for binary data + * + * - fix endianness with functions inspired by UNIX arpa/inet.h + */ + +/** convert 32-bit value from host endian to network (big-endian) */ +uint32_t w2_bin_hton32(uint32_t h32); +/** convert 16-bit value from host endian to network (big-endian) */ +uint16_t w2_bin_hton16(uint16_t h16); +/** convert 32-bit value from network (big-endian) to host endian */ +uint32_t w2_bin_ntoh32(uint32_t n32); +/** convert 16-bit value from network (big-endian) to host endian */ +uint16_t w2_bin_ntoh16(uint16_t n16); + diff --git a/robot/consts.h b/robot/consts.h index 1e021e0..3558da0 100644 --- a/robot/consts.h +++ b/robot/consts.h @@ -7,31 +7,5 @@ #define W2_MAX_MODULE_CYCLE_MS (20) #define W2_SERIAL_BAUD (9600) - #define W2_E_BUFFER_SIZE (16) -#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 - */ -enum w2_e_errorcodes { - // critical error codes - W2_E_CRIT_CONN_LOST = 0x00 | W2_E_TYPE_CRIT, - W2_E_CRIT_COM_UNAVAILABLE = 0x01 | W2_E_TYPE_CRIT, // client-only - W2_E_CRIT_LINE_LOST = 0x02 | W2_E_TYPE_CRIT, - W2_E_CRIT_OBSTACLE_STUCK = 0x03 | W2_E_TYPE_CRIT, - // warnings - W2_E_WARN_BATTERY_LOW = 0x00 | W2_E_TYPE_WARN, - W2_E_WARN_OBSTACLE_DETECTED = 0x01 | W2_E_TYPE_WARN, - W2_E_WARN_CYCLE_EXPIRED = 0x02 | W2_E_TYPE_WARN, - W2_E_WARN_UNCAUGHT_ERROR = 0x03 | W2_E_TYPE_WARN, -}; diff --git a/robot/errcatch.h b/robot/errcatch.h index 98bb7d0..ec4b90f 100644 --- a/robot/errcatch.h +++ b/robot/errcatch.h @@ -4,6 +4,33 @@ #include "consts.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 + */ +enum w2_e_errorcodes { + // critical error codes + W2_E_CRIT_CONN_LOST = 0x00 | W2_E_TYPE_CRIT, + W2_E_CRIT_COM_UNAVAILABLE = 0x01 | W2_E_TYPE_CRIT, // client-only + W2_E_CRIT_LINE_LOST = 0x02 | W2_E_TYPE_CRIT, + W2_E_CRIT_OBSTACLE_STUCK = 0x03 | W2_E_TYPE_CRIT, + + // warnings + W2_E_WARN_BATTERY_LOW = 0x00 | W2_E_TYPE_WARN, + W2_E_WARN_OBSTACLE_DETECTED = 0x01 | W2_E_TYPE_WARN, + W2_E_WARN_CYCLE_EXPIRED = 0x02 | W2_E_TYPE_WARN, + W2_E_WARN_UNCAUGHT_ERROR = 0x03 | W2_E_TYPE_WARN, +}; + /** * error struct * diff --git a/robot/orangutan_shim.h b/robot/orangutan_shim.h index de57c98..cd624d0 100644 --- a/robot/orangutan_shim.h +++ b/robot/orangutan_shim.h @@ -3,5 +3,8 @@ #ifdef W2_SIM #include "sim.h" #else +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" #include +#pragma GCC diagnostic pop #endif diff --git a/robot/sercomm.h b/robot/sercomm.h index 58c79b9..1533a4c 100644 --- a/robot/sercomm.h +++ b/robot/sercomm.h @@ -1,5 +1,27 @@ #pragma once +#include "bin.h" + +#define W2_CMD_RX (0) +#define W2_CMD_TX (1) + +enum w2_e_serial_commands { + W2_E_CMD_PING = 0x00, + W2_E_CMD_EXPT = 0x02, + W2_E_CMD_MODE = 0x04, + W2_E_CMD_SPED = 0x06, + W2_E_CMD_DIRC = 0x08, + W2_E_CMD_CORD = 0x0a, + W2_E_CMD_BOMD = 0x0c, + W2_E_CMD_SRES = 0x0e, + W2_E_CMD_MCFG = 0x10, + W2_E_CMD_SENS = 0x12, + W2_E_CMD_INFO = 0x14, + W2_E_CMD_DISP = 0x16, + W2_E_CMD_PLAY = 0x18, + W2_E_CMD_CLED = 0x1a, +}; + /** * serial pc-robot communication module * @@ -7,3 +29,29 @@ * - sends all data in the message buffer */ void w2_sercomm_main(); + +void w2_sercomm_append_msg(w2_s_bin data); + +w2_s_bin w2_sercomm_rx_generic(); +w2_s_bin w2_sercomm_tx_generic(); + +w2_s_bin w2_sercomm_rx_ping(); +w2_s_bin w2_sercomm_tx_ping(); +w2_s_bin w2_sercomm_tx_expt(); +w2_s_bin w2_sercomm_rx_mode(); +w2_s_bin w2_sercomm_tx_mode(); +w2_s_bin w2_sercomm_rx_sped(); +w2_s_bin w2_sercomm_rx_dirc(); +w2_s_bin w2_sercomm_rx_cord(); +w2_s_bin w2_sercomm_tx_cord(); +w2_s_bin w2_sercomm_rx_bomd(); +w2_s_bin w2_sercomm_tx_bomd(); +w2_s_bin w2_sercomm_rx_sres(); +w2_s_bin w2_sercomm_rx_mcfg(); +w2_s_bin w2_sercomm_rx_sens(); +w2_s_bin w2_sercomm_tx_sens(); +w2_s_bin w2_sercomm_rx_info(); +w2_s_bin w2_sercomm_tx_info(); +w2_s_bin w2_sercomm_rx_disp(); +w2_s_bin w2_sercomm_rx_play(); +w2_s_bin w2_sercomm_rx_cled(); diff --git a/robot/setup.c b/robot/setup.c index c74cca9..bdd5991 100644 --- a/robot/setup.c +++ b/robot/setup.c @@ -5,8 +5,17 @@ #include "modes.h" #include "orangutan_shim.h" #include "setup.h" +#include "bin.h" + +// pointers for endianness check +static const uint16_t _test = 1; +static const uint8_t* _ptest = (uint8_t*)&_test; +uint8_t g_w2_endianness; void w2_setup_main() { + // check endianness + g_w2_endianness = *_ptest; + serial_set_baud_rate(W2_SERIAL_BAUD); // reset underside leds -- cgit v1.2.3