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
main.cpp
- Committer:
- bob_tpc
- Date:
- 2015-01-23
- Revision:
- 10:55e35536d493
- Parent:
- 9:046247707ffb
- Child:
- 11:984631a6e373
File content as of revision 10:55e35536d493:
/** * @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" // 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 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; #define ERR_CDC_NO_TX_ENDMARK 2 // message for no endmark on message to PC #define ERR_UART_NOT_WRITEABLE 3 // UART has no buffer space #define ERR_UART_NO_TX_ENDMARK 4 // message for UART has no 0x7E end-mark #define ERR_UART_NO_RX_ENDMARK 5 // message received from UART has no end-mark #define ERR_I2C_NOT_WRITEABLE 6 // UART has no buffer space #define ERR_I2C_NO_TX_ENDMARK 7 // message for UART has no 0x7E end-mark #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 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 // UART-RFID baud rate #define RFIDBAUD 115200 // RFID-FE board default rate = 115.2Kbps // Peripherals USBSerial cdc; // CDC Class USB<>Serial adapter. Needs custom INF, but uses existing Windows 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) // GPIO signals DigitalOut led_err(PTC1); // Red LED shows error condition (active low) DigitalOut led_com(PTC2); // Yellow LED shows communication activity (active low) DigitalOut rfid_int(PTD4); // RFID FE power control (active high) DigitalOut rfid_isp(PTD5); // RFID FE In-System Programming (active high) DigitalOut rfid_rst(PTD6); // RFID FE Reset (active high) 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) // buffers & variables uint8_t gpio_values = 0x00; // register to read GPIO values 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]; uint8_t gpio_buffer[32]; // buffer for GPIO messages 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; // 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; } /** * @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 uart.baud(RFIDBAUD); // RFID-FE baud rate 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, low for all others) wait(0.25); // wait 250ms before... rfid_rst = 0; // ... taking RFID out of reset // 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); wait(0.5); led_err.write(LEDOFF); wait(0.5); led_com.write(LEDOFF); return ERR_NONE; } /** * @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) { bool end_mark = FALSE; int i; uint8_t crcCount = sizeof(uart_buffer_tx); // use tx buffer size to start uart.txBufferFlush(); // clear out UART buffers uart.rxBufferFlush(); for (int i = 0; i < sizeof(uart_buffer_tx); i++) { if (!uart.writeable()) { led_err.write(LEDON); return ERR_UART_NOT_WRITEABLE; // if no space in uart, return error } uart.putc(uart_buffer_tx[i]); // send uart message if (uart_buffer_tx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) { led_err.write(LEDON); return ERR_UART_NO_TX_ENDMARK; // no end mark detected } break; } } end_mark = FALSE; while(!uart.readable()); // wait for data from rfid crcCount = sizeof(uart_buffer_rx); // use rx buffer size to start for (i = 0; i < sizeof(uart_buffer_rx); i++) { uart_buffer_rx[i] = uart.getc(); // read a character if (uart_buffer_rx[i] == 0x7E) // check for rfid end mark in inbound message { crcCount = 2; // two more bytes for crc end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) { led_err.write(LEDON); return ERR_UART_NO_RX_ENDMARK; } break; } } return ERR_NONE; } /** * @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; 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). * 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; i2c_err = i2c.write(PROX, &i2c_buffer[3], 2, 1); // I2C Address, pointer to buffer (just the index), index, number of bytes (2 for index), no stop at end. i2c_err |= i2c.read(PROX, &i2c_buffer[5], i2c_buffer[2], 0); // I2C Address, pointer to buffer (just the data), number of data bytes, stop at end. 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 * */ 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] |= ((rfid_int.read() << 2) & 0x04); 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) { led_com_state = LEDON; } else { led_com_state = LEDOFF; } led_err.write(gpio_buffer[2] & 0x01); led_com.write(led_com_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); 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 * 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 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 = 0 for single byte i2c.write) 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 *** * * 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 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. return i2c_err; // 0 = ACK received, 1 = NAK/failure } /** * @name main * @brief main firmware loop * * @returns [none] */ int main(void) { wait(5.0); // gives a chance to connect the COM port - this can be removed for production 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()) // spin here until a message comes in from the host PC { if(prox_irq_state == 1) // process the interrupt if it occurs while waiting for PC message { prox_irq_state = 0; cdc.putc(0xFF); cdc.putc(0x7E); cdc.putc(0x0F); cdc.putc(0xF0); } } 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 for (i = 0; i < sizeof(cdc_buffer_rx); i++) { cdc_buffer_rx[i] = cdc.getc(); // read data from USB side if (cdc_buffer_rx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) return ERR_UART_NO_TX_ENDMARK; // no end mark detected break; } } switch(cdc_buffer_rx[0]) // check first byte for "destination" { case 0xBB: // RFID-FE 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_msg(); // send buffer to RFID and get response according to RFID board for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc_buffer_tx[i] = uart_buffer_rx[i]; // copy RFID response back to USB buffer } for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc.putc(cdc_buffer_tx[i]); // send message back to PC if (cdc_buffer_tx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) return ERR_CDC_NO_TX_ENDMARK; // no end mark detected break; } } break; case 0xCC: // Proximity Sensor 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 = prox_msg_rd(); // read the requested data else if (i2c_buffer[1] == 0) // I2C write = 0 status = prox_msg_wr(); // send buffer to proximity sensor and get response for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc_buffer_tx[i] = i2c_buffer[i]; // copy prox response back to USB buffer } for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc.putc(cdc_buffer_tx[i]); // send message back to PC if (cdc_buffer_tx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) return ERR_CDC_NO_TX_ENDMARK; // no end mark detected break; } } break; case 0xDD: // GPIO (LEDs and RFID-FE control) for (i = 0; i < sizeof(cdc_buffer_rx); i++) { gpio_buffer[i] = cdc_buffer_rx[i]; // copy USB message to buffer for I2C } 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 for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc_buffer_tx[i] = gpio_buffer[i]; // copy GPIO response back to USB buffer } for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc.putc(cdc_buffer_tx[i]); // send message back to PC if (cdc_buffer_tx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) return ERR_CDC_NO_TX_ENDMARK; // no end mark detected break; } } break; case 0xEE: // Read/write EEPROM 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 = gpio_rd(); // read the gpio pins else if (i2c_buffer[1] == 0) // I2C write = 0 status = gpio_wr(); // write gpio pins for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc_buffer_tx[i] = i2c_buffer[i]; // copy prox response back to USB buffer } for (i = 0; i < sizeof(cdc_buffer_tx); i++) { cdc.putc(cdc_buffer_tx[i]); // send message back to PC if (cdc_buffer_tx[i] == 0x7E) // check for rfid end mark in outbound message { crcCount = 2; // two more bytes for CRC end_mark = TRUE; // end mark was reached } if (crcCount-- == 0) // end of message { if (end_mark == FALSE) return ERR_CDC_NO_TX_ENDMARK; // no end mark detected break; } } break; default: return ERR_CDC_BAD_CMD; } } } //EOF