 void sync_abort(char *msg) {
   Serial.print("SYNC aborted:");
   Serial.println(msg);
+}
+
+int8_t sync_blocking_read() {
+  int8_t c;
+  uint16_t startt = millis();
+
+  do {
+    c = Serial.read();
+    if (millis() - startt > SYNC_SERIAL_TIMEOUT) {
+      sync_abort("communication timed out");
+      Sync.abort = 1;
+      break;
+    }
+  } while (c == -1);
+  return c;
+}
+
+/**
+ * Looks for the given word in the serial input.
+ */ 
+uint8_t sync_get_word(char *w) {
+  char *p = w;
+  uint8_t c;
+  while(*p && Sync.abort == 0) {
+    c = sync_blocking_read();
+    if (c == *p) p++;
+    else return ERROR;
+  }
+
+  return OK;
+}
+
+/**
+ * Reads serial stream until SYNC_DELIMITER is found or out of space, then
+ * uses atoi to convert the string into an integer, returning the result.
+ */
+int16_t sync_get_int() {
+  uint8_t readpos = 0;
+  uint8_t c;
+  do {
+    c = sync_blocking_read();
+    if (c == SYNC_DELIMITER) break;
+    else _sbuf[readpos++] = c;
+  } while (readpos < sizeof(_sbuf)-1 && Sync.abort == 0);
+
+  _sbuf[readpos] = '\0';
+  return atoi(_sbuf);
 }
 
 /**

 *
 * is valid.
 */ 
void sync_listen() {
  uint8_t readpos = 0;
  for (readpos = 0; Serial.available() && readpos < sizeof(_sbuf)-1; ++readpos) {
    _sbuf[readpos] = Serial.read();
  }

  if (readpos == 0) return;
  
  _sbuf[readpos] = '\0';

  if (strstr(_sbuf, "SYNC;") == _sbuf) {
    // we have start of sync, yay
    char *sptr = _sbuf+5;
    Serial.println("Starting SYNC");
  } else sync_abort("SYNC; expected");
}

#define SYNC_TEXT_COLOR     (COLOR_WHITE)

#define SYNC_DELIMITER      ';'

// timeout in milliseconds. If we expect communication and don't see it for
// this long we abort sync
#define SYNC_SERIAL_TIMEOUT (1*3000)

typedef struct {
  uint8_t abort;
} Sync_t;

Sync_t Sync = {0};

void sync_init() {
}
