EEP fORK
Dependencies: BLE_API mbed nRF51822
Fork of MCS_LRF by
Diff: main.cpp
- Revision:
- 2:79a9dad8bc5e
- Parent:
- 1:e18634cb382a
- Child:
- 3:de77a4ebbf21
--- a/main.cpp Fri Aug 07 00:45:04 2015 +0000 +++ b/main.cpp Thu Oct 08 04:49:36 2015 +0000 @@ -22,19 +22,30 @@ #define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console; * it will have an impact on code-size and power consumption. */ +#define NEED_PARSE_TRACE 0 // only used for parsing tag data- will not work if parse function is called from within serial interrupt + +Serial pc(USBTX, USBRX); #if NEED_CONSOLE_OUTPUT -Serial pc(USBTX, USBRX); +//Serial pc(USBTX, USBRX); #define DEBUG(...) { pc.printf(__VA_ARGS__); } #else #define DEBUG(...) /* nothing */ +#define TRACE(...) #endif /* #if NEED_CONSOLE_OUTPUT */ +#if NEED_TRACE +#define TRACE(...) { pc.printf(__VA_ARGS__); } +#else +#define TRACE(...) +#endif /* #if NEED_TRACE */ + BLEDevice ble; -DigitalOut pin0(p0); -DigitalOut pin1(p1); +//DigitalOut led(p19); +DigitalOut led(p21); +DigitalOut trigger(p8); +Serial reader(p9, p17); // tx, rx === NOTE tx port pin needs to be wired and verified - -const static char DEVICE_NAME[] = "MCS LED"; +const static char DEVICE_NAME[] = "MCS_RFID"; const static char MANUFACTURER[] = "MCS"; const static char MODEL[] = "Model 1"; const static char SERIAL_NO[] = "SN 1234"; @@ -43,43 +54,115 @@ const static char SOFTWARE_REV[] = "soft-rev 1"; UARTService *uartServicePtr; +static uint8_t isConnected = 0; -void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) +// these values must macth definitions in the XML file accompanying this device +const static uint16_t tagIdCmd = 0x0001; +const static uint16_t triggerCmd = 0x0002; + + +#define HEADER_FLAG 0xFF +#define CMD_OFFSET 2 +#define EPC_READ_CMD 0x29 +#define STATUS_OFFSET 3 +#define EPC_LENGTH_OFFSET 26 +#define BIT_64_TAG_FLAG 0x60 +#define BIT_96_TAG_FLAG 0x80 +#define PC_WORD_OFFSET 27 +#define BIT_64_TAG_PC_WORD 0x20 +#define BIT_96_TAG_PC_WORD 0x30 +#define TAG_EPC_OFFSET 29 + +#define SET_PARAM_CMD_MASK 0x8000 // commands with MSB set to 0 are to get the parameter and MSB of 1 to set the parameter +#define READER_BAUD_RATE 115200 // TODO check this +#define READ_BUF_SIZE 255 +#define TAG_EPC_BUF_SIZE 12 + +typedef enum { + AWAITING_HEADER, + AWAITING_DATA_LEN, + AWAITING_READ_CMD, + AWAITING_STATUS_1, + AWAITING_STATUS_2, + AWAITING_EPC_LENGTH, + AWAITING_PC_WORD, + READING_TAG_EPC, + READIG_TAG_CRC +} packetState_e; + +static uint8_t tagEPC[TAG_EPC_BUF_SIZE] = {0}; +static packetState_e state = AWAITING_HEADER; +static uint8_t tagBufIndex = 0; +static uint8_t skip = 0; +static uint16_t tagLen = 0; +static uint16_t dataLen = 0; + +#if 0 +static uint8_t head = 0; +static uint8_t tail = 0; +static bool receiving = 0; +static uint8_t readBuf[READ_BUF_SIZE] = {0}; +#endif + + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { DEBUG("Disconnected!\n\r"); DEBUG("Restarting the advertising process\n\r"); ble.startAdvertising(); + isConnected = 0; + led = isConnected; + +} + +void connectionCallback(const Gap::ConnectionCallbackParams_t *params) +{ + DEBUG("Connected!\n\r"); + isConnected = 1; + led = isConnected; } -/* set io pins based on the data color, r=red, y=yellow, o=off */ +static void sendBLENotification() +{ + uint8_t buf[READ_BUF_SIZE]; + uint8_t offset = 0; + memcpy(buf, &tagIdCmd, sizeof(uint16_t)); // command + offset+=sizeof(uint16_t); + memcpy(&buf[offset], &tagLen, sizeof(uint16_t)); // length of array + offset+=sizeof(uint16_t); + memcpy(&buf[offset], &tagEPC, tagLen); // tag EPC + offset+= tagLen; + ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), buf, offset); +} + + static void processData(const GattWriteCallbackParams *params) { - DEBUG("data: %d ", *(params->data)); - - if(params->len == 1) { - switch(*(params->data)) { - case 'r': - pin0 = 0; - pin1 = 0; - DEBUG("r \r\n"); + if(params->len >= 2) { + uint16_t command = params->data[0] + (params->data[1] << 8); + bool isSetCmd = (command & SET_PARAM_CMD_MASK) == SET_PARAM_CMD_MASK; + DEBUG("command: %d \r\n", command); + + switch(command & ~SET_PARAM_CMD_MASK) { + case tagIdCmd: + if(!isSetCmd && params->len == 2) { + // form the reply to send + DEBUG("CMD is GET code\n\r"); + sendBLENotification(); + } break; - case 'y': - pin0 = 1; - pin1 = 0; - DEBUG("y \r\n"); - break; - - case 'o': - pin0 = 1; - pin1 = 1; - DEBUG("o \r\n"); + case triggerCmd: + if(isSetCmd && params->len == 2) { + // TODO also need to send this information to the LED controller + DEBUG("CMD is SET triggerCmd\n\r"); + trigger = 0; + wait_ms(10); + trigger = 1; + } break; default: - DEBUG("default \r\n"); - pin0 = 0; - pin1 = 1; break; } } @@ -91,32 +174,193 @@ uint16_t bytesRead = params->len; DEBUG("received %u bytes\n\r", bytesRead); for(int i = 0; i < bytesRead; i++) { - DEBUG("0x%X", params->data[i]); + DEBUG("0x%X ", params->data[i]); } DEBUG("\n\r", bytesRead); - ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); + // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); processData(params); } } +// This function requires the entire scanned data to be available. It takes a pointer to the beginnig of the data array +// and does not do any checking of available data. ie very easy to break (currently not used- Instead use the parsePacket() +// function with each byte received from the serial port. +#if 0 +void checkForEPC(uint8_t* d) +{ + DEBUG("%02X ", *d); + if(*d == HEADER_FLAG && *(d + CMD_OFFSET) == EPC_READ_CMD) { + DEBUG("GOT READ COmmand =======\r\n"); + // this is response to a read tage EPC command + if(*(d + STATUS_OFFSET) == 0 && *(d + STATUS_OFFSET + 1) == 0) { + DEBUG("STATUS is OK =======\r\n"); + // state is Ok + if(*(d + EPC_LENGTH_OFFSET) == BIT_64_TAG_FLAG && *(d + PC_WORD_OFFSET) == BIT_64_TAG_PC_WORD) { + DEBUG("GOT 64bit EPC =======\r\n"); + // this is a 64 bit tag so the next 8 bytes are tag id and further 2 bytes are the tag CRC + memset(&tagEPC[0], 0, TAG_EPC_BUF_SIZE); + memcpy(&tagEPC[0], d + TAG_EPC_OFFSET, 8); // do not worry about the CRC for now + + for(int j = 0; j < 8; j++) { + DEBUG("%02X ", tagEPC[j]); + } + DEBUG("\r\n"); + } else if(*(d + EPC_LENGTH_OFFSET) == BIT_96_TAG_FLAG && *(d + PC_WORD_OFFSET) == BIT_96_TAG_PC_WORD) { + DEBUG("GOT 96bit EPC =======\r\n"); + // this is a 96 bit tag so the next 12 bytes are tag id and further 2 bytes are the tag CRC + memset(&tagEPC[0], 0, TAG_EPC_BUF_SIZE); + memcpy(&tagEPC[0], d + TAG_EPC_OFFSET, 12); // do not worry about the CRC for now + + for(int j = 0; j < 12; j++) { + DEBUG("%02X ", tagEPC[j]); + } + DEBUG("\r\n"); + } + } // Status OK + } // response to EPC +} +#endif + +// State machine to parse the tag data received from serial port. It looks for EPC data in the packet +static void parsePacket(uint8_t d) +{ + TRACE("%02X ", d); + switch (state) { + case AWAITING_HEADER: + if(d == HEADER_FLAG) { + TRACE("AWAITING_DATA_LEN \r\n"); + state = AWAITING_DATA_LEN; + skip = 0; + } + break; + + case AWAITING_DATA_LEN: + if(d > 0) { + dataLen = d; + state = AWAITING_READ_CMD; + TRACE("AWAITING_READ_CMD \r\n"); + } else { + state = AWAITING_HEADER; + } + break; + + case AWAITING_READ_CMD: + if(d == EPC_READ_CMD) { + state = AWAITING_STATUS_1; + TRACE("AWAITING_STATUS_1 \r\n"); + } else { + state = AWAITING_HEADER; + } + break; + + case AWAITING_STATUS_1: + if(d == 0) { + state = AWAITING_STATUS_2; + TRACE("AWAITING_STATUS_2 \r\n"); + } else { + state = AWAITING_HEADER; + } + break; + + case AWAITING_STATUS_2: + if(d == 0) { + state = AWAITING_EPC_LENGTH; + TRACE("AWAITING_EPC_LENGTH_1 \r\n"); + } else { + state = AWAITING_HEADER; + } + break; + + case AWAITING_EPC_LENGTH: + if(++skip >= 22) { + if(d == BIT_64_TAG_FLAG) { + state = AWAITING_PC_WORD; + tagLen = 8; + TRACE("AWAITING_PC_WORD \r\n"); + } else if (d == BIT_96_TAG_FLAG) { + state = AWAITING_PC_WORD; + tagLen = 12; + TRACE("AWAITING_PC_WORD \r\n"); + } else { + state = AWAITING_HEADER; + } + } + break; + + case AWAITING_PC_WORD: + if((tagLen == 8 && d == BIT_64_TAG_PC_WORD) || (tagLen == 12 && d == BIT_96_TAG_PC_WORD)) { + state = READING_TAG_EPC; + tagBufIndex = 0; + TRACE("READING_TAG_EPC \r\n"); + skip = 0; + } else { + state = AWAITING_HEADER; + } + break; + + case READING_TAG_EPC: + if(++skip >= 2) { + if(tagBufIndex < tagLen) { + tagEPC[tagBufIndex++] = d; + TRACE("%02X ", d); + } else { + // don't worry about CRC for now + state = AWAITING_HEADER; + TRACE("AWAITING_HEADER \r\n"); + + TRACE("TAG EPC: ============\r\n"); + //for(int i = 0; i < tagLen; i++) { +// TRACE("%02X ", tagEPC[i]); +// pc.printf("%02X ", tagEPC[i]); +// } +// pc.printf("\r\n"); + + sendBLENotification(); + } + } + break; + } +} + void periodicCallback(void) { // led1 = !led1; } +void readerCallback() +{ + // Note: Need to actually read from the serial to clear the RX interrupt + // receiving = true; + while(reader.readable()) { + uint8_t c = reader.getc(); + // readBuf[head++] = c; +// if(head >= READ_BUF_SIZE) { +// head = 0; +// } + parsePacket(c); + } + + // make sure LED stays on + led = isConnected; + + // receiving = false; +} + int main(void) { - pin0 = 1; - pin1 = 1; + // default state is unknown + led = 0; + Ticker ticker; - ticker.attach(periodicCallback, 1); + ticker.attach(periodicCallback, 5); DEBUG("Initialising the nRF51822\n\r"); ble.init(); ble.onDisconnection(disconnectionCallback); + ble.onConnection(connectionCallback); ble.onDataWritten(onDataWritten); /* setup advertising */ @@ -126,7 +370,7 @@ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)GattService::UUID_DEVICE_INFORMATION_SERVICE, sizeof(GattService::UUID_DEVICE_INFORMATION_SERVICE)); - ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); + ble.setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); ble.startAdvertising(); /* Setup uart service */ @@ -136,6 +380,10 @@ /* Setup auxiliary service. */ DeviceInformationService deviceInfo(ble, MANUFACTURER, MODEL, SERIAL_NO,HARDWARE_REV, FIRMWARE_REV, SOFTWARE_REV); + // setup serial port to RFID reader + reader.baud(READER_BAUD_RATE); + reader.attach(&readerCallback); + while (true) { ble.waitForEvent(); }