It turns out that the Arduino serial port char buffer is only 500 bytes, so
message size has to be < 500 or else data is lost. This change bumps it down
to 128 bytes which should still be big enough. This also has a start on the
actual Bluetooth test code which is the purpose of all this.

Change-Id: I4144821b52800770f707fa3a15a8be16ac4d4146
diff --git a/apps/CtsVerifier/arduino-helper/Makefile b/apps/CtsVerifier/arduino-helper/Makefile
index 65bdacb..4159ee6 100644
--- a/apps/CtsVerifier/arduino-helper/Makefile
+++ b/apps/CtsVerifier/arduino-helper/Makefile
@@ -41,7 +41,7 @@
 ARDUINO_VERSION=18
 ARDUINO_CORES_PATH = $(ARDUINO_PATH)/hardware/arduino/cores/arduino
 AVR_TOOLS_PATH = /usr/bin
-AVRDUDE_PATH = $(ARDUINO_PATH)/hardware/tools
+AVRDUDE_PATH = /usr/bin
 
 # Programming port information
 PORT = /dev/ttyUSB0
@@ -117,8 +117,9 @@
 
 # Programming support using avrdude. Settings and variables.
 AVRDUDE_WRITE_FLASH = -U flash:w:$(OUT_DIR)/$(TARGET).hex
-AVRDUDE_FLAGS = -V -F -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf \
--p $(MCU) -P $(PORT) -c $(AVRDUDE_PROGRAMMER) -b $(UPLOAD_RATE)
+#AVRDUDE_FLAGS = -V -F -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf \
+
+AVRDUDE_FLAGS = -V -F -p $(MCU) -P $(PORT) -c $(AVRDUDE_PROGRAMMER) -b $(UPLOAD_RATE)
 
 # AVR cross-compiler toolchain binaries
 CC = $(AVR_TOOLS_PATH)/avr-gcc
@@ -149,11 +150,12 @@
 
 # Concatenates the 'sketch' .pde file with the usual Arduino boilerplate
 $(OUT_DIR)/$(TARGET).cpp: $(TARGET).pde
-	test -d $(OUT_DIR) || mkdir $(OUT_DIR)
-	echo '#include "WProgram.h"' > $(OUT_DIR)/$(TARGET).cpp
-	echo 'void setup();' >> $(OUT_DIR)/$(TARGET).cpp
-	echo 'void loop();' >> $(OUT_DIR)/$(TARGET).cpp
-	cat $(TARGET).pde >> $(OUT_DIR)/$(TARGET).cpp
+	@echo "Generate $(TARGET).cpp from $(TARGET).pde"
+	@test -d $(OUT_DIR) || mkdir $(OUT_DIR)
+	@echo '#include "WProgram.h"' > $(OUT_DIR)/$(TARGET).cpp
+	@echo 'void setup();' >> $(OUT_DIR)/$(TARGET).cpp
+	@echo 'void loop();' >> $(OUT_DIR)/$(TARGET).cpp
+	@cat $(TARGET).pde >> $(OUT_DIR)/$(TARGET).cpp
 
 elf: $(OUT_DIR)/$(TARGET).elf
 hex: $(OUT_DIR)/$(TARGET).hex
@@ -172,10 +174,10 @@
 HEXSIZE = $(SIZE) --target=$(FORMAT) $(OUT_DIR)/$(TARGET).hex
 ELFSIZE = $(SIZE)  $(OUT_DIR)/$(TARGET).elf
 sizebefore:
