Super Vision / Mbed 2 deprecated sv_usb_firmware

Dependencies:   MODSERIAL USBDevice_for_Rev_C_HW mbed

Fork of mbed_sv_firmware_with_init by Bob Recny

Revision:
22:5707b236cbdb
Parent:
19:d3bef4fbab69
Child:
23:52504c8f63c5
--- a/main.cpp	Thu Apr 02 20:17:21 2015 +0000
+++ b/main.cpp	Fri Jun 05 01:52:30 2015 +0000
@@ -1,24 +1,44 @@
-/**
+ /**
+ * Copyright (c) 2015 The Positive Charge, LLC for Supervision, LLC
  * @file   main.cpp
- * @date   January 2015
+ * @date   2015-06-04
  * @brief  Freescale KL25Z firmware for USB-RFID adapter
  *
- * This firmware provided communication from a PC's USB host port to the following peripherals:
+ * This firmware provides communication from a PC's USB host port to the following peripherals:
  *  RFID-FE over UART - SuperVision RFID reader module
  *  VL6180X over I2C - ST Microelectronics proximity and ambient light sensor
  *  GPIO - two LEDs and several control signals for the RFID module
  *  EEPROM - over I2C - Generic 24LC16B (untested since first revision prototype hardware does not have an EEPROM)
+ *
+ * Revision History
+ * 2014-11-01
+ * For Rev A Hardware - No EEPROM, single-byte GPIO
+ *
+ * 2015-03-01
+ * For Rev B and C Hardware - Includes EEPROM, single-byte GPIO
+ *
+ * 2015-06-04
+ * For Rev C Hardware - Includes EEPROM, 2-byte GPIO allows extra pins on LED connector to be used.
+ *                    - Includes EEPROM storage of USB string descriptors and RFID command for Proximity interrupt
+ *                    - Includes USB initialization update and added code to send RFID command on Proximity interrupt
+ *
  */
 
+// mbed.org headers
+#include "mbed.h"                       // main mbed.org libraries
+#include "USBDevice.h"
+#include "USBSerial.h"                  // USB CDC drivers
+#include "MODSERIAL.h"                  // UART drivers - MODSERIAL allows block writes compared to the mbed driver
 
-#include "mbed.h"
-#include "USBSerial.h"
-#include "MODSERIAL.h"
+// Supervision-specific headers
+#include "SV_USBConfig.h"               // Default USB strings for initial power-up.
+#include "ProxInit.h"                   // VL6180X default initial values - *not* calibrated
 
 // Constants
 #define LEDON       0                   // Low active for LEDs - turns LED on
 #define LEDOFF      1                   // Low active for LEDs - turns LED off
-#define TRUE        1
+
+#define TRUE        1                   // Boolean true and false
 #define FALSE       0
 
 // Error return values
@@ -29,9 +49,10 @@
 #define ERR_UART_NOT_READABLE   0xB2    // UART has no buffer space
 #define ERR_UART_NO_TX_ENDMARK  0xB3    // message for UART has no 0x7E end-mark
 #define ERR_UART_NO_RX_ENDMARK  0xB4    // message received from UART has no end-mark
-#define ERR_I2C_NOT_WRITEABLE   0xC1    // UART has no buffer space
-#define ERR_I2C_NO_TX_ENDMARK   0xC2    // message for UART has no 0x7E end-mark
-#define ERR_I2C_NO_RX_ENDMARK   0xC3    // message received from UART has no end-mark
+#define ERR_I2C_NOT_WRITEABLE   0xC1    // I2C has no buffer space
+#define ERR_I2C_NO_TX_ENDMARK   0xC2    // message for I2C has no 0x7E end-mark
+#define ERR_I2C_NO_RX_ENDMARK   0xC3    // message received from I2C has no end-mark
+#define ERR_I2C_WRITE_TOO_LARGE 0x16    // message for I2C write is too large (16 bytes max)
 #define ERR_NOT_IMPLEMENTED     0xFF    // method has not yet been implemented
 
 // I2C addresses and parameters
@@ -41,11 +62,11 @@
 
 // UART-RFID baud rate
 #define RFIDBAUD                115200  // RFID-FE board default rate = 115.2Kbps
-#define BUFFERSIZE              128      // default buffer sizes
+#define BUFFERSIZE              128     // default buffer sizes
 #define RFIDLENLOW              5       // RFID message length location (length is 2 bytes)
 
 // Peripherals
-USBSerial cdc;                          // CDC Class USB<>Serial adapter.  Needs custom INF, but uses existing Windows drivers.
+USBSerial cdc;                          // CDC Class USB-Serial adapter.  Needs custom INF, but uses existing Windows CDC drivers.
 MODSERIAL uart(PTA2, PTA1);             // UART port connected to RFID-FE board
 I2C i2c(PTB1, PTB0);                    // I2C port connected to VL6180X and EEPROM - note addresses above)
 
@@ -58,25 +79,107 @@
 DigitalOut rfid_pwr(PTE30);             // RFID power switch on USB board (active high for prototype 1, low for all others)
 DigitalIn rfid_hot(PTE0);               // RFID over-current detection on USB board power switch (active low)
 InterruptIn prox_int(PTD7);             // Proximity sensor interrupt (active low)
+DigitalOut ee_wp(PTC5);                 // EEPROM Write Protect (active high)
 
 DigitalInOut gpio_0(PTC3);              // Extra GPIO on LED connector, pin 6
 DigitalInOut gpio_1(PTC4);              // Extra GPIO on LED connector, pin 7
 DigitalOut gpio_7(PTA4);                // Extra GPIO output on LED connector, pin 3 - pin supports PWM for buzzer, not implemented here
 
-// buffers & variables
+// global buffers & variables
+uint8_t led_com_state = LEDOFF;         // initial LED state
+uint8_t prox_irq_state = 0;             // interrupt state passed from service routine
+uint8_t usb_irq_state = 0;              // interrupt state passed from service routine
 uint8_t gpio_values = 0x00;             // register to read GPIO values
-uint8_t cdc_buffer_rx[BUFFERSIZE];      // buffers for cdc (USB-Serial port on PC)          
+uint8_t cdc_buffer_rx[BUFFERSIZE];      // buffers for cdc (USB-Serial port on PC)
 uint8_t cdc_buffer_tx[BUFFERSIZE];
 uint8_t uart_buffer_rx[BUFFERSIZE];     // buffers for uart (RFID-FE board)
 uint8_t uart_buffer_tx[BUFFERSIZE];
 uint8_t gpio_buffer[BUFFERSIZE];        // buffer for GPIO messages
