commit 1085ef7751b530b21865d0ca7d23786578749364
Author: Tom Mullins <tmullins@andrew.cmu.edu>
Date:   Sun Dec 2 17:11:51 2012 -0500

    Made rfid.c more robust against false negatives
    
    Also changed LED code to be more generally usable, and changed mainbox
    to grant access to a particular user id instead of randomly choosing

diff --git a/mainbox/tool.c b/mainbox/tool.c
index 0ea13d4..c3f4d6b 100644
--- a/mainbox/tool.c
+++ b/mainbox/tool.c
@@ -102,7 +102,7 @@ void tool_poll(struct tool_t *tool) {
       if (status[MB_COIL_NEW]) {
         tool_read_user(tool);
         // TODO check actual credentials
-        if (rand() & 1) {
+        if (tool->user == 0x023acbf6) {
           tool_grant_access(tool);
         } else {
           tool_deny_access(tool);
diff --git a/toolbox/led.c b/toolbox/led.c
index 9d9b41b..3a1a3d0 100644
--- a/toolbox/led.c
+++ b/toolbox/led.c
@@ -9,16 +9,34 @@
 #define OCR (F_CPU / PRESCALE / 1000UL)
 #define ERROR (F_CPU / PRESCALE - OCR * 1000UL)
 
-char count;
-uint16_t period;
+char blink_count;
+enum color_t blink_color;
+uint16_t blink_period;
 
 uint16_t ms;
 uint16_t error;
 
+static void led_color(enum color_t color) {
+  switch (color) {
+    case OFF:
+      led_off();
+      break;
+    case RED:
+      led_red();
+      break;
+    case YELLOW:
+      led_yellow();
+      break;
+    case GREEN:
+      led_green();
+      break;
+  }
+}
+
 static void blink() {
-  count--;
-  if (count % 2) {
-    led_yellow();
+  blink_count--;
+  if (blink_count % 2) {
+    led_color(blink_color);
   } else {
     led_off();
   }
@@ -30,9 +48,9 @@ ISR(TIMER0_COMPA_vect) {
     error -= 1000;
   } else {
     ms++;
-    if (ms == period) {
+    if (ms == blink_period) {
       blink();
-      if (count == 0) {
+      if (blink_count == 0) {
         TCCR0B = 0;
       }
       ms = 0;
@@ -40,18 +58,23 @@ ISR(TIMER0_COMPA_vect) {
   }
 }
 
-void led_blink_start(unsigned int period_ms, char n_times) {
-  led_yellow();
+void led_blink_start(unsigned int period_ms, char n_times, enum color_t color) {
+
   ms = 0;
   error = 0;
-  count = n_times*2-1;
-  period = period_ms/2;
+
+  blink_count = n_times*2-1;
+  blink_period = period_ms/2;
+  blink_color = color;
+  led_color(color);
+
   OCR0A = OCR;
   TIMSK = _BV(OCIE0A);
   TCCR0A = _BV(WGM01);
   TCCR0B = CLOCK_SEL;
+
 }
 
 char led_blink_done() {
-  return count == 0;
+  return blink_count == 0;
 }
diff --git a/toolbox/led.h b/toolbox/led.h
index ce15651..a6963d4 100644
--- a/toolbox/led.h
+++ b/toolbox/led.h
@@ -3,6 +3,10 @@
 
 #include <avr/io.h>
 
+enum color_t {
+  OFF, RED, YELLOW, GREEN
+};
+
 static inline void led_init() {DDRC |= _BV(DDC1) | _BV(DDC0);}
 static inline void led_off() {PORTC &= ~(_BV(PC1) | _BV(PC0));}
 static inline void led_red() {PORTC = (PORTC & ~_BV(PC0)) | _BV(PC1);}
@@ -10,7 +14,7 @@ static inline void led_yellow() {PORTC |= _BV(PC1) | _BV(PC0);}
 static inline void led_green() {PORTC = (PORTC & ~_BV(PC1)) | _BV(PC0);}
 
 /* Starts LED blinking */ 
-void led_blink_start(unsigned int period_ms, char n_times);
+void led_blink_start(unsigned int period_ms, char n_times, enum color_t color);
 
 /* Returns nonzero if blinking has finished */
 char led_blink_done();
diff --git a/toolbox/main.c b/toolbox/main.c
index 78596eb..8b727ff 100644
--- a/toolbox/main.c
+++ b/toolbox/main.c
@@ -33,7 +33,7 @@ static inline void tool_init() {DDRA |= _BV(DDA1);}
 static inline void tool_enable() {PORTA |= _BV(PA1);}
 static inline void tool_disable() {PORTA &= ~ _BV(PA1);}
 
-static char serno_zero(uint8_t *serno) {
+static inline void serno_zero(uint8_t *serno) {
   memset(serno, 0, RFID_SERNO_SIZE);
 }
 
@@ -131,7 +131,7 @@ static void tool_main() {
         toolstate = TS_REQ_DIS;
       } else if (!serno_equal(current_user, latest_reading)) {
         toolstate = TS_MISSING_ID;
-        led_blink_start(666, 6);
+        led_blink_start(666, 15, YELLOW);
       }
       break;
 
diff --git a/toolbox/rfid.c b/toolbox/rfid.c
index 8615c30..250744f 100644
--- a/toolbox/rfid.c
+++ b/toolbox/rfid.c
@@ -4,9 +4,11 @@
 #include "rfid.h"
 #include "serial.h"
 
+#define RFID_OK 1
 static uint8_t read_cmd[] = {'!', 'R', 'W', 1, 32};
 
 static int serno_idx;
+static char n_failures;
 static uint8_t serno[RFID_SERNO_SIZE];
 
 static void zero_serno() {
@@ -20,12 +22,16 @@ void rfid_init() {
   serial_init();
 }
 
-void rfid_start_read() {
+static void restart_read() {
   serno_idx = -1;
-  serial_flush();
   serial_write(read_cmd, sizeof(read_cmd));
 }
 
+void rfid_start_read() {
+  n_failures = 0;
+  restart_read();
+}
+
 char rfid_poll() {
   int c;
 
@@ -33,8 +39,14 @@ char rfid_poll() {
 
     if (serno_idx < 0) {
       if (c != RFID_OK) {
-        zero_serno();
-        return 1;
+        n_failures++;
+        if (n_failures >= RFID_N_FAILURES) {
+          zero_serno();
+          return 1;
+        } else {
+          restart_read();
+          return 0;
+        }
       }
     } else {
       serno[serno_idx] = c;
diff --git a/toolbox/rfid.h b/toolbox/rfid.h
index f1f7266..01d3068 100644
--- a/toolbox/rfid.h
+++ b/toolbox/rfid.h
@@ -1,16 +1,11 @@
 #ifndef RFID_H
 #define RFID_H
 
-/* First byte back from rfid reader */
-#define RFID_OK 1
-
 /* Bytes in serial number on rfid tags */
 #define RFID_SERNO_SIZE 4
 
-/* In rfid_read_safe, it must read the same value RFID_MIN_OK times. If it
- * encounters RFID_MAX_ERRS read errors first, it will output all 0's. */
-#define RFID_MAX_ERRS 10
-#define RFID_MIN_OK 5
+/* Number of consective read failures before giving up and returning all 0s */
+#define RFID_N_FAILURES 5
 
 /* Should be called before anything else */
 void rfid_init();
@@ -24,18 +19,10 @@ void rfid_start_read();
  * rfid_get_serno can be called */
 char rfid_poll();
 
-/* Attempts to read the serial number multiple times, and only accepts it if it
- * is the same every time. Don't use it */
-void rfid_read_safe();
-
 /* Call this only after rfid_poll returns nonzero. This will copy the value it
  * read into serno, which should be at least RFID_SERNO_SIZE bytes */
 void rfid_get_serno(uint8_t *serno);
 
-/* Call this only after rfid_poll returns nonzero. Returns 1 if serno matches
- * the internal buffer of the most recently read serial number */
-char rfid_check_serno(uint8_t *serno);
-
 /* Call this only after rfid_poll returns nonzero. Returns 1 if the internal
  * buffer is nonzero, meaning a serial number was successfully read from an
  * rfid tag */
