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:
10:55e35536d493
Parent:
9:046247707ffb
Child:
11:984631a6e373
--- a/main.cpp	Thu Jan 22 23:04:42 2015 +0000
+++ b/main.cpp	Fri Jan 23 01:32:07 2015 +0000
@@ -1,3 +1,16 @@
+/**
+ * @file   main.cpp
+ * @date   January 2015
+ * @brief  Freescale KL25Z firmware for USB-RFID adapter
+ *
+ * This firmware provided 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)
+ */
+
+
 #include "mbed.h"
 #include "USBSerial.h"
 #include "MODSERIAL.h"
@@ -8,7 +21,6 @@
 #define TRUE        1
 #define FALSE       0
 
-
 // Error return values
 #define ERR_NONE                0   // Success
 #define ERR_CDC_BAD_CMD         1   // First byte of PC to USB board needs to be 0xBB, 0xCC, 0xDD or 0xEE;
@@ -21,8 +33,7 @@
 #define ERR_I2C_NO_RX_ENDMARK   8   // message received from UART has no end-mark
 #define ERR_NOT_IMPLEMENTED     255 // method has not yet been implemented
 
-
-// I2C addresses
+// I2C addresses and parameters
 #define PROX        (0x29 << 1)     // default I2C address of VL6180X, shift into upper 7 bits
 #define EEPROM      (0xA0)          // default I2C address of EEPROM, already shifted
 #define I2CRATE     400000          // I2C speed
@@ -47,8 +58,7 @@
 
 // buffers & variables
 uint8_t gpio_values = 0x00;         // register to read GPIO values
-
-uint8_t cdc_buffer_rx[32] = {0xBB, 0x00, 0x03, 0x00, 0x01, 0x02, 0x7E, 0x2E, 0xC9};          // buffers for cdc (USB-Serial port on PC)
+uint8_t cdc_buffer_rx[32];          // buffers for cdc (USB-Serial port on PC)          
 uint8_t cdc_buffer_tx[32];
 uint8_t uart_buffer_rx[32];         // buffers for uart (RFID-FE board)
 uint8_t uart_buffer_tx[32];
@@ -56,16 +66,37 @@
 char i2c_buffer[32];                // 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
 int status = 0x00;                  // return value
-
-uint8_t led_com_state = LEDOFF;
+uint8_t led_com_state = LEDOFF;     // initial LED state
 uint8_t prox_irq_state = 0;         // interrupt state passed from service routine
 
+
+/**
+ * @name    prox_irq
+ * @brief   Sets interrupt variable for use in the main loop.
+ * The interrupt is triggered by the VL6180X GPIO1 (IRQ output)
+ *
+ * @param [in] none
+ * @param [out] prox_irq_state = 1 indicates an interrupt occured.
+ */
 void prox_irq(void)
 {
     prox_irq_state = 1;
 }
 
-int init_periph(void)
+/**
+ * @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.
+ *
+ * @param [in] none
+ * @param [out] none
+ * 
+ * @retval ERR_NONE     No error
+ */
+ int init_periph(void)
 {
     // Set up peripherals
     // RFID
@@ -81,9 +112,8 @@
     // Prox & EEPROM
     i2c.frequency(I2CRATE);                                             // I2C speed = 400Kbps
     prox_int.mode(PullUp);                                              // pull up proximity sensor interrupt at MCU
-    prox_int.fall(&prox_irq);
-    prox_int.enable_irq();
-    cdc.printf("Interrupt active");
+    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);
@@ -93,11 +123,29 @@
     wait(0.5);
     led_com.write(LEDOFF);
     
-    return 0;
+    return ERR_NONE;
 }
 
-/*
-RFID messages are as defined in the RFID-FE manual.
+/**
+ * @name    rfid_msg
+ * @brief   Forwards command to RFID reader and returns the reader response
+ *
+ * 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 
+ * 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 [in] uart_buffer_rx - messages from the RFID reader
+ * @param [out] uart_buffer_tx - messages to the RFID reader
+ * 
+ * @retval ERR_NONE                No error
+ * @retval ERR_CDC_BAD_CMD         First byte of PC to USB board needs to be 0xBB, 0xCC, 0xDD or 0xEE;
+ * @retval ERR_CDC_NO_TX_ENDMARK   message for CDC port has no 0x7E endmark
+ * @retval ERR_UART_NOT_WRITEABLE  UART has no buffer space
+ * @retval ERR_UART_NO_TX_ENDMARK  message for UART has no 0x7E end-mark
+ * @retval ERR_UART_NO_RX_ENDMARK  message received from UART has no end-mark
+ * @example
+ * BB 00 03 00 01 02 7E 2E C9 = read 
  */
 int rfid_msg(void)
 {
@@ -159,13 +207,35 @@
     return ERR_NONE;
 }
 
