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_for_Rev_C_HW mbed
Fork of mbed_sv_firmware_with_init 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