command.c 1.78 KB
Newer Older
jp7g21's avatar
jp7g21 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
     }
}