ongoing Development Project for interfacing a BM019 Module with nrf51-dk, acting as a nfc 2 ble bridge. Base project for opensource blueReader Device
Dependencies: BLE_API mbed nRF51822
Diff: bm019.cpp
- Revision:
- 0:d156731c291b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bm019.cpp Sat Apr 16 14:00:28 2016 +0000 @@ -0,0 +1,436 @@ +#include "bm019.h" + +volatile uint8_t rxBuffer[BM019_MAX_RX]; + +uint8_t BM019_CMD_IDN[] = {2,0x01,0x00}; + +uint8_t BM019_CMD_ECHO[] = {1,0x55}; + +uint8_t BM019_CMD_PROTOCOL_START[] = {2,0x02,0x02}; +uint8_t BM019_CMD_PROTOCOL_ISO_IEC_15693[] = {2,0x01,0x00}; +uint8_t BM019_CMD_PROTOCOL_OFF[] = {2,0x00,0x00}; + +uint8_t BM019_CMD_HYBERNATE[] = {15, + 0x07, //idle + 0x0E, //14 bytes + 0x08, //WU source low pulse irq + 0x04, 0x00, //Enter Control hybernate + 0x04, 0x00, //WU Control hybernate + 0x18, 0x00, //Leave Control hybernate + 0x00, //WU Period 0 + 0x00, //Osc Start + 0x00, //DAC Start + 0x00, 0x00, //DAC Data + 0x00, //Swing Count + 0x00 //Max Sleep + }; + +uint8_t BM019_CMD_ISO_IEC_15693_INVENTORY[] = {5, 0x04, //send recieve + 0x03,//length + 0x26, //options: + /* + 0 -> bit 0: Subcarrier 0 = ask, 1 =fsk + 1 -> bit 1: uplink data rate 0 = low, 1 = high + 1 -> bit 2: inventory flags 0 -> a), 1 -> b) + 0 -> bit 3: proto extension = 0 + a) + bit 4: select flag 0 = if(bit 5 = 1 address mode) + bit 5: address flag 1 = use address + bit 6: for write = 1, else 0 + bit 7: future usage, always 0 + b) + 0 -> bit 4: afi flag 0 = no afi, 1 = afi (Application family identification) + 1 -> bit 5: slot flag, 0 -> 16 slots, 1 -> 1 slot + 0 -> bit 6: for write = 1, else 0 + 0 -> bit 7: future usage, always 0 + + */ + 0x01, // inventory command + 0x00 // do not know why i sent it, maybe useless? + }; + +uint8_t BM019_CMD_READ[] = {5, + 0x04, //send recieve + 0x03, //length + 0x02, //options + 0x20, //read + 0x00 //Address + + }; +uint8_t BM019_CMD_READ_MULTI[] = {6, + 0x04, //send recieve + 0x00, //length + 0x02, //options + 0x23, //read + 0x00, //address + 0x00 //count + }; +enum BM019_PROTOCOL { + BM019_PROTOCOL_Field_OFF = 0x00, + BM019_PROTOCOL_ISO_IEC_15693 = 0x01, + //other not yet supported! + BM019_PROTOCOL_ISO_IEC_14443_Type_A = 0x02,// also NFC Forum Tag Type 1 (Topaz), NFC Forum Tag Type 2, NFC Forum Tag Type 4A + BM019_PROTOCOL_ISO_IEC_14443_Type_B = 0x03,// also NFC Forum Tag Type 4B + BM019_PROTOCOL_ISO_IEC_18092 = 0x04 // also NFC Forum Tag Type 3 +}; + +SPI spi(BM019_MOSI, BM019_MISO, BM019_CLK); + +DigitalOut ss(BM019_CS); +DigitalOut wake(BM019_IRQ); + +BM019_STATE stateBM019 = BM019_STATE_UNKNOWN; + +int write_read(uint8_t *tx_buf, int tx_len, int timeout = BM019_READY_TIMEOUT); //write, poll, read + +/*bool stateAtLeast(BM019_STATE requiredState) +{ + if(stateBM019 < requiredState) + { + DEBUG("required state %d, having state %d",requiredState,stateBM019); + return false; + } + return true; +}*/ + +bool resetBM019() +{ + if(stateBM019 < BM019_STATE_ANSWERING) { + DEBUG("IDN failed, bm019 not answering\n"); + return false; + } + DEBUG("BM019: reset\n"); + ss=0; + spi.write(0x01); + ss=1; + wait_ms(20); + stateBM019 = BM019_STATE_UNKNOWN; + return true; +} + +bool echoBM019(int timeout, bool log) +{ + if(log) { + DEBUG("BM019: echo\n"); + } + int len = write_read(&BM019_CMD_ECHO[1],BM019_CMD_ECHO[0], timeout); + if(len>=1 && rxBuffer[0] == 0x55) { + stateBM019 = stateBM019 > BM019_STATE_ANSWERING ? stateBM019 : BM019_STATE_ANSWERING; + return true; + } else { + if(log) { + DEBUG("recievedlen: %d \n",len); + + for(int i = 0; i < len; i++) + DEBUG("rx[%d]: %#x\n",i,rxBuffer[i]); + } + } + stateBM019 = BM019_STATE_UNKNOWN; + return false; +} + +BM019_STATE getStateBM019() +{ + return stateBM019; +} + +bool wakeBM019(int timeout) +{ + DEBUG("BM019: wake\n"); + ss=0; + wake = 0; + wait_ms(10); + wake = 1; + ss = 1; + + wait_ms(timeout); + int t = 10; + + stateBM019 = BM019_STATE_UNKNOWN; + while(!echoBM019(10,false) && t > 0) { + wait_ms(10); + t--; + } + if(t<0) { + return false; + } + return true; +} + + + +int waitReady(int timeoutMS = 0) +{ + int ready = 0; + + if(timeoutMS) { + Timer t; + t.start(); + ss=0; + while(!ready) { + wait_ms(1); + ready = spi.write(0x03) & 0x08; + if(t.read_ms()>timeoutMS) { + break; + } + } + ss = 1; + } else { + ss=0; + while(!ready) { + wait_ms(1); + ready = spi.write(0x03); + ready = ready & 0x08; + } + ss = 1; + } + return ready; +} + +void write(uint8_t *tx_buf, int tx_len) +{ + ss=0; + spi.write(0x00); + for(int i = 0; i < tx_len; i++) { + spi.write(tx_buf[i]); + } + ss=1; +} + +int readBM019() +{ + ss=0; + spi.write(0x02); + rxBuffer[0] = spi.write(0x00); + int len = 0; + if(rxBuffer[0] != 0x55) { + len = rxBuffer[1] = spi.write(0x00); + for(int i = 0; i < len && i < BM019_MAX_RX; i++) { + rxBuffer[i+2] = spi.write(0x00); + } + len += 2; + } else { + len = 1; + } + ss=1; + return len; +} + +int write_read(uint8_t *tx_buf, int tx_len, int timeout) +{ + write(tx_buf, tx_len); + waitReady(timeout); + return readBM019(); +} + +bool setProtocolISO_EIC_15693BM019(BM019_PROTOCOL_ISO_IEC_15693_BYTE_0 configuration) +{ + if(stateBM019 < BM019_STATE_ANSWERING) { + DEBUG("SETTING Protocol failed, bm019 not answering\n"); + return false; + } + DEBUG("SETTING Protocol to iso/iec 15693: %#x\n",configuration); + + int len = BM019_CMD_PROTOCOL_START[0]+BM019_CMD_PROTOCOL_ISO_IEC_15693[0]; + + uint8_t iso[BM019_CMD_PROTOCOL_START[0]+BM019_CMD_PROTOCOL_ISO_IEC_15693[0]]; + memcpy(iso,&BM019_CMD_PROTOCOL_START[1],BM019_CMD_PROTOCOL_START[0]); + memcpy(&iso[BM019_CMD_PROTOCOL_START[0]],&BM019_CMD_PROTOCOL_ISO_IEC_15693[1],BM019_CMD_PROTOCOL_ISO_IEC_15693[0]); + iso[len-1] = configuration; + + int recieved = write_read(iso,len,20); + if(recieved >= 2 && rxBuffer[0] == 0x00 && rxBuffer[1] == 0x00) { + stateBM019 = stateBM019 > BM019_STATE_PROTOCOL ? stateBM019 : BM019_STATE_PROTOCOL; + return true; + } else { + DEBUG("SETTING Protocol failed: %#x\n",rxBuffer[0]); + stateBM019 = BM019_STATE_UNKNOWN; + return false; + } +} + +bool setProtocolOFF() +{ + if(stateBM019 < BM019_STATE_ANSWERING) { + DEBUG("SETTING Protocol failed, bm019 not answering\n"); + return false; + } + DEBUG("SETTING Protocol to OFF\n"); + + int len = BM019_CMD_PROTOCOL_START[0]+BM019_CMD_PROTOCOL_OFF[0]; + uint8_t off[BM019_CMD_PROTOCOL_START[0]+BM019_CMD_PROTOCOL_OFF[0]]; + memcpy(off,&BM019_CMD_PROTOCOL_START[1],BM019_CMD_PROTOCOL_START[0]); + memcpy(&off[BM019_CMD_PROTOCOL_START[0]],&BM019_CMD_PROTOCOL_OFF[1],BM019_CMD_PROTOCOL_OFF[0]); + + int recieved = write_read(off,len,20); + if(recieved >= 2 && rxBuffer[0] == 0x00 && rxBuffer[1] == 0x00) { + stateBM019 = BM019_STATE_ANSWERING; + return true; + } else { + DEBUG("SETTING Protocol failed: %#x\n",rxBuffer[0]); + stateBM019 = BM019_STATE_UNKNOWN; + return false; + } +} + +bool idnBM019(BM019_IDN *idn) +{ + if(stateBM019 < BM019_STATE_ANSWERING) { + DEBUG("IDN failed, bm019 not answering\n"); + return false; + } + int len = write_read(&BM019_CMD_IDN[1],BM019_CMD_IDN[0]); + if(len == 17) { + memcpy(idn->deviceID,(const void *)&rxBuffer[2],13); + memcpy(idn->romCRC,(const void *)&rxBuffer[15],2); + return true; + } + return false; + +} + +bool hybernateBM019() +{ + if(stateBM019 < BM019_STATE_ANSWERING) { + DEBUG("SETTING HYBERNATE failed, bm019 not answering\n"); + return false; + } + + DEBUG("HYBERNATE bm019 (FIELD_OFF and POWER_DOWN)\n"); + if(setProtocolOFF()) { + write(&BM019_CMD_HYBERNATE[1],BM019_CMD_HYBERNATE[0]); + stateBM019 = BM019_STATE_UNKNOWN; + return true; + } + return false; +} + + +bool inventoryISO_IES_15693BM019(BM019_TAG *tag, int timeout) +{ + if(stateBM019 < BM019_STATE_PROTOCOL) { + DEBUG("inventory failed, bm019 not in protocol\n"); + return false; + } + + DEBUG("inventory.."); + + int len = write_read(&BM019_CMD_ISO_IEC_15693_INVENTORY[1],BM019_CMD_ISO_IEC_15693_INVENTORY[0]); + + DEBUG("got answer len()=%d\n",len); + for(int i = 0; i < len; i++) { + DEBUG("%#04x ",rxBuffer[i]); + } + DEBUG("\n"); + + if(rxBuffer[0] != EFrameRecvOK) { + DEBUG("got error %#04x\n",rxBuffer[0]); + return false; + } + + int tlen = rxBuffer[1]; + if(tlen < 11) { + DEBUG("to few bytes recieved \n"); + return false; + } + /* this does not work very good, maybe something misinterpreted from docs + if(rxBuffer[tlen-1] & 0x01) { + DEBUG("got collision \n"); + return false; + } + if(rxBuffer[tlen-1] & 0x02) { + DEBUG("got bad crc \n"); + return false; + }*/ + tag->crc[0] = rxBuffer[tlen-2]; + tag->crc[1] = rxBuffer[tlen-3]; + + for(int i = 0; i < 9; i++) { + tag->uid[i] = rxBuffer[11-i]; + } + return true; + +} + +int readBM019(uint8_t adr, uint8_t *buf, int len, int timeout) +{ + if(stateBM019 < BM019_STATE_PROTOCOL) { + DEBUG("read failed, bm019 not in protocol\n"); + return -1; + } + uint8_t cmd[BM019_CMD_READ[0]]; + memcpy(cmd,&BM019_CMD_READ[1],BM019_CMD_READ[0]); + cmd[BM019_CMD_READ[0]-1] = adr & 0xFF; + + DEBUG("read at %#4X..\n",adr); + for(int i = 0; i < BM019_CMD_READ[0]; i++) { + DEBUG("%#04x ",cmd[i]); + } + int tx = write_read(cmd,BM019_CMD_READ[0]); + + DEBUG("got answer len()=%d\n",tx); + for(int i = 0; i < tx; i++) { + DEBUG("%#04x ",rxBuffer[i]); + } + DEBUG("\n"); + if(rxBuffer[0] != EFrameRecvOK) { + DEBUG("got error %#04x\n",rxBuffer[0]); + return -1; + } + + DEBUG("flags: %#04x\n",rxBuffer[2]); + int tlen = rxBuffer[1]-4; + if(tlen <=0) + return -1; + DEBUG("read resultet in %d bytes, copying %d bytes\n",rxBuffer[1],(tlen < len ? tlen : len)); + tlen = (tlen < len ? tlen : len); + memcpy(buf,(const void *)&rxBuffer[3],tlen); + + return tlen; +} + +int readMultiBM019(uint8_t adr, int count, uint8_t *buf, int len, int timeout) +{ + if(stateBM019 < BM019_STATE_PROTOCOL) { + DEBUG("multi read failed, bm019 not in protocol\n"); + return -1; + } + uint8_t cmd[BM019_CMD_READ_MULTI[0]]; + memcpy(cmd,&BM019_CMD_READ_MULTI[1],BM019_CMD_READ_MULTI[0]); + cmd[BM019_CMD_READ_MULTI[0]-2] = adr & 0xFF; + cmd[BM019_CMD_READ_MULTI[0]-1] = (count-1) & 0xFF; + + DEBUG("multi read at %#4X for %d..\n",adr, count & 0xFF); + for(int i = 0; i < BM019_CMD_READ_MULTI[0]; i++) { + DEBUG("%#04x ",cmd[i]); + } + int tx = write_read(cmd,BM019_CMD_READ_MULTI[0]); + + DEBUG("got answer len()=%d\n",tx); + for(int i = 0; i < tx; i++) { + DEBUG("%02x ",rxBuffer[i]); + } + DEBUG("\n"); + if(rxBuffer[0] != EFrameRecvOK) { + DEBUG("got error %#04x\n",rxBuffer[0]); + return -1; + } + + DEBUG("flags: %#04x\n",rxBuffer[2]); + int tlen = rxBuffer[1]-4; + if(tlen <=0) + return -1; + DEBUG("read resultet in %d bytes, copying %d bytes\n",rxBuffer[1],(tlen < len ? tlen : len)); + tlen = (tlen < len ? tlen : len); + memcpy(buf,(const void *)&rxBuffer[3],tlen); + + return tlen; +} +bool initBM019() +{ + DEBUG("BM019: init\n"); + spi.format(8,3); + spi.frequency(1000000); + stateBM019 = BM019_STATE_UNKNOWN; + return true; +}