summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-05-17 21:21:00 +0200
committerlonkaars <loek@pipeframe.xyz>2022-05-17 21:21:00 +0200
commit365dcc18fbd98645585cdbe009f537ecdaa90c1a (patch)
tree078c14da20867e177d658ae4cc517b81ab9ad1aa
parentf00fca5f6f9751b16d868f52bda908c7b4704457 (diff)
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
-rw-r--r--.clang-tidy10
-rw-r--r--protocol.md7
-rw-r--r--robot/bin.c30
-rw-r--r--robot/bin.h27
-rw-r--r--robot/consts.h26
-rw-r--r--robot/errcatch.h27
-rw-r--r--robot/orangutan_shim.h3
-rw-r--r--robot/sercomm.h48
-rw-r--r--robot/setup.c9
9 files changed, 155 insertions, 32 deletions
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 <stdint.h>
+
+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 <pololu/orangutan.h>
+#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