-
-/*
-I2C-prox messages = 0xCC, r/w#, number of data bytes, index (2 bytes), data bytes, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
-
-Multiple registers can be read or written with single prox_msg_rd() or prox_msg_wr().  Location address increments for each byte.
+/**
+ * @name    prox_msg_wr
+ * @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).  
+ * 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:   0xCC                (byte) leading value = 0xCC
+ *                      r/w#                (byte) 0 = write, 1 = read
+ *                      number of data bytes(byte) 0 to 32 (size of declared buffers)
+ *                      index               (2 bytes) 12-bit VL6801X register offset, high byte first
+ *                      data                (n bytes) number of data bytes noted above
+ *                      end_mark            (byte) 0x7E
+ *                      dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
+ *
+ * Multiple registers can be read or written with single prox_msg_rd() or prox_msg_wr().  Location address increments for each byte.
+ * 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
 {
     int i2c_err;
@@ -173,6 +243,34 @@
     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).  
+ * 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:   0xCC                (byte) leading value = 0xCC
+ *                      r/w#                (byte) 0 = write, 1 = read
+ *                      number of data bytes(byte) 0 to 32 (size of declared buffers)
+ *                      index               (2 bytes) 12-bit VL6801X register offset, high byte first
+ *                      data                (n bytes) number of data bytes noted above
+ *                      end_mark            (byte) 0x7E
+ *                      dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
+ *
+ * Multiple registers can be read or written with single prox_msg_rd() or prox_msg_wr().  Location address increments for each byte.
+ * VL6180X registers are defined in the sensor datasheet.
+ *
+ * @param [in/out] i2c_buffer - messages to and from the i2c bus - see above
+ *
+ * @retval 0            No error
+ * @retval 1            I2C bus has NAK'd / failure
+ *
+ * 
+ */
 int prox_msg_rd()
 {
     int i2c_err;
@@ -181,8 +279,37 @@
     return i2c_err;                                                     // 0 = ACK received, 1 = NAK/failure
 }
 
+/**
+ * @name    gpio_rd
+ * @brief   retrieves instantaneous value of GPIO pins
+ *
+ * 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:       0xDD                (byte) leading value = 0xDD
+ *                      r/w#                (byte) 0 = write, 1 = read
+ *                      data                (byte) 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                  
+ *                      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)
+ *                      4 RFID reset            0 = off, 1 = on (inverted in h/w)
+ *                      5 RFID power enable 
+ *                         for first prototype, 0 = off, 1 = on
+ *                              for production, 0 = on, 1 = off
+ *                      6 RFID over-current     0 = overcurrent detected, 1 = OK
+ *                      7 Proximity interrupt   0 = interrupt, 1 = idle (This pin may not return anything meaningful here.  The interrupt is edge triggered).
+ *
+ * @param [in/out] gpio_buffer - GPIO states
+ *
+ * @retval 0            No error
+ * 
+ */
 
-// GPIO messages = 0xDD, r/w#, value, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
 int gpio_rd()
 {
     gpio_buffer[2]  = ( led_err.read()        & 0x01);                  // read all of the GPIO pins and store in a single byte
@@ -191,10 +318,42 @@
     gpio_buffer[2] |= ((rfid_isp.read() << 3) & 0x08);
     gpio_buffer[2] |= ((rfid_rst.read() << 4) & 0x10);
     gpio_buffer[2] |= ((rfid_pwr.read() << 5) & 0x20);
-    
+    gpio_buffer[2] |= ((rfid_hot.read() << 6) & 0x40);
+    gpio_buffer[2] |= ((prox_int.read() << 7) & 0x80);
     return ERR_NONE;
 }
 
+
+/**
+ * @name    gpio_wr
+ * @brief   sets value of GPIO pins
+ *
+ * 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:       0xDD                (byte) leading value = 0xDD
+ *                      r/w#                (byte) 0 = write, 1 = read
+ *                      data                (byte) 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                  
+ *                      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)
+ *                      4 RFID reset            0 = off, 1 = on (inverted in h/w)
+ *                      5 RFID power enable 
+ *                         for first prototype, 0 = off, 1 = on
+ *                              for production, 0 = on, 1 = off
+ *                      6 don't care
+ *                      7 don't care
+ *
+ * @param [in/out] gpio_buffer - GPIO states
+ *
+ * @retval 0            No error
+ * 
+ */
 int gpio_wr()
 {
     if ((gpio_buffer[2] & 0x02) == 0x00) 
@@ -215,26 +374,86 @@
 }
     
     