-char i2c_buffer[BUFFERSIZE];            // buffer for I2C devices - Proximity sensor and EEPROM - up to 256 bytes data payload for EEPROM, up to 4 for proximity
-int i, j;                               // index variables
+
+char i2c_buffer[BUFFERSIZE];            // buffer for I2C devices - Proximity sensor and EEPROM - up to BUFFERSIZE bytes data payload for EEPROM, up to 4 for proximity
+char prox_irq_msg[BUFFERSIZE];          // buffer for automatic RFID message on proximity interrupt
+
+int i, j;                               // general index variables
 int status = 0x00;                      // return value
-uint8_t led_com_state = LEDOFF;         // initial LED state
-uint8_t prox_irq_state = 0;             // interrupt state passed from service routine
-uint8_t usb_irq_state = 0;              // interrupt state passed from service routine
+
+// USB config descriptor strings
+// These are held in SV_USBConfig.h, and only used during initial bring-up after manufacturing
+
+char mfg_str[0x2E] = {SV_MFG};          // Default USB strings - Manufacturer
+char mfg_str_cnt = SV_MFG_CNT;
+char ser_str[0x2E] = {SV_SER};          // Default USB strings - Serial Number
+char ser_str_cnt = SV_SER_CNT;
+char des_str[0x3E] = {SV_DES};          // Default USB strings - Product Description
+char des_str_cnt = SV_DES_CNT;
+
+// These next functions are modified from the original USBDevice.cpp and USBCDC.cpp mbed drivers
+// in order to allow custom USB descriptor strings.
+
+/**
+ * @name    USBDevice::stringImanufacturerDesc
+ * @name    USBDevice::stringIserialDesc
+ * @name    USBDevice::stringIproductDesc
+ * @name    USBCDC::stringIproductDesc
+ * @brief   Sets custom USB Config Descriptor Strings
+ *
+ *  These methods are modified from the original to allow custom USB config descriptor strings.
+ *  The original (in USBDevice.cpp and USBCDC.cpp) are hard-coded for generic mbed.org values 
+ *  The values used in these methods are read from the EEPROM.  Especially important is allowing
+ *  a custom USB Serial Number, which will be written to the EEPROM during the factory test.
+ *
+ * @param [in] none
+ * @retval stringImanufacturerDescriptor
+ * @retval stringIserialDescriptor
+ * @retval stringIproductDescriptor
+ * @retval stringIproductDescriptor
+ */
+
 
