Initial commit of a helper stub for the Arduino code to be used in tandem with
the CTS Verifier. Builds and should flash, but does nothing, currently.

Change-Id: I5fc8222e18094d8c5270e34b369074ab0367101b
diff --git a/apps/CtsVerifier/arduino-helper/arduino-helper.pde b/apps/CtsVerifier/arduino-helper/arduino-helper.pde
new file mode 100644
index 0000000..5649972
--- /dev/null
+++ b/apps/CtsVerifier/arduino-helper/arduino-helper.pde
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2010 The Android Open-Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/*
+ * 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.
+ * 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_ESCAPE 0x2a
+struct message {
+  uint16_t opcode;
+  uint16_t id;
+  uint8_t data[506];
+  uint16_t tail;
+};
+struct message CURRENT_MESSAGE;
+
+#define OPCODE_RESET 0x00
+struct reset {
+  uint16_t opcode;
+  uint16_t id;
+  uint8_t unused[506];
+  uint16_t tail;
+};
+
+#define OPCODE_INIT_TIME (OPCODE_RESET + 1)
+struct init_time {
+  uint16_t opcode;
+  uint16_t id;
+  uint32_t cur_raw_time;
+  uint8_t unused[502];
+  uint16_t tail;
+};
+
+struct wall_time_struct {
+  uint32_t raw; // long == 4-byte on AVR
+  uint8_t initialized;
+  uint8_t hours;
+  uint8_t minutes;
+  uint8_t seconds;
+};
+struct wall_time_struct WALL_TIME;
+
+
+/*
+ * An object used to store app-specific state data.
+ */
+struct struct_state {
+};
+struct struct_state STATE;
+
+void handle_current_message() {
+}
+
+/* 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'
+};
+struct message_buffer MESSAGE_BUFFER;
+
+/*
+ * Clears all stateful values, including the wall clock time, current message
+ * data, and user/app state. Also clears the message handler's buffer. By
+ * "clear" we mean "memset to 0".
+ */
+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));
+}
+
+
+/*
+ * Pumps the message processor. That is, this function is intended to be
+ * called once per loop to read all pending Serial/TTL data, and decode a
+ * message from the peer if one is complete. In cases where data is corrupted
+ * (such as by dropping bytes), this function also attempts to re-sync with
+ * the host by discarding messages until it finds a MESSAGE_DELIMITER, after
+ * which is resyncs its buffer on the first subsequent byte.
+ *
+ * This functional also handles two low-level 'system' messages: a reset
+ * instruction which invokes reset(), and an init_time instruction which
+ * provides the soft clock with the current time so that it can start keeping
+ * time.
+ */
+void pump_message_processor() {
+  static uint16_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;
+    MESSAGE_BUFFER.buffer[(MESSAGE_BUFFER.count)++] = cur_byte;
+    if (MESSAGE_BUFFER.count >= 512) {
+      if ((uint16_t)(*(MESSAGE_BUFFER.buffer + 510)) != 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) {
+          if (*((uint16_t*)(MESSAGE_BUFFER.buffer + i)) == MESSAGE_DELIMITER) {
+            if (((i - 1) < 0) || (MESSAGE_BUFFER.buffer[i - 1] != MESSAGE_ESCAPE)) {
+              delimiter_index = i;
+              break;
+            }
+          }
+        }
+        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];
+        }
+        memset(MESSAGE_BUFFER.buffer + MESSAGE_BUFFER.count, 0, 512 - MESSAGE_BUFFER.count);
+      } else {
+        memcpy(&CURRENT_MESSAGE, MESSAGE_BUFFER.buffer, 512);
+        memset(&MESSAGE_BUFFER, 0, sizeof(MESSAGE_BUFFER));
+        switch (CURRENT_MESSAGE.opcode) {
+          case OPCODE_RESET:
+            reset();
+            return;
+
+          case OPCODE_INIT_TIME:
+            // cast CURRENT_MESSAGE to our time struct to conveniently fetch
+            // out the current time
+            WALL_TIME.raw = ((struct init_time*)(&CURRENT_MESSAGE))->cur_raw_time;
+            WALL_TIME.initialized = 1;
+            CURRENT_MESSAGE.id = 0;
+            break;
+
+          default:
+            // no-op -- actually means main loop will handle it
+            break;
+        }
+      }
+    }
+  }
+}
+
+
+/* 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
+ * by dead reckoning. Since the device has no battery backup, a power-off will
+ * lose the current time, so timekeeping cannot begin until an INIT_TIME
+ * message is received. (The pump_message_processor() function handles that.)
+ *
+ * Once timekeeping is underway, current time is exposed to user/app code via
+ * the WALL_TIME object, which has 24-hour HH/MM/SS fields.
+ */
+void pump_clock() {
+  static uint32_t prev_millis = 0;
+  uint32_t tmp = 0;
+
+  if (WALL_TIME.initialized) {
+    tmp = millis() / 1000;
+    if (tmp != prev_millis) {
+      prev_millis = tmp;
+      WALL_TIME.raw++;
+    }
+    WALL_TIME.seconds = WALL_TIME.raw % 60;
+    WALL_TIME.minutes = (WALL_TIME.raw / 60) % 60;
+    WALL_TIME.hours = (WALL_TIME.raw / (60 * 60)) % 24;
+  }
+}
+
+
+/*
+ * Standard Arduino setup hook.
+ */
+void setup() {
+  Serial.begin(115200);
+}
+
+
+/*
+ * Standard Arduino loop-pump hook.
+ */
+void loop() {
+  static uint16_t last_id = 0;
+
+  // pump the clock and message processor
+  pump_clock();
+  pump_message_processor();
+  
+  // ignore any "system" messages (those with ID == 0) but dispatch app messages
+  if ((last_id != CURRENT_MESSAGE.id) && (CURRENT_MESSAGE.id != 0)) {
+    handle_current_message();
+  }
+  last_id = CURRENT_MESSAGE.id;
+}