/*
Example of state machine
Author: Nick Gammon, Date: 5 December 2013
Ernter 'R' or 'S' with a positive or negitive number.
R12 S456 R-89 S20
*/
// the possible states of the state-machine
typedef enum {
STATE_NONE,
STATE_R,
STATE_S,
STATE_POSITIVE,
STATE_NEGATIVE
} states;
states state = STATE_NONE; // current state-machine state
void setup () {
Serial.begin (115200);
Serial.println (F("Starting ..."));
}
void loop () {
if (Serial.available ())
processInput ();
// do other stuff here
}
// - - - - - - FUNCTIONS - - - - - -
void doRotate(const long angle) { // rotate to desired angle
Serial.print (F("Rotating to "));
Serial.println (angle);
}
void doSpeed(const long speed) { // set to desired speed
Serial.print (F("Setting speed to "));
Serial.println (speed);
}
void processNumber(char command, long n) {
switch (command) {
case 'R' : doRotate(n);
break;
case 'S' : doSpeed(n);
break;
}
}
void unexpectedInput (char c) {
Serial.print (F("Unexpected input: '"));
Serial.print (char (c));
Serial.println (F("'"));
}
long receivedNumber = 0; // current number
char commandType; // what command we received
void gotSpace () {
switch (state) {
case STATE_NONE:
case STATE_R:
case STATE_S:
break; // ignore space
case STATE_POSITIVE:
processNumber (commandType, receivedNumber);
state = STATE_NONE;
break;
case STATE_NEGATIVE:
processNumber (commandType, -receivedNumber);
state = STATE_NONE;
break;
}
}
void gotNewline () {
switch (state) {
case STATE_NONE:
break; // ignore newline/carriage-return
case STATE_R:
case STATE_S:
Serial.print (F("Unexpected line ending."));
state = STATE_NONE;
break;
case STATE_POSITIVE:
processNumber (commandType, receivedNumber);
state = STATE_NONE;
break;
case STATE_NEGATIVE:
processNumber (commandType, -receivedNumber);
state = STATE_NONE;
break;
}
}
void gotR (const char c) {
commandType = 'R';
receivedNumber = 0;
switch (state) {
case STATE_NONE:
state = STATE_R;
break;
case STATE_R:
case STATE_S:
unexpectedInput (c);
state = STATE_R;
break;
case STATE_POSITIVE:
processNumber (commandType, receivedNumber);
state = STATE_R;
break;
case STATE_NEGATIVE:
processNumber (commandType, -receivedNumber);
state = STATE_R;
break;
}
}
void gotS (const char c) {
commandType = 'S';
receivedNumber = 0;
switch (state) {
case STATE_NONE:
state = STATE_S;
break;
case STATE_R:
case STATE_S:
unexpectedInput (c);
state = STATE_S;
break;
case STATE_POSITIVE:
processNumber (commandType, receivedNumber);
state = STATE_S;
break;
case STATE_NEGATIVE:
processNumber (commandType, -receivedNumber);
state = STATE_S;
break;
}
}
void gotDigit (const char digit) {
switch (state) {
case STATE_NONE:
unexpectedInput (digit);
break;
case STATE_R:
case STATE_S:
state = STATE_POSITIVE;
break;
case STATE_POSITIVE:
case STATE_NEGATIVE:
break;
}
receivedNumber *= 10;
receivedNumber += digit - '0';
}
void gotMinus (const char c) {
switch (state) {
case STATE_NONE:
case STATE_POSITIVE:
case STATE_NEGATIVE:
unexpectedInput (c);
state = STATE_NONE;
break;
case STATE_R:
case STATE_S:
state = STATE_NEGATIVE;
break;
}
}
void gotPlus (const char c) {
switch (state) {
case STATE_NONE:
case STATE_POSITIVE:
case STATE_NEGATIVE:
unexpectedInput (c);
state = STATE_NONE;
break;
case STATE_R:
case STATE_S:
state = STATE_POSITIVE;
break;
}
}
void gotOther (const char c) {
switch (state) {
case STATE_NONE:
case STATE_R:
case STATE_S:
case STATE_POSITIVE:
case STATE_NEGATIVE:
unexpectedInput (c);
state = STATE_NONE;
break;
}
}
void processInput () {
byte c = Serial.read ();
// process according to what the input was
switch (toupper (c)) {
case ' ':
gotSpace ();
break;
case '\n':
case '\r':
gotNewline ();
break;
case 'R':
gotR (c);
break;
case 'S':
gotS (c);
break;
case '0' ... '9':
gotDigit (c);
break;
case '-':
gotMinus (c);
break;
case '+':
gotPlus (c);
break;
default:
unexpectedInput (c);
break;
}
}