Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MODSERIAL USBDevice mbed-rtos mbed
Fork of mbed_sv_firmware_mt by
Diff: main.cpp
- 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