-	@if [ -f $(OUT_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
+	@if [ -f $(OUT_DIR)/$(TARGET).elf ]; then echo $(MSG_SIZE_BEFORE); $(HEXSIZE); fi
 
 sizeafter:
-	@if [ -f $(OUT_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi
+	@if [ -f $(OUT_DIR)/$(TARGET).elf ]; then echo $(MSG_SIZE_AFTER); $(HEXSIZE); fi
 
 
 # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
@@ -254,9 +256,14 @@
 
 # Target: clean project.
 clean:
-	$(REMOVE) $(OUT_DIR)/$(TARGET).hex $(OUT_DIR)/$(TARGET).eep $(OUT_DIR)/$(TARGET).cof $(OUT_DIR)/$(TARGET).elf \
-	$(OUT_DIR)/$(TARGET).map $(OUT_DIR)/$(TARGET).sym $(OUT_DIR)/$(TARGET).lss $(OUT_DIR)/core.a \
-	$(ARDUINO_C_MODULES_SRC:.c=.s) $(ARDUINO_C_MODULES_SRC:.c=.d) $(ARDUINO_CPP_MODULES_SRC:.cpp=.s) $(ARDUINO_CPP_MODULES_SRC:.cpp=.d) $(ARDUINO_C_MODULES_OBJ) $(ARDUINO_CPP_MODULES_OBJ) $(OUT_DIR)/$(TARGET).cpp
+	$(REMOVE) $(OUT_DIR)/$(TARGET).hex $(OUT_DIR)/$(TARGET).eep \
+        $(OUT_DIR)/$(TARGET).cof $(OUT_DIR)/$(TARGET).elf \
+        $(OUT_DIR)/$(TARGET).map $(OUT_DIR)/$(TARGET).sym \
+        $(OUT_DIR)/$(TARGET).lss $(OUT_DIR)/core.a \
+	$(ARDUINO_C_MODULES_SRC:.c=.s) $(ARDUINO_C_MODULES_SRC:.c=.d) \
+        $(ARDUINO_CPP_MODULES_SRC:.cpp=.s) $(ARDUINO_CPP_MODULES_SRC:.cpp=.d) \
+        $(ARDUINO_C_MODULES_OBJ) $(ARDUINO_CPP_MODULES_OBJ) \
+        $(OUT_DIR)/$(TARGET).cpp $(OUT_DIR)/$(TARGET).o
 distclean: clean
 	$(RMDIR) $(OUT_DIR)
 
diff --git a/apps/CtsVerifier/arduino-helper/arduino-helper.pde b/apps/CtsVerifier/arduino-helper/arduino-helper.pde
index 5649972..0c41388 100644
--- a/apps/CtsVerifier/arduino-helper/arduino-helper.pde
+++ b/apps/CtsVerifier/arduino-helper/arduino-helper.pde
@@ -16,19 +16,20 @@
 
 /*
  * Define the basic structure for messages from the host.
- * Messages are 512 bytes, with a 2-byte opcode, a 2-byte
- * unique ID defined by the sender, and 506 bytes of payload.
+ * Messages are MESSAGE_SIZE bytes, with a 2-byte opcode, a 2-byte
+ * unique ID defined by the sender, and the remainder payload.
  * The remaining 2 bytes must be 0xFEEDFACE. This is used by
  * the message handler as a tail sentinel to resync with the
  * sender in case data is lost and the fixed-byte messages
  * get out of sync.
  */
-#define MESSAGE_DELIMITER 0xFEEDFACE // required to be 
+#define MESSAGE_SIZE 128
+#define MESSAGE_DELIMITER 0xBEEF
 #define MESSAGE_ESCAPE 0x2a
 struct message {
   uint16_t opcode;
   uint16_t id;
-  uint8_t data[506];
+  uint8_t data[MESSAGE_SIZE - 6];
   uint16_t tail;
 };
 struct message CURRENT_MESSAGE;
@@ -37,8 +38,7 @@
 struct reset {
   uint16_t opcode;
   uint16_t id;
-  uint8_t unused[506];
-  uint16_t tail;
+  uint8_t unused[MESSAGE_SIZE - 4];
 };
 
 #define OPCODE_INIT_TIME (OPCODE_RESET + 1)
@@ -46,8 +46,35 @@
   uint16_t opcode;
   uint16_t id;
   uint32_t cur_raw_time;
-  uint8_t unused[502];
-  uint16_t tail;
+  uint8_t unused[MESSAGE_SIZE - 6];
+};
+
+#define OPCODE_CURRENT_TIME (OPCODE_RESET + 2)
+struct current_time { // we never actually use this, but here for consistency
+  uint16_t opcode;
+  uint16_t id;
+  uint8_t unused[MESSAGE_SIZE - 4];
+};
+
+#define OPCODE_SETMODE_PONG (OPCODE_RESET + 3)
+struct setmode_pong {
+  uint16_t opcode;
+  uint16_t id;
+  uint16_t playfield_width;
+  uint16_t playfield_height;
+  uint16_t paddle_width;
+  uint16_t paddle_offset;
+  uint16_t max_paddle_motion;
+  uint8_t unused[MESSAGE_SIZE - 14];
+};
+
+#define OPCODE_PONG_BALL_STATE (OPCODE_RESET + 4)
+struct pong_ball_state {
+  uint16_t opcode;
+  uint16_t id;
+  uint16_t ball_x;
+  uint16_t ball_y;
+  uint8_t unused[MESSAGE_SIZE - 8];
 };
 
 struct wall_time_struct {
@@ -59,21 +86,113 @@
 };
 struct wall_time_struct WALL_TIME;
 
-
-/*
- * An object used to store app-specific state data.
- */
-struct struct_state {
+struct pong_state_struct {
+  uint16_t playfield_width;
+  uint16_t playfield_height;
+  uint16_t paddle_width;
+  uint16_t paddle_offset;
+  uint16_t max_paddle_motion;
+  uint16_t paddle_x;
+  uint16_t last_ball_x;
+  uint16_t last_ball_y;
 };
-struct struct_state STATE;
+struct pong_state_struct PONG_STATE;
+
+
+void print_current_time() {
+  if (WALL_TIME.initialized) {
+    Serial.print("current_time=");
+    Serial.print(WALL_TIME.hours, DEC);
+    Serial.print(":");
+    if (WALL_TIME.minutes < 10)
+      Serial.print("0");
+    Serial.print(WALL_TIME.minutes, DEC);
+    Serial.print(":");
+    if (WALL_TIME.seconds < 10)
+      Serial.print("0");
+    Serial.println(WALL_TIME.seconds, DEC);
+  } else {
+    Serial.println("current_time=00:00:00");
+  }
+}
+
 
 void handle_current_message() {
+  static uint16_t last_id;
+  static struct setmode_pong* setmode_pong_msg;
+  static struct pong_ball_state* pong_ball_state_msg;
+  static uint16_t paddle_half_width;
+  static uint16_t paddle_max;
+  static uint16_t danger;
+  static uint8_t invert;
+  static uint16_t delta;
+
+  if (CURRENT_MESSAGE.id == 0 || CURRENT_MESSAGE.id == last_id) {
+    return;
+  }
+  last_id = CURRENT_MESSAGE.id;
+
+  switch (CURRENT_MESSAGE.opcode) {
+
+    case OPCODE_SETMODE_PONG:
+      memset(&PONG_STATE, 0, sizeof(PONG_STATE));
+      setmode_pong_msg = (struct setmode_pong*)(&CURRENT_MESSAGE);
+      PONG_STATE.playfield_width = setmode_pong_msg->playfield_width;
+      PONG_STATE.playfield_height = setmode_pong_msg->playfield_height;
+      PONG_STATE.paddle_width = setmode_pong_msg->paddle_width;
+      PONG_STATE.paddle_offset = setmode_pong_msg->paddle_offset;
+      PONG_STATE.max_paddle_motion = setmode_pong_msg->max_paddle_motion;
+
+      paddle_half_width = PONG_STATE.paddle_width / 2;
+      paddle_max = PONG_STATE.playfield_width - paddle_half_width;
+
+      Serial.println("message_type=setmode_pong_ack");
+      Serial.print("id=");
+      Serial.println(CURRENT_MESSAGE.id);
+      print_current_time();
+      Serial.println("");
+      break;
+
+    case OPCODE_PONG_BALL_STATE:
+      pong_ball_state_msg = (struct pong_ball_state*)(&CURRENT_MESSAGE);
+      danger = pong_ball_state_msg->ball_x - PONG_STATE.paddle_x;
+      invert = (danger < 0);
+      danger *= invert ? -1 : 1;
+      if (danger < paddle_half_width) {
+        delta = 0;
+      } else if (danger < PONG_STATE.playfield_width / 3) {
+        delta = PONG_STATE.max_paddle_motion / 3;
+      } else if (danger < PONG_STATE.playfield_width * 2 / 3) {
+        delta = PONG_STATE.max_paddle_motion * 2 / 3;
+      } else {
+        delta = PONG_STATE.max_paddle_motion;
+      }
+      delta *= invert ? 1 : -1;
+      PONG_STATE.paddle_x += delta;
+      if (PONG_STATE.paddle_x < paddle_half_width) {
+        PONG_STATE.paddle_x = paddle_half_width;
+      } else if (PONG_STATE.paddle_x > paddle_max) {
+        PONG_STATE.paddle_x = paddle_max;
+      }
+
+      Serial.println("message_type=pong_paddle_state");
+      Serial.print("id=");
+      Serial.println(CURRENT_MESSAGE.id);
+      print_current_time();
+      Serial.print("paddle_x=");
+      Serial.println(PONG_STATE.paddle_x);
+      Serial.println("");
+      break;
+
+    default:
+      break;
+  }
 }
 
 /* This is a temporary buffer used by the message handler */
 struct message_buffer {
-  uint8_t count; // number of bytes read into the buffer
-  uint8_t buffer[512]; // contents of a 'struct message'
+  uint16_t count; // number of bytes read into the buffer
+  uint8_t buffer[MESSAGE_SIZE]; // contents of a 'struct message'
 };
 struct message_buffer MESSAGE_BUFFER;
 
@@ -85,8 +204,8 @@
 void reset() {
   memset(&WALL_TIME, 0, sizeof(WALL_TIME));
   memset(&CURRENT_MESSAGE, 0, sizeof(CURRENT_MESSAGE));
-  memset(&STATE, 0, sizeof(STATE));
   memset(&MESSAGE_BUFFER, 0, sizeof(MESSAGE_BUFFER));
+  memset(&PONG_STATE, 0, sizeof(PONG_STATE));
 }
 
 
@@ -104,34 +223,47 @@
  * time.
  */
 void pump_message_processor() {
-  static uint16_t cur_byte;
+  static uint8_t cur_byte;
   static uint16_t* cur_word;
   static int8_t delimiter_index;
-  while (Serial.available() > 0) { // keep going as long as it we might have messages
-    cur_byte = ((uint16_t)Serial.read()) & 0x00ff;
+  static char buf[4];
+  while (Serial.available() > 0) { // keep going as long as we might have messages
+    cur_byte = (uint8_t)(Serial.read() & 0x000000ff);
     MESSAGE_BUFFER.buffer[(MESSAGE_BUFFER.count)++] = cur_byte;
-    if (MESSAGE_BUFFER.count >= 512) {
-      if ((uint16_t)(*(MESSAGE_BUFFER.buffer + 510)) != MESSAGE_DELIMITER) {
+    Serial.print("booga ");
+    Serial.print(itoa(MESSAGE_BUFFER.count, buf, 10));
+    Serial.print(" ");
+    Serial.print(itoa(Serial.available(), buf, 10));
+    Serial.print(" ");
+    Serial.println(itoa(cur_byte, buf, 10));
+    if (MESSAGE_BUFFER.count >= MESSAGE_SIZE) {
+      if ((*(uint16_t*)(MESSAGE_BUFFER.buffer + MESSAGE_SIZE - 2)) != MESSAGE_DELIMITER) {
         // whoops, we got out of sync with the transmitter. Scan current
         // buffer for the delimiter, discard previous message, and shift
         // partial next message to front of buffer. This loses a message but
         // gets us back in sync
         delimiter_index = -2;
-        for (int i = 510; i >= 0; --i) {
+        for (int i = MESSAGE_SIZE - 2; i >= 0; --i) {
           if (*((uint16_t*)(MESSAGE_BUFFER.buffer + i)) == MESSAGE_DELIMITER) {
-            if (((i - 1) < 0) || (MESSAGE_BUFFER.buffer[i - 1] != MESSAGE_ESCAPE)) {
+            if (((i - 1) >= 0) && (MESSAGE_BUFFER.buffer[i - 1] != MESSAGE_ESCAPE)) {
               delimiter_index = i;
               break;
             }
           }
         }
+        Serial.print("klaxon ");
+        Serial.println(itoa(delimiter_index, buf, 10));
+        Serial.print("klaxon ");
+        Serial.println(itoa(*((uint16_t*)(MESSAGE_BUFFER.buffer + MESSAGE_SIZE - 2)), buf, 10));
         MESSAGE_BUFFER.count = 0;
-        for (int i = delimiter_index + 2; i < 512; ++i, ++(MESSAGE_BUFFER.count)) {
-          MESSAGE_BUFFER.buffer[MESSAGE_BUFFER.count] = MESSAGE_BUFFER.buffer[i];
+        if (delimiter_index >= 0) {
+          for (int i = delimiter_index + 2; i < MESSAGE_SIZE; ++i, ++(MESSAGE_BUFFER.count)) {
+            MESSAGE_BUFFER.buffer[MESSAGE_BUFFER.count] = MESSAGE_BUFFER.buffer[i];
+          }
         }
-        memset(MESSAGE_BUFFER.buffer + MESSAGE_BUFFER.count, 0, 512 - MESSAGE_BUFFER.count);
+        memset(MESSAGE_BUFFER.buffer + MESSAGE_BUFFER.count, 0, MESSAGE_SIZE - MESSAGE_BUFFER.count);
       } else {
-        memcpy(&CURRENT_MESSAGE, MESSAGE_BUFFER.buffer, 512);
+        memcpy(&CURRENT_MESSAGE, MESSAGE_BUFFER.buffer, MESSAGE_SIZE);
         memset(&MESSAGE_BUFFER, 0, sizeof(MESSAGE_BUFFER));
         switch (CURRENT_MESSAGE.opcode) {
           case OPCODE_RESET:
@@ -143,9 +275,25 @@
             // out the current time
             WALL_TIME.raw = ((struct init_time*)(&CURRENT_MESSAGE))->cur_raw_time;
             WALL_TIME.initialized = 1;
+
+            Serial.println("message_type=init_time_ack");
+            Serial.print("id=");
+            Serial.println(CURRENT_MESSAGE.id);
+            print_current_time();
+            Serial.println("");
+
             CURRENT_MESSAGE.id = 0;
             break;
 
+          case OPCODE_CURRENT_TIME:
+            Serial.println("message_type=current_time_ack");
+            Serial.print("id=");
+            Serial.println(CURRENT_MESSAGE.id);
+            print_current_time();
+            Serial.println("");
+
+            CURRENT_MESSAGE.id = 0;
+
           default:
             // no-op -- actually means main loop will handle it
             break;
@@ -155,29 +303,6 @@
   }
 }
 
-
-/* Dumps the full state of the system for the other side to peruse. Because we dump our state
- * periodically, we don't need to worry about responding to commands -- the other side can
- * just monitor for changes in state.
- */
-void dump_state() {
-  Serial.print("current_time=");
-  Serial.print(WALL_TIME.hours, DEC);
-  Serial.print(":");
-  if (WALL_TIME.minutes < 10)
-    Serial.print("0");
-  Serial.print(WALL_TIME.minutes, DEC);
-  Serial.print(":");
-  if (WALL_TIME.seconds < 10)
-    Serial.print("0");
-  Serial.println(WALL_TIME.seconds, DEC);
-
-  // TODO
-
-  Serial.println("");
-}
-
-
 /*
  * Pumps the system wall clock. This checks the device's monotonic clock to
  * determine elapsed time since last invocation, and updates wall clock time
@@ -190,8 +315,14 @@
  */
 void pump_clock() {
   static uint32_t prev_millis = 0;
+  static uint32_t tmp_prev_millis = 0;
   uint32_t tmp = 0;
 
+  if (millis() / 1000 != tmp_prev_millis) {
+    tmp_prev_millis = millis() / 1000;
+    print_current_time();
+  }
+
   if (WALL_TIME.initialized) {
     tmp = millis() / 1000;
     if (tmp != prev_millis) {