+// MODIFIED to allow custom strings
+uint8_t * USBDevice::stringImanufacturerDesc() {
+    static uint8_t stringImanufacturerDescriptor[0x30];
+    stringImanufacturerDescriptor[0] = mfg_str_cnt;
+    stringImanufacturerDescriptor[1] = STRING_DESCRIPTOR;
+    for (int i = 0; i < sizeof(mfg_str); i++){
+        stringImanufacturerDescriptor[i+2] = mfg_str[i];
+    }
+    return stringImanufacturerDescriptor;
+}
+
+// MODIFIED to allow custom strings
+
+uint8_t * USBDevice::stringIserialDesc() {
+    static uint8_t stringIserialDescriptor[0x30];
+    stringIserialDescriptor[0] = ser_str_cnt;
+    stringIserialDescriptor[1] = STRING_DESCRIPTOR;
+    for (int i = 0; i < sizeof(ser_str); i++){
+        stringIserialDescriptor[i+2] = ser_str[i];
+    }
+    return stringIserialDescriptor;
+}
+
+// MODIFIED to allow custom strings
+uint8_t * USBDevice::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[0x40];
+    stringIproductDescriptor[0] = des_str_cnt;
+    stringIproductDescriptor[1] = STRING_DESCRIPTOR;
+    for (int i = 0; i < sizeof(des_str); i++){
+        stringIproductDescriptor[i+2] = des_str[i];
+    }
+    return stringIproductDescriptor;
+}
+
+
+// MODIFIED to allow custom strings
+uint8_t * USBCDC::stringIproductDesc() {
+    static uint8_t stringIproductDescriptor[0x40];
+    stringIproductDescriptor[0] = des_str_cnt;
+    stringIproductDescriptor[1] = STRING_DESCRIPTOR;
+    for (int i = 0; i < sizeof(des_str); i++){
+        stringIproductDescriptor[i+2] = des_str[i];
+    }
+    return stringIproductDescriptor;
+}
 
 /**
  * @name    prox_irq
@@ -89,8 +192,17 @@
 void prox_irq(void)
 {
     prox_irq_state = 1;
+    led_com.write(LEDON);                                           // Turn on COM LED until interrupt is serviced
 }
 
+/**
+ * @name    usb_irq
+ * @brief   Sets interrupt variable for use in the main loop.
+ * The interrupt is triggered when the host PC has sent data to the CDC port.
+ *
+ * @param [in] none
+ * @param [out] usb_irq_state = 1 indicates an interrupt occured.
+ */
 void usb_irq(void)
 {
     usb_irq_state = 1;
@@ -100,51 +212,154 @@
  * @name    init_periph
  * @brief   Initializes the KL25Z peripheal interfaces
  * KL25Z interfaces:
- *  UART - connects to SuperVision RFID-FE module
- *  I2C - connects to the ST VL6180X proximity/ambient light sensor device and a 24LC16B EEPROM (future)
- *  GPIO - includes two LEDs and signals to control RFID reader.
+ *  USB - Initializes USB config descriptors
+ *  UART - Connects to SuperVision RFID-FE module
+ *  I2C - Configures to the ST VL6180X proximity/ambient light sensor device 
+ *  I2C - Reads configuration data from EEPROM
+ *  GPIO - Includes two LEDs and signals to control RFID reader.
  *
  * @param [in] none
- * @param [out] none
- * 
- * @retval ERR_NONE     No error
+ * @param [out] error status (0 = no error)
+ *
+ * @retval error state
  */
- int init_periph(void)
+int init_periph(void)
 {
-    // Set up peripherals
+    int i2c_err;                                                    // return value
+    char temploc = 0x00;                                            // temporary values
+    char temp[] = {0,0};
+    char i2c_page = 0;
+    char prox_ee[254] = {0};                                        // buffer for Proximity initialization values stored
+                                                                    // in EEPROM, especially the cover glass calibration
+    // Set up peripherals on KL25Z
+
+    led_err.write(LEDOFF);                                          // Start with leds
+    led_com.write(LEDOFF);
+
+    // Check EEPROM for programmed USB string descriptors.  These are held in BANK ZERO (I2C address = EEPROM | 0 << 1)
+    // Factory test should initialize the EEPROM
+    //
+    // First two bytes of bank zero will be "SV" if programmed.
+    // Bank 0x10 holds Manufacturer string
+    // Bank 0x40 holds Serial Number string
+    // Bank 0x70 holds Product Description string
+
+    i2c_page = EEPROM | 0 << 1;                                     // set EEPROM page = bank 0
+    i2c.write(i2c_page, &temploc, 1, 1);                            // i2c address+bank 0, memory index, 1 byte (just index), no stop at end.
+    i2c.read(i2c_page, temp, 2, 0);                                 // i2c address+bank 0, variable location, 2 bytes (just data), stop at end.
+    
+    if ((temp[0] == 'S') && (temp[1] == 'V')) {
+        led_com.write(LEDON);
+        
+        // Read Manufacturer String
+        temploc = 0x10;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, count index, 1 byte, no stop at end
+        i2c.read(i2c_page, &mfg_str_cnt, 1, 0);                     // i2c address+bank 0, mfg string size, 1 byte, stop at end
+        temploc = 0x11;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, memory index, 1 byte, no stop at end
+        i2c.read(i2c_page, mfg_str, mfg_str_cnt, 0);                // i2c address+bank 0, mfg string, string size, stop at end
+        
+        // Read Serial Number string
+        temploc = 0x40;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, memory index, 1 byte no stop at end
+        i2c.read(i2c_page, &ser_str_cnt, 1, 0);                     // i2c address+bank 0, serial number string size, 1 byte, stop at end
+        temploc = 0x41;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, memory index, 1 byte, no stop at end
+        i2c.read(i2c_page, ser_str, ser_str_cnt, 0);                // i2c address+bank 0, serial number string, string size, stop at end
+        
+        // Read Product Description String
+        temploc = 0x70;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, memory index, 1 byte, no stop at end
+        i2c.read(i2c_page, &des_str_cnt, 1, 0);                     // i2c address+bank 0, description string size, 1 byte, stop at end
+        temploc = 0x71;
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 0, memory index, 1 byte, no stop at end
+        i2c.read(i2c_page, des_str, des_str_cnt, 0);                // i2c address+bank 0, description string, string size, stop at end
+        led_com.write(LEDOFF);
+
+    }
+
+    // Prox & EEPROM
+    ee_wp.write(0);                                                 // no write protection on EEPROM
+    i2c.frequency(I2CRATE);                                         // I2C speed = 400Kbps
+  
+    // Get the VL6180X register values from the ProxInit.h header and program them to the Proximity Sensor (from VL6180X app notes)
+
+    for (i = 0; i < sizeof(proxinit); i += 3){                      // Initialize VL6180X with default values, calibration data sent later
+        i2c_err = i2c.write(PROX, &proxinit[i], 3, 0);              // I2C Address, pointer to buffer, number of bytes (for index + data), stop at end.
+                                                                    // also includes taking off the "Fresh out of Reset" flag.
+        if (i2c_err){
+            led_err.write(LEDON);                                   // Turn on both LEDs
+            led_com.write(LEDON);                                   // We can't write to the proximity sensor
+            return i2c_err;
+        }
+    }
+    
+    // Get Supervision-specific register values and program them to the Proximity Sensor (calibration, other operating features)
+    
+    i2c_page = EEPROM | 1 << 1;                                     // set EEPROM page = bank 1
+    temploc = 0;
+    i2c.write(i2c_page, &temploc, 1, 1);                            // i2c address+bank 1, memory index, 1 byte (just index), no stop at end.
+    i2c.read(i2c_page, temp, 2, 0);                                 // i2c address+bank 1, variable location, 2 bytes (just data), stop at end.
+    
+    if ((temp[0] == 'S') && (temp[1] == 'V')) {
+        led_com.write(LEDON);
+        // Read values
+        temploc = 0x02;                                             // Values start here.  Since this section is mostly one-byte values with two-byte
+                                                                    //                     addresses, 2- and 4-byte registers are individually addressed    
+        i2c.write(i2c_page, &temploc, 1, 1);                        // i2c address+bank 1, location 2, 1 byte, no stop at end - read the whole bank
+        i2c.read(i2c_page, prox_ee, sizeof(prox_ee), 0);            // i2c address+bank 1, buffer location, 1 byte, stop at end
+        for (i = 0; i < sizeof(prox_ee); i += 3){                   // Initialize VL6180X with default values, calibration data sent later
+            if ((prox_ee[i] == 0xFF) && (prox_ee[i+1] == 0xFF)){
+                break;                                              // No more values are in the EEPROM (blank / erased = 0xFF)
+            }
+            else {
+                i2c_err = i2c.write(PROX, &prox_ee[i], 3, 0);       // I2C Address, pointer to buffer, number of bytes (for index + data), stop at end.
+                                                                    // also includes taking off the "Fresh out of Reset" flag.
+                if (i2c_err){
+                    led_err.write(LEDON);                           // Turn on both LEDs
+                    led_com.write(LEDON);                           // We can't write to the proximity sensor
+                    return i2c_err;
+                }
+            }
+        }
+        led_com.write(LEDOFF);
+    }
+
+    // Enable the Proximity interrupt
+    prox_int.mode(PullUp);                                          // pull up proximity sensor interrupt at MCU
+    prox_int.fall(&prox_irq);                                       // VL6180X interrupt is low active
+    prox_int.enable_irq();                                          // Enable proximity interrupt inputs
+
+    // "Fresh-out-of-reset" register was automatically set to 0x01 after boot
+    prox_ee[0] = 0x00;                                              
+    prox_ee[1] = 0x16;
+    prox_ee[2] = 0x00;
+    i2c.write(PROX, prox_ee, 3, 0);                                 // Remove "Fresh out of Reset" flag to allow normal operation
+
+    cdc.attach(&usb_irq);                                           // Attach USB interrupt
+    usb_irq_state = 0;                                              // Ensure interrupt flag is not set after setup
+  
     // RFID
     uart.baud(RFIDBAUD);                                            // RFID-FE baud rate
-    
-    cdc.attach(&usb_irq);
-    
+
     rfid_int = 0;                                                   // RFID FE power control (active high)
     rfid_isp = 0;                                                   // RFID FE In-System Programming (active high)
     rfid_rst = 1;                                                   // RFID FE Reset (active high)
-//    rfid_pwr = 1;                                                   // RFID power switch on USB board (active high for prototype 1)
     rfid_pwr = 0;                                                   // RFID power switch on USB board (active low for all others)
     wait(0.25);                                                     // wait 250ms before...
     rfid_rst = 0;                                                   // ... taking RFID out of reset
     wait(0.25);
-    
-    while(!uart.readable())                                           // wait for RESET message from RFID
-    {
+
+    while(!uart.readable()) {                                       // wait for RESET message from RFID
         led_err.write(LEDON);                                       // flash LED until it arrives
-        wait(0.1);
+        wait(0.1);                                                  // This is a good way to see if the RFID cable is properly seated
         led_err.write(LEDOFF);
         wait(0.1);
-    }                                           
-    
-    uart.txBufferFlush();                                           // clear out UART buffers
+    }
+
+    uart.txBufferFlush();                                           // clear out UART buffers - we don't need the reset message
     uart.rxBufferFlush();
-    
-    led_err.write(LEDOFF);
-        
-    // Prox & EEPROM
-    i2c.frequency(I2CRATE);                                         // I2C speed = 400Kbps
-    prox_int.mode(PullUp);                                          // pull up proximity sensor interrupt at MCU
-    prox_int.fall(&prox_irq);                                       // VL6180X interrupt is low active
-    prox_int.enable_irq();                                          // Enable proximity interrupt inputs
-    
+
     // LEDs                                                         // Cycle through the LEDs.
     led_err.write(LEDON);
     led_com.write(LEDON);
@@ -152,67 +367,63 @@
     led_err.write(LEDOFF);
     wait(0.5);
     led_com.write(LEDOFF);
-    
+
     return ERR_NONE;
 }
 
 /**
  * @name    rfid_wr
- * @brief   Forwards command to RFID reader 
+ * @brief   Forwards command to RFID reader
  *
  * RFID reader is connected to the KL25Z UART interface.  The host PC will have a USB CDC class COM port device driver.
- * The host PC sends the RFID command over the COM port.  Messages destined for the RFID reader (0xBB leading byte) are 
+ * The host PC sends the RFID command over the COM port.  Messages destined for the RFID reader (0xBB leading byte) are
  * forwarded as-is to the RFID reader.  The reader then responds in kind.  All RFID commands are described in the
  * RFID-FE module manual.
  *
  * @param [out] uart_buffer_tx - messages to the RFID reader
- * 
+ *
  * @retval ERR_NONE                No error
  * @retval ERR_UART_NOT_WRITEABLE  UART has no buffer space
  * @retval ERR_UART_NO_TX_ENDMARK  message for UART has no 0x7E end-mark
  * @example
- * BB 00 03 00 01 02 7E 2E C9 = read 
+ * BB 00 03 00 01 02 7E 2E C9 = read
  */
 int rfid_wr(void)
 {
     int em_pos = 0;
-    
-    for (i = 0; i < sizeof(uart_buffer_tx); i++)
-    {
+
+    for (i = 0; i < sizeof(uart_buffer_tx); i++) {
         if (uart_buffer_tx[i] == 0x7E) em_pos = (i + 1);            // allows 0x7E to appear in the data payload - uses last one for end-mark
     }
 
-    if (em_pos == 0) 
-    {
+    if (em_pos == 0) {
         led_err.write(LEDON);                                       // end mark never reached
         return ERR_UART_NO_TX_ENDMARK;
     }
 
-    if (!uart.writeable()) 
-    {
+    if (!uart.writeable()) {
         led_err.write(LEDON);
         return ERR_UART_NOT_WRITEABLE;                              // if no space in uart, return error
     }
 
-    for (i = 0; i < (em_pos + 2); i++)
-    {
+    for (i = 0; i < (em_pos + 2); i++) {
         uart.putc(uart_buffer_tx[i]);                               // send uart message
     }
-    
+
     return ERR_NONE;
-}    
+}
 
 /**
  * @name    prox_msg_wr
- * @brief   Forwards command to VL6180X sensor 
+ * @brief   Forwards command to VL6180X sensor
  *
- * Proximity/ALS reader is connected to the KL25Z I2C interface.  
- * The host PC sends the sensor command over the COM port.  Messages destined for the proximity/ALS sensor (0xCC leading byte) are 
- * forwarded to the proximity/ALS sensor after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).  
+ * Proximity/ALS reader is connected to the KL25Z I2C interface.
+ * The host PC sends the sensor command over the COM port.  Messages destined for the proximity/ALS sensor (0xCC leading byte) are
+ * forwarded to the proximity/ALS sensor after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).
  * The sensor then responds in kind.  Firmware re-attaches the leading 0xCC and trailing bytes before sending the response over the
  * CDC port to the host PC.
  *
- * I2C-prox messages:   
+ * I2C-prox messages:
  * - 0xCC                (byte) leading value = 0xCC
  * - r/w#                (byte) 0 = write, 1 = read
  * - number of data bytes(byte) 0 to 32 (size of declared buffers)
@@ -225,12 +436,12 @@
  * VL6180X registers are defined in the sensor datasheet.
  *
  * @param [in] i2c_buffer - messages to and from the VL6180X and EEPROM
- * 
+ *
  * @retval 0            No error
  * @retval 1            I2C bus has NAK'd / failure
  *
  * @param [in/out] i2c_buffer - messages to and from the i2c bus - see above
- * 
+ *
  */
 int prox_msg_wr()                                                   // write proximity I2C register
 {
@@ -238,18 +449,18 @@
     i2c_err = i2c.write(PROX, &i2c_buffer[3], i2c_buffer[2] + 2, 0);// I2C Address, pointer to buffer, number of bytes (for index + data), stop at end.
     return i2c_err;                                                 // 0 = ACK received, 1 = NAK/failure
 }
-    
+
 /**
  * @name    prox_msg_rd
  * @brief   retrieves response from VL6180X sensor
  *
- * Proximity/ALS reader is connected to the KL25Z I2C interface.  
- * The host PC sends the sensor command over the COM port.  Messages destined for the proximity/ALS sensor (0xCC leading byte) are 
- * forwarded to the proximity/ALS sensor after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).  
+ * Proximity/ALS reader is connected to the KL25Z I2C interface.
+ * The host PC sends the sensor command over the COM port.  Messages destined for the proximity/ALS sensor (0xCC leading byte) are
+ * forwarded to the proximity/ALS sensor after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).
  * The sensor then responds in kind.  Firmware re-attaches the leading 0xCC and trailing bytes before sending the response over the
  * CDC port to the host PC.
  *
- * I2C-prox messages:   
+ * I2C-prox messages:
  * - 0xCC                (byte) leading value = 0xCC
  * - r/w#                (byte) 0 = write, 1 = read
  * - number of data bytes(byte) 0 to 32 (size of declared buffers)
@@ -266,7 +477,7 @@
  * @retval 0            No error
  * @retval 1            I2C bus has NAK'd / failure
  *
- * 
+ *
  */
 int prox_msg_rd()
 {
@@ -280,11 +491,11 @@
  * @name    gpio_rd
  * @brief   retrieves instantaneous value of GPIO pins
  *
- * GPIO signals are defined directly off of the KL25Z.  
+ * GPIO signals are defined directly off of the KL25Z.
  * The host PC sends the GPIO command over the COM port.  With a 0xDD leading byte in the message, the state of the GPIO signals are read and returned.
  * This allows a read-modify-write GPIO sequence.
  *
- * GPIO messages:       
+ * GPIO messages:
  * - 0xDD                (byte) leading value = 0xDD
  * - r/w#                (byte) 0 = write, 1 = read
  * - data                (2 bytes) see below
@@ -292,7 +503,7 @@
  * - dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
  *
  * GPIO data bits - First Byte
- * - 0 LED - Error           0 = on, 1 = off                  
+ * - 0 LED - Error           0 = on, 1 = off
  * - 1 LED - Comm state      0 = on, 1 = off
  * - 2 RFID interrupt input  0 = off, 1 = on (inverted in h/w)
  * - 3 RFID in-system-prog   0 = off, 1 = on (inverted in h/w)
@@ -310,13 +521,13 @@
  * @param [in/out] gpio_buffer - GPIO states
  *
  * @retval 0            No error
- * 
+ *
  */
 
 int gpio_rd()
 {
-    gpio_buffer[2]  = ( led_err.read()        & 0x01);              // read all of the GPIO pins and store in a single byte
-    gpio_buffer[2] |= ((led_com_state   << 1) & 0x02);              // use of led_com_state allows the led to be ON during this call, but send back the pre-call state.
+    gpio_buffer[2]  = ( led_err.read()        & 0x01);              // read first byte of the GPIO pins
+    gpio_buffer[2] |= ((led_com_state   << 1) & 0x02);              // use of led_com_state allows the LED to remain ON in the main loop if desired
     gpio_buffer[2] |= ((rfid_int.read() << 2) & 0x04);
     gpio_buffer[2] |= ((rfid_isp.read() << 3) & 0x08);
     gpio_buffer[2] |= ((rfid_rst.read() << 4) & 0x10);
@@ -324,14 +535,14 @@
     gpio_buffer[2] |= ((rfid_hot.read() << 6) & 0x40);
     gpio_buffer[2] |= ((prox_int.read() << 7) & 0x80);
 
-    gpio_buffer[3]  = (   gpio_0.read()       & 0x01);              // read all of the GPIO pins and store in a single byte
-    gpio_buffer[3] |= ((  gpio_1.read() << 1) & 0x02);              // use of led_com_state allows the led to be ON during this call, but send back the pre-call state.
-    gpio_buffer[3] |= ((              0 << 2) & 0x04);              // bits 2-7 not implemented for read
+    gpio_buffer[3]  = (   gpio_0.read()       & 0x01);              // read second byte of the GPIO pins
+    gpio_buffer[3] |= ((  gpio_1.read() << 1) & 0x02);
+    gpio_buffer[3] |= ((              0 << 2) & 0x04);              // bits 2-7 always return zero
     gpio_buffer[3] |= ((              0 << 3) & 0x08);
     gpio_buffer[3] |= ((              0 << 4) & 0x10);
     gpio_buffer[3] |= ((              0 << 5) & 0x20);
     gpio_buffer[3] |= ((              0 << 6) & 0x40);
-    gpio_buffer[2] |= ((              0 << 7) & 0x80);
+    gpio_buffer[3] |= ((              0 << 7) & 0x80);
     return ERR_NONE;
 }
 
@@ -340,19 +551,19 @@
  * @name    gpio_wr
  * @brief   sets value of GPIO pins
  *
- * GPIO signals are defined directly off of the KL25Z.  
+ * GPIO signals are defined directly off of the KL25Z.
  * The host PC sends the GPIO command over the COM port.  With a 0xDD leading byte in the message, the state of the GPIO signals are read and returned.
  * This allows a read-modify-write GPIO sequence.
  *
- * GPIO messages:       
+ * GPIO messages:
  * - 0xDD                (byte) leading value = 0xDD
  * - r/w#                (byte) 0 = write, 1 = read
- * - data                (byte) see below
+ * - data                (2 bytes) see below
  * - end_mark            (byte) 0x7E
  * - dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
  *
- * GPIO data bits:      
- * - 0 LED - Error           0 = on, 1 = off                  
+ * GPIO data bits - First Byte:
+ * - 0 LED - Error           0 = on, 1 = off
  * - 1 LED - Comm state      0 = on, 1 = off
  * - 2 RFID interrupt input  0 = off, 1 = on (inverted in h/w)
  * - 3 RFID in-system-prog   0 = off, 1 = on (inverted in h/w)
@@ -370,48 +581,44 @@
  * @param [in/out] gpio_buffer - GPIO states
  *
  * @retval 0            No error
- * 
+ *
  */
 int gpio_wr()
 {
-    if ((gpio_buffer[2] & 0x02) == 0x00) 
-    {
+    if ((gpio_buffer[2] & 0x02) == 0x00) {                          // Set the desired state of the yellow LED
         led_com_state = LEDON;
-    }
-    else 
-    {
+    } else {
         led_com_state = LEDOFF;
     }
-    led_err.write(gpio_buffer[2] & 0x01);             // Write GPIO bits - first byte                 
-    led_com.write(led_com_state);                     // use of led_com_state allows the led to be ON during this call, but send back the pre-call state.         
-    rfid_int.write(gpio_buffer[2] & 0x04);                             
-    rfid_isp.write(gpio_buffer[2] & 0x08);                             
-    rfid_rst.write(gpio_buffer[2] & 0x10);                             
-    rfid_pwr.write(gpio_buffer[2] & 0x20);                             
+    led_err.write(gpio_buffer[2] & 0x01);                           // Write GPIO bits - first byte
+    led_com.write(led_com_state);                                   // use of led_com_state allows the LED to remain ON in the main loop if desired
+    rfid_int.write(gpio_buffer[2] & 0x04);
+    rfid_isp.write(gpio_buffer[2] & 0x08);
+    rfid_rst.write(gpio_buffer[2] & 0x10);
+    rfid_pwr.write(gpio_buffer[2] & 0x20);
 
-    gpio_0.write(gpio_buffer[3] & 0x01);              // Write GPIO bits - second byte
-    gpio_1.write(gpio_buffer[3] & 0x02);              // Write GPIO bits - second byte
-    gpio_7.write(gpio_buffer[3] & 0x80);              // Write GPIO bits - second byte
+    gpio_0.write(gpio_buffer[3] & 0x01);                            // Write GPIO bits - second byte
+    gpio_1.write(gpio_buffer[3] & 0x02);                            // Write GPIO bits - second byte
+    gpio_7.write(gpio_buffer[3] & 0x80);                            // Write GPIO bits - second byte
 
     return ERR_NONE;
 }
-    
-    
+
+
 /**
  * @name    eeprom_msg_wr
  * @brief   writes data to the I2C EEPROM
- * @note    *** UNTESTED with first prototype ***
  *
- * The EEPROM is connected to the KL25Z I2C interface.  
- * The host PC sends the sensor command over the COM port.  Messages destined for the EERPOM (0xEE leading byte) are 
- * forwarded to the EEPROM after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).  
- * Firmware re-attaches the leading 0xFF and trailing bytes before sending the response over the
+ * The EEPROM is connected to the KL25Z I2C interface.
+ * The host PC sends the sensor command over the COM port.  Messages destined for the EERPOM (0xEE leading byte) are
+ * forwarded to the EEPROM after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).
+ * Firmware re-attaches the leading 0xEE and trailing bytes before sending the response over the
  * CDC port to the host PC.
  *
- * I2C-EEPROM messages:    
+ * I2C-EEPROM messages:
  * - 0xEE                (byte) leading value = 0xEE
  * - r/w#                (byte) 0 = write, 1 = read
- * - number of data bytes(byte) 0 to 32 (size of declared buffers)
+ * - number of data bytes(byte) 0 to 16 bytes for write
  * - block               (byte) lower 3 bits are logically OR'd with the I2C address
  * - address             (byte) memory location within block
  * - data                (n bytes) number of data bytes noted above
@@ -424,38 +631,45 @@
  * This practically the the same as the proximity calls, except the index/location is only one byte and the block select is part of the I2C address byte.
  *
  * @param [in] i2c_buffer - messages to and from the VL6180X and EEPROM
- * 
+ *
  * @retval 0            No error
  * @retval 1            I2C bus has NAK'd / failure
+ * @retval ERR_I2C_WRITE_TOO_LARGE  buffer size too large
  *
  * @param [in/out] i2c_buffer - messages to and from the i2c bus - see above
- * 
+ *
  */
 
 int eeprom_msg_wr()                                                 // write proximity I2C register
 {
-    int i2c_err;
-    i2c_err = i2c.write((EEPROM | (i2c_buffer[3] << 1 )), &i2c_buffer[4], i2c_buffer[2] + 1, 0);  
-                                                                    // I2C Address & block select, pointer to buffer, number of bytes (for address + data), stop at end.
-    while ( i2c.write(EEPROM | (i2c_buffer[3] << 1 )));             // wait until write is done (EEPROM will ACK = 0 for single byte i2c.write)
+    int i2c_err = ERR_NONE;
+    char wr[2] = {0xFF, 0xFF};
+
+    for (i = 0; i < i2c_buffer[2]; i++){                            // done with single-byte writes to avoid addressing wrap-around
+        wr[0] = i2c_buffer[4]+i;
+        wr[1] = i2c_buffer[5+i];
+        i2c_err |= i2c.write((EEPROM | (i2c_buffer[3] << 1 )), wr, 2, 0);
+        while ( i2c.write(EEPROM | (i2c_buffer[3] << 1 )));         // wait until write is done (EEPROM will ACK = 0 for single byte i2c.write)
+        // I2C Address & block select, pointer to buffer, 2 bytes (address + one data), stop at end.
+    }
     return i2c_err;                                                 // 0 = ACK received, 1 = NAK/failure
 }
-    
+
 /**
  * @name    eeprom_msg_rd
  * @brief   read data from the I2C EEPROM
- * @note    *** UNTESTED with first prototype ***
+ * @note    EEPROM only availalbe on REV B and later
  *
- * The EEPROM is connected to the KL25Z I2C interface.  
- * The host PC sends the sensor command over the COM port.  Messages destined for the EERPOM (0xEE leading byte) are 
- * forwarded to the EEPROM after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).  
- * Firmware re-attaches the leading 0xFF and trailing bytes before sending the response over the
+ * The EEPROM is connected to the KL25Z I2C interface.
+ * The host PC sends the sensor command over the COM port.  Messages destined for the EERPOM (0xEE leading byte) are
+ * forwarded to the EEPROM after removing the leading byte and trailing bytes (0x7E endmark plus 2 bytes).
+ * Firmware re-attaches the leading 0xEE and trailing bytes before sending the response over the
  * CDC port to the host PC.
  *
- * I2C-EEPROM messages:    
+ * I2C-EEPROM messages:
  * - 0xEE                (byte) leading value = 0xEE
  * - r/w#                (byte) 0 = write, 1 = read
- * - number of data bytes(byte) 0 to 32 (size of declared buffers)
+ * - number of data bytes(byte) 0 to 128 bytes for read (size of declared buffer)
  * - block               (byte) lower 3 bits are logically OR'd with the I2C address
  * - address             (byte) memory location within block
  * - data                (n bytes) number of data bytes noted above
@@ -468,106 +682,112 @@
  * This practically the the same as the proximity calls, except the index/location is only one byte and the block select is part of the I2C address byte.
  *
  * @param [in/out] i2c_buffer - messages to and from the VL6180X and EEPROM
- * 
+ *
  * @retval [none]0            No error
  * @retval 1            I2C bus has NAK'd / failure
  *
  * @param [in/out] i2c_buffer - messages to and from the i2c bus - see above
- * 
+ *
  */
- int eeprom_msg_rd()
+int eeprom_msg_rd()
 {
     int i2c_err;
-    i2c_err = i2c.write((EEPROM | (i2c_buffer[3] << 1)), &i2c_buffer[4], 1, 1); 
-                                                                    // I2C Address & block select, pointer to buffer (just the index), index, number of bytes (for address + data), no stop at end.
-    i2c_err |= i2c.read((EEPROM | (i2c_buffer[3] << 1)), &i2c_buffer[5], i2c_buffer[2], 0);   
-                                                                    // I2C Address & block select, pointer to buffer (just the data), number of data bytes, stop at end.
+    i2c_err = i2c.write((EEPROM | (i2c_buffer[3] << 1)), &i2c_buffer[4], 1, 1);
+    // I2C Address & block select, pointer to buffer (just the index), index, number of bytes (for address + data), no stop at end.
+    i2c_err |= i2c.read((EEPROM | (i2c_buffer[3] << 1)), &i2c_buffer[5], i2c_buffer[2], 0);
+    // I2C Address & block select, pointer to buffer (just the data), number of data bytes, stop at end.
     return i2c_err;                                                 // 0 = ACK received, 1 = NAK/failure
 }
 
 /**
  * @name    main
- * @brief   main firmware loop
+ * @brief   Main firmware loop
  *
  * @returns [none]
  */
-int main(void) 
+int main(void)
 {
     int em_pos = 0;                                                 // end of message count - allows multiple 0x7e in message.
+    char msgcount;
+    char temploc;
+    char autorange[] = {0x00, 0x18, 0x00};                          // Proximity sensor automatic measurement.  Set last byte = 0x03 to start
+    char proxintclr[] = {0x00, 0x15, 0x07};                         // Clear proximity interrupt
 
-    //wait(5.0);                                                    // gives a chance to connect the COM port - this can be removed for production
+    char i2c_addr = (EEPROM | (2 << 1));                            // EEPROM base address is 0xA0 (already shifted).  Bank 2 in use here, shifted for I2C addressing.
 
     init_periph();                                                  // initialize everything
-    
-    while(1)
-    {
+
+    while(1) {                                                      // main loop
         led_com.write(led_com_state);                               // turn off communication LED unless it was specifically turned on by GPIO command
-        if (prox_irq_state == 1)                                    // process the proximity interrupt 
-        {
-            prox_irq_state = 0;
-            cdc_buffer_tx[0] = 0xFF;                                // send message to PC
-            cdc_buffer_tx[1] = 0x7E;
-            cdc_buffer_tx[2] = 0x0F;
-            cdc_buffer_tx[3] = 0xF0;
-            cdc.writeBlock(cdc_buffer_tx, 4);
+        if (prox_irq_state == 1) {                                  // process the proximity interrupt
+            if (prox_irq_msg[0] != 0xBB){                           // no message to send to RFID
+                cdc_buffer_tx[0] = 0xFF;                            // just send a dummy message back to the host
+                cdc_buffer_tx[1] = 0x7E;
+                cdc_buffer_tx[2] = 0x0F;
+                cdc_buffer_tx[3] = 0xF0;
+                cdc.writeBlock(cdc_buffer_tx, 4);
+                led_err.write(LEDON);                               // we shouldn't get here
+            }
+            else{
+                msgcount = prox_irq_msg[2] + 6;                     // See RFID-FE manual for message construction
+                for (i = 0; i < msgcount; i++) {
+                    uart.putc(prox_irq_msg[i]);                     // send message to RFID-FE module for a single read
+                }
+            }
+            prox_irq_state = 0;                                     // reset proximity interrupt state
+            wait(0.5);                                              // wait 1/2 sec so the COM LED can be seen
+            led_com.write(led_com_state);                           // turn off COM LED if not on by GPIO (it was turned on in the ISR)
+            i2c.write(PROX, proxintclr, 3, 0);                      // i2c prox sensor, interrupt clear message, 3 bytes, stop at end
+
         }
-        if (uart.readable())                                        // message availalbe from rfid
-        {
+        if (uart.readable()) {                                      // message availalbe from rfid (all responses (0x01) and broadcast (0x02))
             int rfid_len = 0;
             led_com.write(LEDON);
-            for (i = 0; i < (RFIDLENLOW); i++)                              // Get first part of message to find out total count
-            {
-                uart_buffer_rx[i] = uart.getc();                            // get a byte from rfid
+            for (i = 0; i < (RFIDLENLOW); i++) {                    // Get first part of message to find out total count
+                uart_buffer_rx[i] = uart.getc();                    // get a byte from rfid
             }
             rfid_len = ((uart_buffer_rx[i-2]<<8) + (uart_buffer_rx[i-1]));  // location of message length for RFID
-            for (i = RFIDLENLOW; i < (RFIDLENLOW + rfid_len + 3); i++)
-            {
-                uart_buffer_rx[i] = uart.getc();                            // get a byte from rfid
+            for (i = RFIDLENLOW; i < (RFIDLENLOW + rfid_len + 3); i++) { // get the reset of the message
+                uart_buffer_rx[i] = uart.getc();                    // get a byte from rfid
             }
-            for (i = 0; i < (RFIDLENLOW + rfid_len + 3); i++)
-            {
+            for (i = 0; i < (RFIDLENLOW + rfid_len + 3); i++) {     // copy the message to the USB buffer
                 cdc_buffer_tx[i] = uart_buffer_rx[i];
             }
-            cdc.writeBlock(cdc_buffer_tx, (RFIDLENLOW + rfid_len + 3));
-            led_com.write(LEDOFF);
-        }                                         
-        if (usb_irq_state == 1)                                     // message available from PC
-        {
-            led_com.write(LEDON);                                   // Message received - turn on LED
-            usb_irq_state = 0;
+            cdc.writeBlock(cdc_buffer_tx, (RFIDLENLOW + rfid_len + 3)); // send the RFID message to the PC
+            led_com.write(led_com_state);
+        }
+        if (usb_irq_state == 1) {                                   // message available from PC
+            usb_irq_state = 0;                                      // allow another USB interrupt 
 
-            for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-            {
+            for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
                 if (cdc.readable()) cdc_buffer_rx[i] = cdc._getc(); // read data from USB side
             }
-            for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-            {
-                if (cdc_buffer_rx[i] == 0x7E)                       // check for rfid end mark in outbound message
-                {
+            if ((cdc_buffer_rx[0] == 'A') && (cdc_buffer_rx[1] == 'T')) { // check for Hayes command and ignore it
+                    break;                                          // Linux systems will enumerate as ttyACMx
+            }                                                       // and attempt to initialize the non-existent modem
+            for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
+                if (cdc_buffer_rx[i] == 0x7E) {                     // check for rfid end mark in outbound message
                     em_pos = (i + 1);
                 }
             }
-            if (em_pos == 0)                                        // end mark never reached
-            {
+            led_com.write(LEDON);                                   // Message received - turn on LED
+            if (em_pos == 0) {                                      // end mark never reached
                 led_err.write(LEDON);
                 break;
             }
-    
-            switch(cdc_buffer_rx[0])                                // check first byte for "destination"
-            {
+
+            switch(cdc_buffer_rx[0]) {                              // check first byte for "destination"
                 case 0xBB:                                          // RFID-FE
-                    for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-                    {
+                    for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
                         uart_buffer_tx[i] = cdc_buffer_rx[i];       // copy USB message to UART for RFID
                     }
-                    
+
                     status = rfid_wr();                             // send buffer to RFID and get response according to RFID board
                     break;
-            
+
                 case 0xCC:                                          // Proximity Sensor
                     led_com.write(LEDON);
-                    for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-                    {
+                    for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
                         i2c_buffer[i] = cdc_buffer_rx[i];           // copy USB message to buffer for I2C
                     }
 
@@ -576,99 +796,109 @@
                     else if (i2c_buffer[1] == 0)                    // I2C write = 0
                         status = prox_msg_wr();                     // send buffer to proximity sensor and get response
 
-                    if (status) led_err.write(LEDON);
-            
+                    if (status) led_err.write(LEDON);               // we shouldn't get here
+
                     em_pos = 0;
-                    for (i = 0; i < sizeof(cdc_buffer_tx); i++)
-                    {
+                    for (i = 0; i < sizeof(cdc_buffer_tx); i++) {
                         cdc_buffer_tx[i] = i2c_buffer[i];           // copy RFID response back to USB buffer
-                        if (cdc_buffer_tx[i] == 0x7E) 
-                        {
+                        if (cdc_buffer_tx[i] == 0x7E) {
                             em_pos = (i + 1);                       // allows 0x7E to appear in the data payload - uses last one for end-mark
                         }
                     }
-                    if (em_pos == 0) 
-                    {
+                    if (em_pos == 0) {
                         led_err.write(LEDON);                       // end mark never reached
                         break;
                     }
 
                     cdc.writeBlock(cdc_buffer_tx, (em_pos + 2));
-                    led_com.write(LEDOFF);
+                    led_com.write(led_com_state);
                     break;
-            
+
                 case 0xDD:                                          // GPIO (LEDs and RFID-FE control)
-
                     led_com.write(LEDON);
-                    for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-                    {
-                        gpio_buffer[i] = cdc_buffer_rx[i];          // copy USB message to buffer for I2C
+                    for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
+                        gpio_buffer[i] = cdc_buffer_rx[i];          // copy USB message to buffer for GPIO
                     }
-                
+
                     if (gpio_buffer[1] == 1)                        // GPIO read = 1
                         status = gpio_rd();                         // read the requested data
                     else if (gpio_buffer[1] == 0)                   // GPIO write = 0
                         status = gpio_wr();                         // send GPIO pin data
-            
+
                     em_pos = 0;
-                    for (i = 0; i < sizeof(cdc_buffer_tx); i++)
-                    {
+                    for (i = 0; i < sizeof(cdc_buffer_tx); i++) {
                         cdc_buffer_tx[i] = gpio_buffer[i];          // copy RFID response back to USB buffer
-                        if (cdc_buffer_tx[i] == 0x7E) 
-                        {
+                        if (cdc_buffer_tx[i] == 0x7E) {
                             em_pos = (i + 1);                       // allows 0x7E to appear in the data payload - uses last one for end-mark
                         }
                     }
-                    if (em_pos == 0) 
-                    {
+                    if (em_pos == 0) {
                         led_err.write(LEDON);                       // end mark never reached
                         break;
                     }
 
                     cdc.writeBlock(cdc_buffer_tx, (em_pos + 2));
-                    led_com.write(LEDOFF);
+                    led_com.write(led_com_state);
+
+                    break;
 
-                    break;            
-                
                 case 0xEE:                                          // Read/write EEPROM
-                   led_com.write(LEDON);
-                    for (i = 0; i < sizeof(cdc_buffer_rx); i++)
-                    {
+                    led_com.write(LEDON);
+                    for (i = 0; i < sizeof(cdc_buffer_rx); i++) {
                         i2c_buffer[i] = cdc_buffer_rx[i];           // copy USB message to buffer for I2C
                     }
 
                     if (i2c_buffer[1] == 1)                         // I2C read = 1
                         status = eeprom_msg_rd();                   // read the requested data
                     else if (i2c_buffer[1] == 0)                    // I2C write = 0
-                        status = eeprom_msg_wr();                   // send buffer to proximity sensor and get response
+                        status = eeprom_msg_wr();                   // send buffer to EEPROM and get response
 
                     if (status) led_err.write(LEDON);
-            
+
                     em_pos = 0;
-                    for (i = 0; i < sizeof(cdc_buffer_tx); i++)
-                    {
+                    for (i = 0; i < sizeof(cdc_buffer_tx); i++) {
                         cdc_buffer_tx[i] = i2c_buffer[i];           // copy RFID response back to USB buffer
-                        if (cdc_buffer_tx[i] == 0x7E) 
-                        {
+                        if (cdc_buffer_tx[i] == 0x7E) {
                             em_pos = (i + 1);                       // allows 0x7E to appear in the data payload - uses last one for end-mark
                         }
                     }
-                    if (em_pos == 0) 
-                    {
+                    if (em_pos == 0) {
                         led_err.write(LEDON);                       // end mark never reached
                         break;
                     }
 
                     cdc.writeBlock(cdc_buffer_tx, (em_pos + 2));
-                    led_com.write(LEDOFF);
+                    led_com.write(led_com_state);
                     break;
+
+                case 0xFF:
+                    if (cdc_buffer_rx[1] > 0){
+                        // read message sent to RFID on interrupt
+                        
+                        temploc = 0x12;
+                        i2c.write(i2c_addr, &temploc, 1, 1);        // i2c address+bank 0, RFID message size location, 1 byte, no stop at end
+                        i2c.read(i2c_addr, &msgcount, 1, 0);        // i2c address+bank 0, RFID message size, 1 byte, stop at end
+                        msgcount += 6;                              // get the real size
+                        temploc = 0x10;
+                        i2c.write(i2c_addr, &temploc, 1, 1);        // i2c address+bank 0, RFID message location, 1 byte, no stop at end
+                        i2c.read(i2c_addr, prox_irq_msg, msgcount, 0);  // i2c address+bank 0, description string, string size, stop at end
+
+                        autorange[2] = 0x03;
+                        i2c.write(PROX, autorange, 3, 0);           // Start contonuous proximity range read
+                    }
+                    else {
+                        prox_irq_msg[0] = 0xFF;                     // clear first byte
+                        autorange[2] = 0x00;
+                        i2c.write(PROX, autorange, 3, 0);           // Stop range read
+                    }
                     
+                    break;
                 default:
-                    led_err.write(LEDON);
-                    while(1);
+                    led_err.write(LEDON);                           // we should never get here
+                    while(1);                                       // halt!
             }
         }
-        led_com.write(LEDOFF);
+        led_com.write(led_com_state);
     }
 }
-//EOF
\ No newline at end of file
+//EOF main.cpp
\ No newline at end of file