summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2015-06-10 14:03:12 +0200
committerPeter Wu <peter@lekensteyn.nl>2015-06-10 14:03:42 +0200
commit0bf6143b949e349bf2bf1f97cdd401bcbd523531 (patch)
treed056ac03bc0b22d564fcd1cd8c1712438ec8bf19
parentffea9d997ad36e7a8a42cd2384ab314a77d623f0 (diff)
downloadcode-0bf6143b949e349bf2bf1f97cdd401bcbd523531.tar.gz
Add Uno communication
-rw-r--r--Venus_Skeleton/comm.c90
-rw-r--r--Venus_Skeleton/comm.h23
2 files changed, 113 insertions, 0 deletions
diff --git a/Venus_Skeleton/comm.c b/Venus_Skeleton/comm.c
new file mode 100644
index 0000000..f5392e0
--- /dev/null
+++ b/Venus_Skeleton/comm.c
@@ -0,0 +1,90 @@
+/**
+ * Serial communication module.
+ */
+
+#include <stdbool.h>
+#include "dataTypes.h"
+
+serial_state_t serial_state = SERIAL_UNKNOWN;
+
+static void handle_recv(int r);
+
+static void handle_ctrl(int r) {
+ // detect reset procedure
+ switch (r) {
+ case RESET1:
+ // reset request received, ack and wait for RESET2
+ Serial.write(ACK1);
+ serial_state = SERIAL_INIT;
+ return;
+ case RESET2:
+ if (serial_state == SERIAL_INIT) {
+ // Handshake completed!
+ Serial.write(ACK2);
+ serial_state = SERIAL_READY;
+ } else {
+ // invalid state, reject it
+ Serial.write(OUTOFSYNC);
+ serial_state = SERIAL_UNKNOWN;
+ }
+ return;
+ case PONG:
+ // TODO mark as alive if PING was previously sent
+ return;
+ }
+ // TODO commands for navigation? Use DATA_LEN, etc?
+}
+
+void handle_serial(data_t *data, int changedBits) {
+ // first attempt sync
+ while (Serial.available()) {
+ r = Serial.read();
+
+ if ((r & 0xC0) == 0x80) {
+ // handle control packets
+ handle_ctrl(r);
+ // TODO if DATA_ESCAPE or DATA_LEN1, react appropriately
+ } else if (serial_state == SERIAL_READY) {
+ // handle normal data only when the handshake has completed.
+ handle_recv(r);
+ }
+ }
+
+ if (serial_state != SERIAL_READY) {
+ // Hardware is not ready, do not send data.
+ return;
+ }
+
+ // then send queued data
+}
+
+// writes data of length len
+static void serial_write_data(const char *data, unsigned len) {
+ len--; // length on wire is one smaller (00 means 1 byte, 01 means 2, etc.)
+ if (len >= 0 && len < 56) {
+ Serial.write(0x80 + len + 7);
+ } else if (len >= 0 && len < 256) {
+ Serial.write(0x88 | (len >> 5));
+ Serial.write(0xA0 | (len & 0x1F));
+ } else {
+ // zero length or too long.
+ return;
+ }
+ // write remainder
+ for (unsigned i = 0; i < len; i++) {
+ char c = data[i];
+ if (c & 0x80) {
+ Serial.write(DATA_ESCAPE);
+ Serial.write(c & ~0x80);
+ } else {
+ Serial.write(c);
+ }
+ }
+}
+
+void serial_print_debug(const char *str) {
+ serial_print_debug(str, strlen(str));
+}
+
+static void handle_recv(int r) {
+}
diff --git a/Venus_Skeleton/comm.h b/Venus_Skeleton/comm.h
new file mode 100644
index 0000000..5cdf77e
--- /dev/null
+++ b/Venus_Skeleton/comm.h
@@ -0,0 +1,23 @@
+typedef enum {
+ RESET1 = 0x81,
+ RESET2 = 0x82,
+ ACK1 = 0x81,
+ ACK2 = 0x82,
+ OUTOFSYNC = 0x83,
+ PING = 0x80,
+ PONG = 0x80,
+ DATA_ESCAPE = 0x84,
+} serial_control_command_t;
+
+typedef enum {
+ // waiting for RESET1
+ SERIAL_UNKNOWN,
+ // received RESET1, sent ACK1, waiting for RESET2
+ SERIAL_INIT,
+ // received RESET2, sent ACK1, waiting for other commands
+ SERIAL_READY,
+} serial_state_t;
+extern serial_state_t serial_state;
+
+void handle_serial(data_t *data, int changedBits);
+void serial_print_debug(const char *str);