NFC API for mbed using the MicroNFCBoard as a peripheral
Dependents: MicroNFCBoardAPI_P2P_Client MicroNFCBoardAPI_Blink MicroNFCBoardAPI_Tag_Emulator MicroNFCBoardAPI_Tag_Reader ... more
Diff: transport.cpp
- Revision:
- 0:07fa9c0dd549
- Child:
- 1:1d246e0872c6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/transport.cpp Fri Apr 24 12:57:23 2015 +0000 @@ -0,0 +1,260 @@ +/** + * \file transport.cpp + * \copyright Copyright (c) AppNearMe Ltd 2015 + * \author Donatien Garnier + */ + +#include "transport.h" + + +//MSB first +#define WRITE_UINT32( addr, val ) do{ *(((uint8_t*)(addr)) + 0) = ((val) >> 24 ) & 0xFF; \ + *(((uint8_t*)(addr)) + 1) = ((val) >> 16 ) & 0xFF; \ + *(((uint8_t*)(addr)) + 2) = ((val) >> 8 ) & 0xFF; \ + *(((uint8_t*)(addr)) + 3) = ((val) >> 0 ) & 0xFF; } while(0) +#define WRITE_UINT16( addr, val ) do{ *(((uint8_t*)(addr)) + 0) = ((val) >> 8 ) & 0xFF; \ + *(((uint8_t*)(addr)) + 1) = ((val) >> 0 ) & 0xFF; } while(0) + +//MSB first +#define READ_UINT32( addr, val ) do{ val = (*(((uint8_t*)(addr)) + 0) << 24 ) \ + | (*(((uint8_t*)(addr)) + 1) << 16 ) \ + | (*(((uint8_t*)(addr)) + 2) << 8 ) \ + | (*(((uint8_t*)(addr)) + 3) << 0 ); } while(0) +#define READ_UINT16( addr, val ) do{ val = (*(((uint8_t*)(addr)) + 0) << 8 ) \ + | (*(((uint8_t*)(addr)) + 1) << 0 ); } while(0) + + +Transport::Transport(PinName mosi, PinName miso, PinName sck, PinName cs, PinName irq) : \ +_cs(cs), _spi(mosi, miso, sck), _int(irq) +{ +} + +void Transport::init() +{ + _spi.format(8, 1); + _spi.frequency(100000); + _cs = 1; + + for(int i = 0; i < 64; i++) + { + _cs = 0; + _spi.write(0); + _cs = 1; + } +} + +void Transport::reset() +{ + uint8_t out[] = {0}; + command(Transport::RESET, out, sizeof(out), NULL, 0); +} + +bool Transport::statusChanged() +{ + return (_int.read() != 0); +} + +uint32_t Transport::status() +{ + uint8_t in[4]; + command(Transport::GET_STATUS, NULL, 0, in, sizeof(in)); + + uint32_t status; + READ_UINT32(&in[0], status); + return status; +} + +void Transport::nfcPoll(bool enable) +{ + uint8_t out[] = {enable?1:0}; + command(Transport::NFC_POLL, out, sizeof(out), NULL, 0); +} + +void Transport::nfcOperation(bool readOp, bool writeOp) +{ + uint8_t out[1]; + if(readOp) + { + out[0] = 1; + } + else if(writeOp) + { + out[0] = 2; + } + else + { + out[0] = 0; + } + command(Transport::NFC_OPERATION, out, sizeof(out), NULL, 0); +} + +void Transport::nfcGetInfoIsoA(uint8_t* atqa, uint8_t* sak, uint8_t* uid, size_t* pUidLength) +{ + uint8_t in[2 + 1 + 1 + 10]; + command(Transport::NFC_GET_INFO, NULL, 0, in, sizeof(in)); + memcpy(atqa, &in[0], 2); + *sak = in[2]; + *pUidLength = in[3]; + memcpy(uid, &in[4], *pUidLength); +} + +void Transport::nfcGetMessageInfo(size_t* pRecordCount) +{ + uint8_t in[2]; + command(Transport::NFC_GET_MESSAGE_INFO, NULL, 0, in, sizeof(in)); + READ_UINT16(&in[0], *pRecordCount); +} + +void Transport::nfcSetMessageInfo(size_t recordCount) +{ + uint8_t out[2]; + WRITE_UINT16(&out[0], recordCount); + command(Transport::NFC_SET_MESSAGE_INFO, out, sizeof(out), NULL, 0); +} + +void Transport::nfcGetRecordInfo(size_t recordNumber, uint16_t* pType, uint16_t* info, size_t infoCount) +{ + uint8_t out[2]; + uint8_t in[2+2*infoCount]; + WRITE_UINT16(&out[0], recordNumber); + command(Transport::NFC_GET_RECORD_INFO, out, sizeof(out), in, sizeof(in)); + READ_UINT16(&in[0], *pType); + for(int i = 0; i < infoCount; i++) + { + READ_UINT16(&in[2+2*i], info[i]); + } +} + +void Transport::nfcSetRecordInfo(size_t recordNumber, uint16_t type, uint16_t* info, size_t infoCount) +{ + uint8_t out[2+2+2*infoCount]; + WRITE_UINT16(&out[0], recordNumber); + WRITE_UINT16(&out[2], type); + for(int i = 0; i < infoCount; i++) + { + WRITE_UINT16(&out[2+2+2*i], info[i]); + } + command(Transport::NFC_SET_RECORD_INFO, out, sizeof(out), NULL, 0); +} + +void Transport::nfcGetRecordData(size_t recordNumber, size_t item, size_t offset, uint8_t* data, size_t length) +{ + uint8_t out[7]; + WRITE_UINT16(&out[0], recordNumber); + out[2] = item; + WRITE_UINT16(&out[3], offset); + WRITE_UINT16(&out[5], length); + command(Transport::NFC_GET_RECORD_DATA, out, sizeof(out), data, length); +} + +void Transport::nfcSetRecordData(size_t recordNumber, size_t item, size_t offset, uint8_t* data, size_t length) +{ + uint8_t out[7+length]; + WRITE_UINT16(&out[0], recordNumber); + out[2] = item; + WRITE_UINT16(&out[3], offset); + WRITE_UINT16(&out[5], length); + memcpy(&out[7], data, length); + command(Transport::NFC_SET_RECORD_DATA, out, sizeof(out), NULL, 0); +} + +void Transport::nfcPrepareMessage(bool lock, bool generate) +{ + uint8_t out[1]; + if(lock) + { + out[0] = 1; + } + else if(generate) + { + out[0] = 2; + } + else + { + out[0] = 0; + } + command(Transport::NFC_POLL, out, sizeof(out), NULL, 0); +} + +void Transport::nfcDecodePrefix(uint8_t prefix, char* data, size_t* pDataLength) +{ + uint8_t out[] = { prefix }; + uint8_t in[2 + 36]; //max prefix length is 36 + command(Transport::NFC_DECODE_PREFIX, out, sizeof(out), in, sizeof(in)); + size_t length; + READ_UINT16(&in[0], length); + if(length < *pDataLength) + { + *pDataLength = length; + } + memcpy(data, &in[2], *pDataLength); +} + +void Transport::nfcEncodePrefix(uint8_t* pPrefix, char* data, size_t dataLength) +{ + uint8_t out[2 + dataLength]; + uint8_t in[1]; + + WRITE_UINT16(&out[0], dataLength); + memcpy(data, &out[2], dataLength); + + command(Transport::NFC_ENCODE_PREFIX, out, sizeof(out), in, sizeof(in)); + + *pPrefix = in[0]; +} + +void Transport::leds(bool led1, bool led2) +{ + uint8_t out[] = {led1?1:0, led2?1:0}; + command(Transport::LEDS, out, sizeof(out), NULL, 0); +} + +Transport::CommandError Transport::command(Transport::CommandCode command, uint8_t* outBuf, size_t outLength, uint8_t* inBuf, size_t inLength) +{ + _cs = 0; + _spi.write((uint8_t)((outLength + 1) & 0xFF)); + _cs = 1; + _cs = 0; + _spi.write((uint8_t)(command & 0xFF)); + _cs = 1; + for(int i = 0; i < outLength; i++) + { + _cs = 0; + _spi.write(outBuf[i]); + _cs = 1; + } + + size_t length = 0; + while(length == 0) + { + _cs = 0; + length = _spi.write(0); + _cs = 1; + } + + _cs = 0; + Transport::CommandCode retCmd = (Transport::CommandCode)_spi.write(0); + length--; + _cs = 1; + + _cs = 0; + Transport::CommandError ret = (Transport::CommandError)_spi.write(0); + length--; + _cs = 1; + + for(int i = 0; i < length; i++) + { + _cs = 0; + if(i < inLength) + { + inBuf[i] = _spi.write(0); + } + else + { + _spi.write(0); + } + _cs = 1; + } + + return ret; +}