-/*
-I2C-EEPROM messages = 0xEE, r/w, number of data bytes, block, address, data bytes, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
-
-Multiple registers can be read or written with single eeprom_msg_rd() or eeprom_msg_wr().  Location address increments for each byte.
-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.
+/**
+ * @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
+ * CDC port to the host PC.
+ *
+ * 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)
+ *                      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
+ *                      end_mark            (byte) 0x7E
+ *                      dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
+ *
+ * Multiple memory locations can be read or written with single eeprom_msg_rd() or eeprom_msg_wr().  Location address increments for each byte.
+ * Read/Write sequences are defined in the 24LC16B datasheet.
+ *
+ * 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
+ *
+ * @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]), &i2c_buffer[4], i2c_buffer[2] + 1, 0);  
+    i2c_err = i2c.write((EEPROM | i2c_buffer[3]), &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]));                        // wait until write is done (EEPROM will ACK = 1 for single byte i2c.write)
+    while (!i2c.write(EEPROM | i2c_buffer[3]));                         // wait until write is done (EEPROM will ACK = 0 for single byte i2c.write)
     return i2c_err;                                                     // 0 = ACK received, 1 = NAK/failure
 }
     
-int eeprom_msg_rd()
+/**
+ * @name    eeprom_msg_rd
+ * @brief   read data from 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
+ * CDC port to the host PC.
+ *
+ * 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)
+ *                      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
+ *                      end_mark            (byte) 0x7E
+ *                      dummy               (2 bytes) values are don't-care - fillers for RFID CRC bytes
+ *
+ * Multiple memory locations can be read or written with single eeprom_msg_rd() or eeprom_msg_wr().  Location address increments for each byte.
+ * Read/Write sequences are defined in the 24LC16B datasheet.
+ *
+ * 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 i2c_err;
-    i2c_err = i2c.write((EEPROM || i2c_buffer[3]), &i2c_buffer[4], 1, 1); 
+    i2c_err = i2c.write((EEPROM | i2c_buffer[3]), &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]), &i2c_buffer[5], i2c_buffer[2], 0);   
                                                                         // I2C Address & block select, pointer to buffer (just the data), number of data bytes, stop at end.
@@ -242,21 +461,24 @@
 }
 
 
-
-int main() 
+/**
+ * @name    main
+ * @brief   main firmware loop
+ *
+ * @returns [none]
+ */
+int main(void) 
 {
-    // initialize everything
-
     wait(5.0);                                                          // gives a chance to connect the COM port - this can be removed for production
 
-    init_periph();
+    init_periph();                                                      // initialize everything
     
     while(1)
     {
         led_com.write(led_com_state);                                   // turn off communication LED unless it was specifically turned on by GPIO command
-        while(!cdc.readable())
+        while(!cdc.readable())                                          // spin here until a message comes in from the host PC
         {
-            if(prox_irq_state == 1)
+            if(prox_irq_state == 1)                                     // process the interrupt if it occurs while waiting for PC message
             {
                 prox_irq_state = 0;
                 cdc.putc(0xFF);
@@ -264,7 +486,7 @@
                 cdc.putc(0x0F);
                 cdc.putc(0xF0);
             }
-        }                                         // spin here until a message comes in from the host PC
+        }                                         
         led_com.write(LEDON);                                           // Message received - turn on LED
         bool end_mark = FALSE;
         uint8_t crcCount = sizeof(cdc_buffer_rx);                       // use tx buffer size to start
@@ -284,7 +506,7 @@
             }
         }
 
-        switch(cdc_buffer_rx[0])
+        switch(cdc_buffer_rx[0])                                        // check first byte for "destination"
         {
             case 0xBB:                                                  // RFID-FE
                 for (i = 0; i < sizeof(cdc_buffer_rx); i++)
@@ -317,7 +539,6 @@
                 break;
             
             case 0xCC:                                                  // Proximity Sensor
-            //I2C-prox messages = 0xCC, r/w, number of data bytes, index, data bytes, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
                 for (i = 0; i < sizeof(cdc_buffer_rx); i++)
                 {
                     i2c_buffer[i] = cdc_buffer_rx[i];                   // copy USB message to buffer for I2C
@@ -351,7 +572,6 @@
                 break;
             
             case 0xDD:                                                  // GPIO (LEDs and RFID-FE control)
-            //GPIO messages = 0xDD, r/w#, value, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
                 for (i = 0; i < sizeof(cdc_buffer_rx); i++)
                 {
                     gpio_buffer[i] = cdc_buffer_rx[i];                  // copy USB message to buffer for I2C
@@ -385,12 +605,6 @@
                 break;            
                 
             case 0xEE:                                                  // Read/write EEPROM
-/*
-I2C-EEPROM messages = 0xEE, r/w, number of data bytes, block, address, data bytes, 0x7E, 0xXX, 0xXX - last two are fillers where CRC goes for RFID
-
-Multiple registers can be read or written with single eeprom_msg_rd() or eeprom_msg_wr().  Location address increments for each byte.
-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.
- */
                 for (i = 0; i < sizeof(cdc_buffer_rx); i++)
                 {
                     i2c_buffer[i] = cdc_buffer_rx[i];                   // copy USB message to buffer for I2C
@@ -427,3 +641,4 @@
         }
     }
 }
+//EOF
\ No newline at end of file