From 6aa159ba5c958d904408ff37a1486670390232ca Mon Sep 17 00:00:00 2001
From: jp7g21 <jp7g21@soton.ac.uk>
Date: Sat, 13 Nov 2021 18:55:02 +0000
Subject: [PATCH] Command reading code

---
 emb/command.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
 emb/command.h | 14 ++++++++++
 2 files changed, 88 insertions(+)
 create mode 100644 emb/command.c
 create mode 100644 emb/command.h

diff --git a/emb/command.c b/emb/command.c
new file mode 100644
index 0000000..edf0d31
--- /dev/null
+++ b/emb/command.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "command.h"
+
+#define NUM_COMMANDS 20
+
+/* Cyclic buffer; when comm_start == comm_end, length = 0 */
+struct command command_buf[NUM_COMMANDS];
+uint16_t comm_start = 0, comm_end = 0;
+
+/* Add y to x, wrapping around limit */
+static inline void add_wrap(uint16_t *x, uint16_t y, uint16_t limit)
+{
+     *x += y;
+     if (*x >= limit) *x %= limit;
+     while (*x < 0) *x += limit;
+}
+
+enum state {
+     STATE_COMM, STATE_COMM_SPACE, STATE_ARG
+};
+
+/* Return 1 if new command ready */
+uint8_t uart_add_ch(char c)
+{
+     static enum state state = STATE_COMM;
+     static char argbuf[20]; /* Buffer for storing argument */
+     static int argbuf_ind = 0; /* Index into argbuf of next character */
+     static int argnum = 0;
+     struct command *curr = &command_buf[comm_end];
+     
+     switch (state) {
+     case STATE_COMM:
+	  curr->comm_ch = c;
+	  state = STATE_COMM_SPACE;
+	  break;
+     case STATE_COMM_SPACE:
+	  if (c == ' ') {
+	       state = STATE_ARG;
+	  } else {
+	       state = STATE_COMM;
+	       add_wrap(&comm_end, 1, NUM_COMMANDS);
+	  }
+	  break;
+     case STATE_ARG:
+	  if (c == ' ' || c == '\n') {
+	       argbuf[argbuf_ind] = '\0'; /* Terminate string */
+	       curr->arg[argnum] = atoi(argbuf);
+	       argbuf_ind = 0;
+	       if (c == ' ') { /* More arguments follow */
+		    argnum++;
+	       } else { /* End of line */
+		    argnum = 0;
+		    state = STATE_COMM;
+		    add_wrap(&comm_end, 1, NUM_COMMANDS);
+	       }
+	  } else {
+	       if (argbuf_ind < 19) argbuf[argbuf_ind++] = c;
+	  }
+	  break;
+     }
+     return state == STATE_COMM;
+}
+
+struct command *get_command(void)
+{
+     if (comm_start != comm_end) {
+	  struct command *ret = &command_buf[comm_start];
+	  add_wrap(&comm_start, 1, NUM_COMMANDS);
+	  return ret;
+     } else {
+	  return NULL;
+     }
+}
diff --git a/emb/command.h b/emb/command.h
new file mode 100644
index 0000000..abbb552
--- /dev/null
+++ b/emb/command.h
@@ -0,0 +1,14 @@
+#ifndef _COMMAND_H
+#define _COMMAND_H
+
+#include <stdint.h>
+
+struct command {
+     char comm_ch; /* Character of command (ie 's', 'v', 'd') */
+     int16_t arg[2];
+};
+
+uint8_t uart_add_ch(char c);
+struct command *get_command(void);
+
+#endif /* _COMMAND_H */
-- 
GitLab