├── Wire.cpp ├── Wire.h ├── examples ├── nfc_mifare_mf1s50_reader │ └── nfc_mifare_mf1s50_reader.ino ├── nfc_p2p_initiator │ └── nfc_p2p_initiator.ino └── nfc_p2p_target │ └── nfc_p2p_target.ino ├── nfc.cpp ├── nfc.h └── utility ├── twi.c └── twi.h /Wire.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | TwoWire.cpp - TWI/I2C library for Wiring & Arduino 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | extern "C" { 21 | #include 22 | #include 23 | #include 24 | #include "twi.h" 25 | } 26 | 27 | #include "Wire.h" 28 | 29 | // Initialize Class Variables ////////////////////////////////////////////////// 30 | 31 | uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; 32 | uint8_t TwoWire::rxBufferIndex = 0; 33 | uint8_t TwoWire::rxBufferLength = 0; 34 | 35 | uint8_t TwoWire::txAddress = 0; 36 | uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; 37 | uint8_t TwoWire::txBufferIndex = 0; 38 | uint8_t TwoWire::txBufferLength = 0; 39 | 40 | uint8_t TwoWire::transmitting = 0; 41 | void (*TwoWire::user_onRequest)(void); 42 | void (*TwoWire::user_onReceive)(int); 43 | 44 | // Constructors //////////////////////////////////////////////////////////////// 45 | 46 | TwoWire::TwoWire() 47 | { 48 | } 49 | 50 | // Public Methods ////////////////////////////////////////////////////////////// 51 | 52 | void TwoWire::begin(void) 53 | { 54 | rxBufferIndex = 0; 55 | rxBufferLength = 0; 56 | 57 | txBufferIndex = 0; 58 | txBufferLength = 0; 59 | 60 | twi_init(); 61 | } 62 | 63 | void TwoWire::begin(uint8_t address) 64 | { 65 | twi_setAddress(address); 66 | twi_attachSlaveTxEvent(onRequestService); 67 | twi_attachSlaveRxEvent(onReceiveService); 68 | begin(); 69 | } 70 | 71 | void TwoWire::begin(int address) 72 | { 73 | begin((uint8_t)address); 74 | } 75 | 76 | uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) 77 | { 78 | // clamp to buffer length 79 | if(quantity > BUFFER_LENGTH){ 80 | quantity = BUFFER_LENGTH; 81 | } 82 | // perform blocking read into buffer 83 | uint8_t read = twi_readFrom(address, rxBuffer, quantity); 84 | // set rx buffer iterator vars 85 | rxBufferIndex = 0; 86 | rxBufferLength = read; 87 | 88 | return read; 89 | } 90 | 91 | uint8_t TwoWire::requestFrom(int address, int quantity) 92 | { 93 | return requestFrom((uint8_t)address, (uint8_t)quantity); 94 | } 95 | 96 | void TwoWire::beginTransmission(uint8_t address) 97 | { 98 | // indicate that we are transmitting 99 | transmitting = 1; 100 | // set address of targeted slave 101 | txAddress = address; 102 | // reset tx buffer iterator vars 103 | txBufferIndex = 0; 104 | txBufferLength = 0; 105 | } 106 | 107 | void TwoWire::beginTransmission(int address) 108 | { 109 | beginTransmission((uint8_t)address); 110 | } 111 | 112 | uint8_t TwoWire::endTransmission(void) 113 | { 114 | // transmit buffer (blocking) 115 | int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1); 116 | // reset tx buffer iterator vars 117 | txBufferIndex = 0; 118 | txBufferLength = 0; 119 | // indicate that we are done transmitting 120 | transmitting = 0; 121 | return ret; 122 | } 123 | 124 | // must be called in: 125 | // slave tx event callback 126 | // or after beginTransmission(address) 127 | size_t TwoWire::write(uint8_t data) 128 | { 129 | if(transmitting){ 130 | // in master transmitter mode 131 | // don't bother if buffer is full 132 | if(txBufferLength >= BUFFER_LENGTH){ 133 | setWriteError(); 134 | return 0; 135 | } 136 | // put byte in tx buffer 137 | txBuffer[txBufferIndex] = data; 138 | ++txBufferIndex; 139 | // update amount in buffer 140 | txBufferLength = txBufferIndex; 141 | }else{ 142 | // in slave send mode 143 | // reply to master 144 | twi_transmit(&data, 1); 145 | } 146 | return 1; 147 | } 148 | 149 | // must be called in: 150 | // slave tx event callback 151 | // or after beginTransmission(address) 152 | size_t TwoWire::write(const uint8_t *data, size_t quantity) 153 | { 154 | if(transmitting){ 155 | // in master transmitter mode 156 | for(size_t i = 0; i < quantity; ++i){ 157 | write(data[i]); 158 | } 159 | }else{ 160 | // in slave send mode 161 | // reply to master 162 | twi_transmit(data, quantity); 163 | } 164 | return quantity; 165 | } 166 | 167 | // must be called in: 168 | // slave rx event callback 169 | // or after requestFrom(address, numBytes) 170 | int TwoWire::available(void) 171 | { 172 | return rxBufferLength - rxBufferIndex; 173 | } 174 | 175 | // must be called in: 176 | // slave rx event callback 177 | // or after requestFrom(address, numBytes) 178 | int TwoWire::read(void) 179 | { 180 | int value = -1; 181 | 182 | // get each successive byte on each call 183 | if(rxBufferIndex < rxBufferLength){ 184 | value = rxBuffer[rxBufferIndex]; 185 | ++rxBufferIndex; 186 | } 187 | 188 | return value; 189 | } 190 | 191 | // must be called in: 192 | // slave rx event callback 193 | // or after requestFrom(address, numBytes) 194 | int TwoWire::peek(void) 195 | { 196 | int value = -1; 197 | 198 | if(rxBufferIndex < rxBufferLength){ 199 | value = rxBuffer[rxBufferIndex]; 200 | } 201 | 202 | return value; 203 | } 204 | 205 | void TwoWire::flush(void) 206 | { 207 | // XXX: to be implemented. 208 | } 209 | 210 | // behind the scenes function that is called when data is received 211 | void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) 212 | { 213 | // don't bother if user hasn't registered a callback 214 | if(!user_onReceive){ 215 | return; 216 | } 217 | // don't bother if rx buffer is in use by a master requestFrom() op 218 | // i know this drops data, but it allows for slight stupidity 219 | // meaning, they may not have read all the master requestFrom() data yet 220 | if(rxBufferIndex < rxBufferLength){ 221 | return; 222 | } 223 | // copy twi rx buffer into local read buffer 224 | // this enables new reads to happen in parallel 225 | for(uint8_t i = 0; i < numBytes; ++i){ 226 | rxBuffer[i] = inBytes[i]; 227 | } 228 | // set rx iterator vars 229 | rxBufferIndex = 0; 230 | rxBufferLength = numBytes; 231 | // alert user program 232 | user_onReceive(numBytes); 233 | } 234 | 235 | // behind the scenes function that is called when data is requested 236 | void TwoWire::onRequestService(void) 237 | { 238 | // don't bother if user hasn't registered a callback 239 | if(!user_onRequest){ 240 | return; 241 | } 242 | // reset tx buffer iterator vars 243 | // !!! this will kill any pending pre-master sendTo() activity 244 | txBufferIndex = 0; 245 | txBufferLength = 0; 246 | // alert user program 247 | user_onRequest(); 248 | } 249 | 250 | // sets function called on slave write 251 | void TwoWire::onReceive( void (*function)(int) ) 252 | { 253 | user_onReceive = function; 254 | } 255 | 256 | // sets function called on slave read 257 | void TwoWire::onRequest( void (*function)(void) ) 258 | { 259 | user_onRequest = function; 260 | } 261 | 262 | // Preinstantiate Objects ////////////////////////////////////////////////////// 263 | 264 | TwoWire Wire = TwoWire(); 265 | 266 | -------------------------------------------------------------------------------- /Wire.h: -------------------------------------------------------------------------------- 1 | /* 2 | TwoWire.h - TWI/I2C library for Arduino & Wiring 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef TwoWire_h 21 | #define TwoWire_h 22 | 23 | #include 24 | #include "Stream.h" 25 | 26 | #define BUFFER_LENGTH 64 27 | 28 | class TwoWire : public Stream 29 | { 30 | private: 31 | static uint8_t rxBuffer[]; 32 | static uint8_t rxBufferIndex; 33 | static uint8_t rxBufferLength; 34 | 35 | static uint8_t txAddress; 36 | static uint8_t txBuffer[]; 37 | static uint8_t txBufferIndex; 38 | static uint8_t txBufferLength; 39 | 40 | static uint8_t transmitting; 41 | static void (*user_onRequest)(void); 42 | static void (*user_onReceive)(int); 43 | static void onRequestService(void); 44 | static void onReceiveService(uint8_t*, int); 45 | public: 46 | TwoWire(); 47 | void begin(); 48 | void begin(uint8_t); 49 | void begin(int); 50 | void beginTransmission(uint8_t); 51 | void beginTransmission(int); 52 | uint8_t endTransmission(void); 53 | uint8_t requestFrom(uint8_t, uint8_t); 54 | uint8_t requestFrom(int, int); 55 | virtual size_t write(uint8_t); 56 | virtual size_t write(const uint8_t *, size_t); 57 | virtual int available(void); 58 | virtual int read(void); 59 | virtual int peek(void); 60 | virtual void flush(void); 61 | void onReceive( void (*)(int) ); 62 | void onRequest( void (*)(void) ); 63 | 64 | using Print::write; 65 | }; 66 | 67 | extern TwoWire Wire; 68 | 69 | #endif 70 | 71 | -------------------------------------------------------------------------------- /examples/nfc_mifare_mf1s50_reader/nfc_mifare_mf1s50_reader.ino: -------------------------------------------------------------------------------- 1 | /** 2 | @file nfc_mifare_mf1s50_reader.ino 3 | @author www.elechouse.com 4 | @brief example of reading mf1s50 card for NFC_MODULE 5 | 6 | For this demo, waiting for a MF1S50 card or tag, after reading a card/tag UID, 7 | then try to read the block 4/5/6/7 .. 8 | 9 | @section HISTORY 10 | 11 | V1.0 initial version 12 | 13 | Copyright (c) 2012 www.elechouse.com All right reserved. 14 | */ 15 | 16 | /** include library */ 17 | #include "Wire.h" 18 | #include "nfc.h" 19 | 20 | /** define a nfc class */ 21 | NFC_Module nfc; 22 | 23 | void setup(void) 24 | { 25 | Serial.begin(9600); 26 | nfc.begin(); 27 | Serial.println("MF1S50 Reader Demo From Elechouse!"); 28 | 29 | uint32_t versiondata = nfc.get_version(); 30 | if (! versiondata) { 31 | Serial.print("Didn't find PN53x board"); 32 | while (1); // halt 33 | } 34 | 35 | // Got ok data, print it out! 36 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 37 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 38 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 39 | 40 | /** Set normal mode, and disable SAM */ 41 | nfc.SAMConfiguration(); 42 | } 43 | 44 | void loop(void) 45 | { 46 | u8 buf[32],sta; 47 | 48 | 49 | /** Polling the mifar card, buf[0] is the length of the UID */ 50 | sta = nfc.InListPassiveTarget(buf); 51 | 52 | /** check state and UID length */ 53 | if(sta && buf[0] == 4){ 54 | /** the card may be Mifare Classic card, try to read the block */ 55 | Serial.print("UUID length:"); 56 | Serial.print(buf[0], DEC); 57 | Serial.println(); 58 | Serial.print("UUID:"); 59 | nfc.puthex(buf+1, buf[0]); 60 | Serial.println(); 61 | /** factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF */ 62 | u8 key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 63 | u8 blocknum = 4; 64 | /** Authentication blok 4 */ 65 | sta = nfc.MifareAuthentication(0, blocknum, buf+1, buf[0], key); 66 | if(sta){ 67 | /** save read block data */ 68 | u8 block[16]; 69 | Serial.println("Authentication success."); 70 | 71 | // uncomment following lines for writing data to blok 4 72 | /* 73 | strcpy((char*)block, "Elechoues - NFC"); 74 | sta = nfc.MifareWriteBlock(blocknum, block); 75 | if(sta){ 76 | Serial.println("Write block successfully:"); 77 | } 78 | */ 79 | 80 | /** read block 4 */ 81 | sta = nfc.MifareReadBlock(blocknum, block); 82 | if(sta){ 83 | Serial.println("Read block successfully:"); 84 | 85 | nfc.puthex(block, 16); 86 | Serial.println(); 87 | } 88 | 89 | /** read block 5 */ 90 | sta = nfc.MifareReadBlock(blocknum+1, block); 91 | if(sta){ 92 | Serial.println("Read block successfully:"); 93 | 94 | nfc.puthex(block, 16); 95 | Serial.println(); 96 | } 97 | 98 | /** read block 6 */ 99 | sta = nfc.MifareReadBlock(blocknum+2, block); 100 | if(sta){ 101 | Serial.println("Read block successfully:"); 102 | 103 | nfc.puthex(block, 16); 104 | Serial.println(); 105 | } 106 | 107 | /** read block 7 */ 108 | sta = nfc.MifareReadBlock(blocknum+3, block); 109 | if(sta){ 110 | Serial.println("Read block successfully:"); 111 | 112 | nfc.puthex(block, 16); 113 | Serial.println(); 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /examples/nfc_p2p_initiator/nfc_p2p_initiator.ino: -------------------------------------------------------------------------------- 1 | /** 2 | @file nfc_p2p_initiator.ino 3 | @author www.elechouse.com 4 | @brief example of Peer to Peer communication for NFC_MODULE. 5 | 6 | For this demo, initiator waiting for target proximity. As soon as the 7 | target sensed, the initiator exchange data with the target. 8 | By this demo, initiator sends "Hi, this message comes from NFC INITIATOR." 9 | 10 | NOTE: this library only support MAX 50 bytes data packet, that is the tx_len must 11 | less than 50.. 12 | 13 | @section HISTORY 14 | 15 | V1.0 initial version 16 | 17 | Copyright (c) 2012 www.elechouse.com All right reserved. 18 | */ 19 | 20 | /** include library */ 21 | #include "nfc.h" 22 | 23 | /** define a nfc class */ 24 | NFC_Module nfc; 25 | /** define RX and TX buffers, and length variable */ 26 | u8 tx_buf[50]="Hi, this message comes from NFC INITIATOR."; 27 | u8 tx_len; 28 | u8 rx_buf[50]; 29 | u8 rx_len; 30 | 31 | void setup(void) 32 | { 33 | Serial.begin(115200); 34 | /** nfc initial */ 35 | nfc.begin(); 36 | Serial.println("P2P Initiator Demo BY ELECHOSUE!"); 37 | 38 | uint32_t versiondata = nfc.get_version(); 39 | if (! versiondata) { 40 | Serial.println("Didn't find PN53x board"); 41 | while (1); // halt 42 | } 43 | 44 | // Got ok data, print it out! 45 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 46 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 47 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 48 | 49 | /** Set normal mode, and disable SAM */ 50 | nfc.SAMConfiguration(); 51 | } 52 | 53 | void loop(void) 54 | { 55 | 56 | /** device is configured as Initiator */ 57 | if(nfc.P2PInitiatorInit()){ 58 | Serial.println("Target is sensed."); 59 | 60 | /** 61 | send data with a length parameter and receive some data, 62 | tx_buf --- data send buffer 63 | tx_len --- data send legth 64 | rx_buf --- data recieve buffer, return by P2PInitiatorTxRx 65 | rx_len --- data receive length, return by P2PInitiatorTxRx 66 | */ 67 | tx_len = strlen((const char*)tx_buf); 68 | if(nfc.P2PInitiatorTxRx(tx_buf, tx_len, rx_buf, &rx_len)){ 69 | /** send and receive successfully */ 70 | Serial.print("Data Received: "); 71 | Serial.write(rx_buf, rx_len); 72 | Serial.println(); 73 | } 74 | Serial.println(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /examples/nfc_p2p_target/nfc_p2p_target.ino: -------------------------------------------------------------------------------- 1 | /** 2 | @file nfc_p2p_target.ino 3 | @author www.elechouse.com 4 | @brief example of Peer to Peer communication for NFC_MODULE. 5 | 6 | By this demo, target send "Hi, this message comes from NFC TARGET." 7 | 8 | NOTE: this library only support MAX 50 bytes data packet, that is the tx_len must 9 | less than 50.. 10 | 11 | @section HISTORY 12 | 13 | V1.0 initial version 14 | 15 | Copyright (c) 2012 www.elechouse.com All right reserved. 16 | */ 17 | 18 | /** include library */ 19 | #include "nfc.h" 20 | 21 | /** define a nfc class */ 22 | NFC_Module nfc; 23 | 24 | /** define RX and TX buffers, and length variable */ 25 | u8 tx_buf[50]="Hi, This message comes from NFC TARGET."; 26 | u8 tx_len; 27 | u8 rx_buf[50]; 28 | u8 rx_len; 29 | 30 | void setup(void) 31 | { 32 | Serial.begin(115200); 33 | nfc.begin(); 34 | Serial.println("P2P Target Demo From Elechouse!"); 35 | 36 | uint32_t versiondata = nfc.get_version(); 37 | if (! versiondata) { 38 | Serial.println("Didn't find PN53x board"); 39 | while (1); // halt 40 | } 41 | 42 | // Got ok data, print it out! 43 | Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 44 | Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 45 | Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC); 46 | 47 | /** Set normal mode, and disable SAM */ 48 | nfc.SAMConfiguration(); 49 | } 50 | 51 | void loop(void) 52 | { 53 | /** device is configured as Target */ 54 | if(nfc.P2PTargetInit()){ 55 | /** 56 | send data with a length parameter and receive some data, 57 | tx_buf --- data send buffer 58 | tx_len --- data send legth 59 | rx_buf --- data recieve buffer, return by P2PTargetTxRx 60 | rx_len --- data receive length, return by P2PTargetTxRx 61 | */ 62 | Serial.println("Initiator is sensed."); 63 | tx_len = strlen((const char *)tx_buf); 64 | if(nfc.P2PTargetTxRx(tx_buf, tx_len, rx_buf, &rx_len)){ 65 | Serial.print("Data Received: "); 66 | Serial.write(rx_buf, rx_len); 67 | Serial.println(); 68 | } 69 | Serial.println(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /nfc.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /*! 3 | @file nfc.h 4 | @author www.elechouse.com 5 | @brief NFC Module I2C library source file. 6 | This is a library for the Elechoues NFC_Module 7 | ----> LINKS HERE!!! 8 | 9 | NOTE: 10 | IRQ pin is unused. 11 | 12 | @section HISTORY 13 | V1.1 Add fuction about Peer to Peer communication 14 | u8 P2PInitiatorInit(); 15 | u8 P2PTargetInit(); 16 | u8 P2PInitiatorTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 17 | u8 P2PTargetTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 18 | Change wait_ready(void) to wait_ready(u8 ms=NFC_WAIT_TIME); 19 | Attach Wire library with NFC_MODULE, modify I2C buffer length to 64 20 | and change i2c speed to 400KHz 21 | 22 | V1.0 Initial version. 23 | 24 | Copyright (c) 2012 www.elechouse.com All right reserved. 25 | */ 26 | /*****************************************************************************/ 27 | 28 | #include "nfc.h" 29 | 30 | u8 hextab[17]="0123456789ABCDEF"; 31 | u8 ack[6]={ 32 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 33 | }; 34 | u8 nfc_version[6]={ 35 | 0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03 36 | }; 37 | 38 | /** data buffer */ 39 | u8 nfc_buf[NFC_CMD_BUF_LEN]; 40 | 41 | /*****************************************************************************/ 42 | /*! 43 | @brief 44 | @param 45 | */ 46 | /*****************************************************************************/ 47 | NFC_Module::NFC_Module(void) 48 | { 49 | 50 | } 51 | 52 | /*****************************************************************************/ 53 | /*! 54 | @brief initial function. 55 | @param NONE. 56 | @return NONE. 57 | */ 58 | /*****************************************************************************/ 59 | void NFC_Module::begin(void) 60 | { 61 | #ifdef PN532DEBUG 62 | u8 i; 63 | #endif 64 | Wire.begin(); 65 | #ifdef PN532DEBUG 66 | for(i=0; i<16; i++){ 67 | Serial.write((u8)hextab[i]); 68 | } 69 | for(i=0; i<6; i++){ 70 | Serial.write((u8)ack[i]); 71 | } 72 | for(i=0; i<6; i++){ 73 | Serial.write((u8)nfc_version[i]); 74 | } 75 | #endif 76 | } 77 | 78 | /*****************************************************************************/ 79 | /*! 80 | @brief Get version of PN532 81 | @param NONE 82 | @return version number. 83 | */ 84 | /*****************************************************************************/ 85 | u32 NFC_Module::get_version(void) 86 | { 87 | u32 version; 88 | 89 | nfc_buf[0] = PN532_COMMAND_GETFIRMWAREVERSION; 90 | if(!write_cmd_check_ack(nfc_buf, 1)){ 91 | return 0; 92 | } 93 | wait_ready(); 94 | read_dt(nfc_buf, 12); 95 | if(nfc_buf[5] != 0xD5){ 96 | return 0; 97 | } 98 | // check some basic stuff 99 | if (0 != strncmp((char *)nfc_buf, (char *)nfc_version, 6)) { 100 | #ifdef PN532DEBUG 101 | Serial.println("Firmware doesn't match!"); 102 | #endif 103 | return 0; 104 | } 105 | 106 | version = nfc_buf[7]; 107 | version <<= 8; 108 | version |= nfc_buf[8]; 109 | version <<= 8; 110 | version |= nfc_buf[9]; 111 | version <<= 8; 112 | version |= nfc_buf[10]; 113 | 114 | return version; 115 | } 116 | 117 | /*****************************************************************************/ 118 | /*! 119 | @brief Configures the SAM (Secure Access Module) 120 | @param mode - set mode, normal mode default 121 | @param timeout - Details in NXP's PN532UM.pdf 122 | @param irq - 0 unused (default), 1 used 123 | @return 0 - failed 124 | 1 - successfully 125 | */ 126 | /*****************************************************************************/ 127 | u8 NFC_Module::SAMConfiguration(u8 mode, u8 timeout, u8 irq) 128 | { 129 | #ifdef PN532DEBUG 130 | Serial.print("SAMConfiguration\n"); 131 | #endif 132 | nfc_buf[0] = PN532_COMMAND_SAMCONFIGURATION; 133 | nfc_buf[1] = mode; // normal mode; 134 | nfc_buf[2] = timeout; // timeout 50ms * 20 = 1 second 135 | nfc_buf[3] = irq; // use IRQ pin! 136 | 137 | if(!write_cmd_check_ack(nfc_buf, 4)){ 138 | return 0; 139 | } 140 | 141 | // read data packet 142 | read_dt(nfc_buf, 8); 143 | 144 | return (nfc_buf[6] == PN532_COMMAND_SAMCONFIGURATION); 145 | } 146 | 147 | /*****************************************************************************/ 148 | /*! 149 | @brief card inventory. 150 | @param buf - buf[0] UUID length; buf[1], buf[2], buf[3] buf[4] UUID 151 | @param brty - optional parameter, braud rate: PN532_BRTY_ISO14443A, 152 | PN532_BRTY_ISO14443B, 153 | PN532_BRTY_212KBPS, 154 | PN532_BRTY_424KBPS, 155 | PN532_BRTY_JEWEL, 156 | @param maxtg - optional parameter, maximum tag numbers to read once, 157 | maximum 2, recommend 1. 158 | @param idata - assistant parameter, unused. 159 | @return 0 - failed 160 | 1 - successfully 161 | */ 162 | /*****************************************************************************/ 163 | u8 NFC_Module::InListPassiveTarget(u8 *buf, u8 brty, 164 | u8 len, u8 *idata, u8 maxtg) 165 | { 166 | nfc_buf[0] = PN532_COMMAND_INLISTPASSIVETARGET; 167 | nfc_buf[1] = maxtg; 168 | nfc_buf[2] = brty; 169 | if(len){ 170 | memcpy(nfc_buf+3, idata, len); 171 | } 172 | if(!write_cmd_check_ack(nfc_buf, 3+len)){ 173 | return 0; 174 | } 175 | #ifdef PN532DEBUG 176 | puthex(nfc_buf, 3+len); 177 | Serial.println(); 178 | #endif 179 | // puthex(nfc_buf, 3+len); 180 | // Serial.println(); 181 | 182 | /** "Waiting for IRQ (indicates card presence)" */ 183 | wait_ready(); 184 | wait_ready(); 185 | wait_ready(); 186 | #ifdef PN532DEBUG 187 | Serial.print(" Found Card.\n"); 188 | #endif 189 | read_dt(nfc_buf,40); 190 | // puthex(nfc_buf, nfc_buf[3]+6); 191 | // Serial.println(); 192 | if(nfc_buf[NFC_FRAME_ID_INDEX-1] != 0xD5){ 193 | return 0; 194 | } 195 | 196 | puthex(nfc_buf, nfc_buf[3]+6); 197 | Serial.println(); 198 | 199 | if(nfc_buf[NFC_FRAME_ID_INDEX] != (PN532_COMMAND_INLISTPASSIVETARGET+1)){ 200 | return 0; 201 | } 202 | // if(nfc_buf[NFC_FRAME_ID_INDEX+1]!=1){ 203 | //#ifdef PN532DEBUG 204 | // Serial.println(nfc_buf[NFC_FRAME_ID_INDEX+1],DEC); 205 | //#endif 206 | // return 0; 207 | // } 208 | if(brty == PN532_BRTY_ISO14443A){ 209 | /** UUID length */ 210 | buf[0] = nfc_buf[12]; 211 | 212 | for(u8 i=1; i<5; i++){ 213 | buf[i] = nfc_buf[12+i]; 214 | } 215 | }else{ 216 | buf[0] = nfc_buf[3]; 217 | memcpy(buf, nfc_buf+5, nfc_buf[3]); 218 | } 219 | 220 | return 1; 221 | } 222 | 223 | u8 NFC_Module::FelicaPoll(u8 *buf, u8 len, u8 *idata) 224 | { 225 | static u8 sta=0; 226 | if(!sta){ 227 | nfc_buf[0] = PN532_COMMAND_INLISTPASSIVETARGET; 228 | nfc_buf[1] = 0x02; 229 | nfc_buf[2] = 0x02; 230 | if(len){ 231 | memcpy(nfc_buf+3, idata, len); 232 | } 233 | if(!write_cmd_check_ack(nfc_buf, 3+len)){ 234 | return 0; 235 | } 236 | #ifdef PN532DEBUG 237 | puthex(nfc_buf, 3+len); 238 | Serial.println(); 239 | #endif 240 | // puthex(nfc_buf, 3+len); 241 | Serial.println("Send command"); 242 | } 243 | sta = 1; 244 | /** "Waiting for IRQ (indicates card presence)" */ 245 | wait_ready(); 246 | wait_ready(); 247 | wait_ready(); 248 | #ifdef PN532DEBUG 249 | Serial.print(" Found Card.\n"); 250 | #endif 251 | read_dt(nfc_buf,40); 252 | puthex(nfc_buf, nfc_buf[3]+6); 253 | Serial.println(); 254 | if(nfc_buf[NFC_FRAME_ID_INDEX-1] != 0xD5){ 255 | return 0; 256 | } 257 | sta = 0; 258 | puthex(nfc_buf, nfc_buf[3]+6); 259 | Serial.println(); 260 | 261 | if(nfc_buf[NFC_FRAME_ID_INDEX] != (PN532_COMMAND_INLISTPASSIVETARGET+1)){ 262 | return 0; 263 | } 264 | // if(nfc_buf[NFC_FRAME_ID_INDEX+1]!=1){ 265 | //#ifdef PN532DEBUG 266 | // Serial.println(nfc_buf[NFC_FRAME_ID_INDEX+1],DEC); 267 | //#endif 268 | // return 0; 269 | // } 270 | buf[0] = nfc_buf[3]; 271 | memcpy(buf, nfc_buf+5, nfc_buf[3]); 272 | 273 | 274 | return 1; 275 | } 276 | 277 | /*****************************************************************************/ 278 | /*! 279 | @brief Mifare funciton. Authentication a block for more operation. 280 | @param type - key type. 0-KEYA, 1-KEYB 281 | @param block - block to Authentication 282 | @param uuid - pointer to selected card's UUID 283 | @param uuid_len - UUID length 284 | @param key - pointer to key buffer. 285 | @return 0 - failed 286 | 1 - successfully 287 | */ 288 | /*****************************************************************************/ 289 | u8 NFC_Module::MifareAuthentication(u8 type, u8 block, 290 | u8 *uuid, u8 uuid_len, u8 *key) 291 | { 292 | u8 i; 293 | nfc_buf[0] = PN532_COMMAND_INDATAEXCHANGE; 294 | nfc_buf[1] = 1; // logical number of the relevant target 295 | nfc_buf[2] = MIFARE_CMD_AUTH_A+type; 296 | nfc_buf[3] = block; 297 | 298 | for(i=0; i<6; i++){ 299 | nfc_buf[4+i] = key[i]; 300 | } 301 | for(i=0; i 10){ 803 | Serial.println("*************Reinit Target************"); 804 | /** Target release */ 805 | TgInitAsTarget(); 806 | Serial.println("*************Reinit Target************"); 807 | sta = NFC_STA_TAG; 808 | } 809 | break; 810 | case NFC_STA_SETDATA: 811 | break; 812 | } 813 | if(nfc_buf[5] == 0xD5){ 814 | puthex(nfc_buf, nfc_buf[3]+6); 815 | switch(nfc_buf[NFC_FRAME_ID_INDEX]){ 816 | case PN532_COMMAND_TGINITASTARGET+1: 817 | Serial.println("TgInitTatget"); 818 | nfc_buf[0] = PN532_COMMAND_TGGETDATA; 819 | sta = NFC_STA_GETDATA; 820 | count=0; 821 | if(!write_cmd_check_ack(nfc_buf, 1)){ 822 | return 0; 823 | } 824 | break; 825 | case PN532_COMMAND_TGRESPONSETOINITIATOR+1: 826 | Serial.println("TgResponseToInitiator"); 827 | break; 828 | case PN532_COMMAND_TGGETINITIATORCOMMAND+1: 829 | Serial.println("TgGetInitiatorCommand"); 830 | break; 831 | case PN532_COMMAND_TGGETDATA+1: 832 | Serial.println("TgGetData"); 833 | if(!nfc_buf[NFC_FRAME_ID_INDEX+1]){ 834 | Serial.println("TgGetData Success."); 835 | switch(nfc_buf[NFC_FRAME_ID_INDEX+2]){ 836 | case 0x60: 837 | nfc_buf[0] = PN532_COMMAND_TGSETDATA; 838 | nfc_buf[1] = 0x00; 839 | nfc_buf[2] = 0xFF; 840 | if(!write_cmd_check_ack(nfc_buf, 3)){ 841 | return 0; 842 | } 843 | break; 844 | case 0x30: 845 | nfc_buf[0] = PN532_COMMAND_TGSETDATA; 846 | for(u8 i=1; i<17; i++){ 847 | nfc_buf[i] = i; 848 | } 849 | if(!write_cmd_check_ack(nfc_buf, 17)){ 850 | return 0; 851 | } 852 | break; 853 | default: 854 | Serial.println("TgGetData Error."); 855 | wait_ready(); 856 | /** Target release */ 857 | TgInitAsTarget(); 858 | break; 859 | } 860 | 861 | }else{ 862 | /** Target release */ 863 | TgInitAsTarget(); 864 | } 865 | break; 866 | case PN532_COMMAND_TGSETDATA+1: 867 | Serial.println("TgSetData"); 868 | if(!nfc_buf[NFC_FRAME_ID_INDEX+1]){ 869 | Serial.println("TgSetData Success."); 870 | nfc_buf[0] = PN532_COMMAND_TGGETDATA; 871 | sta = NFC_STA_GETDATA; 872 | count=0; 873 | if(!write_cmd_check_ack(nfc_buf, 1)){ 874 | /** */ 875 | Serial.println("SetData check error."); 876 | return 0; 877 | } 878 | } 879 | break; 880 | default: 881 | Serial.println("Undifined command"); 882 | break; 883 | } 884 | }else{ 885 | Serial.println("."); 886 | } 887 | return 1; 888 | } 889 | 890 | /*****************************************************************************/ 891 | /*! 892 | @brief PN532 SetParameters command. Details in NXP's PN532UM.pdf 893 | @param para - parameter to set 894 | @return 0 - send failed 895 | 1 - send successfully 896 | */ 897 | /*****************************************************************************/ 898 | u8 NFC_Module::SetParameters(u8 para) 899 | { 900 | nfc_buf[0] = PN532_COMMAND_SETPARAMETERS; 901 | nfc_buf[1] = para; 902 | 903 | if(!write_cmd_check_ack(nfc_buf, 2)){ 904 | return 0; 905 | } 906 | read_dt(nfc_buf, 8); 907 | if(nfc_buf[NFC_FRAME_ID_INDEX] != (PN532_COMMAND_SETPARAMETERS+1)){ 908 | return 0; 909 | } 910 | return 1; 911 | } 912 | 913 | /*****************************************************************************/ 914 | /*! 915 | @brief send frame to PN532 and wait for ack 916 | @param cmd - pointer to frame buffer 917 | @param len - frame length 918 | @return 0 - send failed 919 | 1 - send successfully 920 | */ 921 | /*****************************************************************************/ 922 | u8 NFC_Module::write_cmd_check_ack(u8 *cmd, u8 len) 923 | { 924 | write_cmd(cmd, len); 925 | wait_ready(); 926 | #ifdef PN532DEBUG 927 | Serial.println("IRQ received"); 928 | #endif 929 | 930 | // read acknowledgement 931 | if (!read_ack()) { 932 | #ifdef PN532DEBUG 933 | Serial.println("No ACK frame received!"); 934 | #endif 935 | return false; 936 | } 937 | 938 | return true; // ack'd command 939 | } 940 | 941 | /*****************************************************************************/ 942 | /*! 943 | @brief send a byte data via I2C interface 944 | @param data - The byte to send. 945 | @return 0 - send failed 946 | 1 - successful 947 | */ 948 | /*****************************************************************************/ 949 | inline u8 NFC_Module::send(u8 data) 950 | { 951 | #if ARDUINO >= 100 952 | return Wire.write((u8)data); 953 | #else 954 | return Wire.send((u8)data); 955 | #endif 956 | } 957 | 958 | /*****************************************************************************/ 959 | /*! 960 | @brief receive a byte from I2C interface 961 | @param NONE 962 | @return received data 963 | */ 964 | /*****************************************************************************/ 965 | inline u8 NFC_Module::receive(void) 966 | { 967 | #if ARDUINO >= 100 968 | return Wire.read(); 969 | #else 970 | return Wire.receive(); 971 | #endif 972 | } 973 | 974 | /*****************************************************************************/ 975 | /*! 976 | @brief Send a byte by hex format 977 | @param data - the byte 978 | @return NONE 979 | */ 980 | /*****************************************************************************/ 981 | void NFC_Module::puthex(u8 data) 982 | { 983 | Serial.write(hextab[(data>>4)&0x0F]); 984 | Serial.write(hextab[data&0x0F]); 985 | Serial.write(' '); 986 | } 987 | 988 | /*****************************************************************************/ 989 | /*! 990 | @brief Send hexadecimal data through Serial with specified length. 991 | @param buf - pointer of data buffer. 992 | @param len - length need to send. 993 | @return NONE 994 | */ 995 | /*****************************************************************************/ 996 | void NFC_Module::puthex(u8 *buf, u32 len) 997 | { 998 | u32 i; 999 | for(i=0; i>4)&0x0F]); 1002 | Serial.write(hextab[buf[i]&0x0F]); 1003 | Serial.write(' '); 1004 | } 1005 | } 1006 | 1007 | /*****************************************************************************/ 1008 | /*! 1009 | @brief Write data frame to PN532. 1010 | @param cmd - Pointer of the data frame. 1011 | @param len - length need to write 1012 | @return NONE 1013 | */ 1014 | /*****************************************************************************/ 1015 | void NFC_Module::write_cmd(u8 *cmd, u8 len) 1016 | { 1017 | uint8_t checksum; 1018 | 1019 | len++; 1020 | 1021 | #ifdef PN532DEBUG 1022 | Serial.print("Sending: "); 1023 | #endif 1024 | 1025 | delay(2); // or whatever the delay is for waking up the board 1026 | 1027 | // I2C START 1028 | Wire.beginTransmission(PN532_I2C_ADDRESS); 1029 | checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2; 1030 | send(PN532_PREAMBLE); 1031 | send(PN532_PREAMBLE); 1032 | send(PN532_STARTCODE2); 1033 | 1034 | send(len); 1035 | send(~len + 1); 1036 | 1037 | send(PN532_HOSTTOPN532); 1038 | checksum += PN532_HOSTTOPN532; 1039 | 1040 | #ifdef PN532DEBUG 1041 | puthex(PN532_PREAMBLE); 1042 | puthex(PN532_PREAMBLE); 1043 | puthex(PN532_STARTCODE2); 1044 | puthex((unsigned char)len); 1045 | puthex((unsigned char)(~len + 1)); 1046 | puthex(PN532_HOSTTOPN532); 1047 | #endif 1048 | 1049 | for (uint8_t i=0; i LINKS HERE!!! 8 | 9 | NOTE: 10 | 1. IRQ pin is unused. 11 | 2. Referenced Adafruit_NFCShield_I2C library 12 | @section HISTORY 13 | V1.1 Add fuction about Peer to Peer communication 14 | u8 P2PInitiatorInit(); 15 | u8 P2PTargetInit(); 16 | u8 P2PInitiatorTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 17 | u8 P2PTargetTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 18 | 19 | Change wait_ready(void) to wait_ready(u8 ms=NFC_WAIT_TIME); 20 | 21 | V1.0 Initial version. 22 | 23 | Copyright (c) 2012 www.elechouse.com All right reserved. 24 | */ 25 | /*****************************************************************************/ 26 | 27 | #ifndef __NFC_H 28 | #define __NFC_H 29 | 30 | #if ARDUINO >= 100 31 | #include "Arduino.h" 32 | #else 33 | #include "WProgram.h" 34 | #endif 35 | #include 36 | #include 37 | 38 | #ifndef __TYPE_REDEFINE 39 | #define __TYPE_REDEFINE 40 | typedef uint8_t u8; 41 | typedef int8_t s8; 42 | typedef uint16_t u16; 43 | typedef int16_t s16; 44 | typedef uint32_t u32; 45 | typedef int32_t s32; 46 | #endif 47 | 48 | 49 | #define PN532_PREAMBLE (0x00) 50 | #define PN532_STARTCODE1 (0x00) 51 | #define PN532_STARTCODE2 (0xFF) 52 | #define PN532_POSTAMBLE (0x00) 53 | 54 | #define PN532_HOSTTOPN532 (0xD4) 55 | 56 | // PN532 Commands 57 | #define PN532_COMMAND_DIAGNOSE (0x00) 58 | #define PN532_COMMAND_GETFIRMWAREVERSION (0x02) 59 | #define PN532_COMMAND_GETGENERALSTATUS (0x04) 60 | #define PN532_COMMAND_READREGISTER (0x06) 61 | #define PN532_COMMAND_WRITEREGISTER (0x08) 62 | #define PN532_COMMAND_READGPIO (0x0C) 63 | #define PN532_COMMAND_WRITEGPIO (0x0E) 64 | #define PN532_COMMAND_SETSERIALBAUDRATE (0x10) 65 | #define PN532_COMMAND_SETPARAMETERS (0x12) 66 | #define PN532_COMMAND_SAMCONFIGURATION (0x14) 67 | #define PN532_COMMAND_POWERDOWN (0x16) 68 | #define PN532_COMMAND_RFCONFIGURATION (0x32) 69 | #define PN532_COMMAND_RFREGULATIONTEST (0x58) 70 | #define PN532_COMMAND_INJUMPFORDEP (0x56) 71 | #define PN532_COMMAND_INJUMPFORPSL (0x46) 72 | #define PN532_COMMAND_INLISTPASSIVETARGET (0x4A) 73 | #define PN532_COMMAND_INATR (0x50) 74 | #define PN532_COMMAND_INPSL (0x4E) 75 | #define PN532_COMMAND_INDATAEXCHANGE (0x40) 76 | #define PN532_COMMAND_INCOMMUNICATETHRU (0x42) 77 | #define PN532_COMMAND_INDESELECT (0x44) 78 | #define PN532_COMMAND_INRELEASE (0x52) 79 | #define PN532_COMMAND_INSELECT (0x54) 80 | #define PN532_COMMAND_INAUTOPOLL (0x60) 81 | #define PN532_COMMAND_TGINITASTARGET (0x8C) 82 | #define PN532_COMMAND_TGSETGENERALBYTES (0x92) 83 | #define PN532_COMMAND_TGGETDATA (0x86) 84 | #define PN532_COMMAND_TGSETDATA (0x8E) 85 | #define PN532_COMMAND_TGSETMETADATA (0x94) 86 | #define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88) 87 | #define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90) 88 | #define PN532_COMMAND_TGGETTARGETSTATUS (0x8A) 89 | 90 | #define PN532_WAKEUP (0x55) 91 | 92 | #define PN532_SPI_STATREAD (0x02) 93 | #define PN532_SPI_DATAWRITE (0x01) 94 | #define PN532_SPI_DATAREAD (0x03) 95 | #define PN532_SPI_READY (0x01) 96 | 97 | #define PN532_I2C_ADDRESS (0x48 >> 1) 98 | #define PN532_I2C_READBIT (0x01) 99 | #define PN532_I2C_BUSY (0x00) 100 | #define PN532_I2C_READY (0x01) 101 | #define PN532_I2C_READYTIMEOUT (20) 102 | 103 | #define PN532_MIFARE_ISO14443A (0x00) 104 | 105 | // Mifare Commands 106 | #define MIFARE_CMD_AUTH_A (0x60) 107 | #define MIFARE_CMD_AUTH_B (0x61) 108 | #define MIFARE_CMD_READ (0x30) 109 | #define MIFARE_CMD_WRITE (0xA0) 110 | #define MIFARE_CMD_TRANSFER (0xB0) 111 | #define MIFARE_CMD_DECREMENT (0xC0) 112 | #define MIFARE_CMD_INCREMENT (0xC1) 113 | #define MIFARE_CMD_RESTORE (0xC2) 114 | 115 | // Prefixes for NDEF Records (to identify record type) 116 | #define NDEF_URIPREFIX_NONE (0x00) 117 | #define NDEF_URIPREFIX_HTTP_WWWDOT (0x01) 118 | #define NDEF_URIPREFIX_HTTPS_WWWDOT (0x02) 119 | #define NDEF_URIPREFIX_HTTP (0x03) 120 | #define NDEF_URIPREFIX_HTTPS (0x04) 121 | #define NDEF_URIPREFIX_TEL (0x05) 122 | #define NDEF_URIPREFIX_MAILTO (0x06) 123 | #define NDEF_URIPREFIX_FTP_ANONAT (0x07) 124 | #define NDEF_URIPREFIX_FTP_FTPDOT (0x08) 125 | #define NDEF_URIPREFIX_FTPS (0x09) 126 | #define NDEF_URIPREFIX_SFTP (0x0A) 127 | #define NDEF_URIPREFIX_SMB (0x0B) 128 | #define NDEF_URIPREFIX_NFS (0x0C) 129 | #define NDEF_URIPREFIX_FTP (0x0D) 130 | #define NDEF_URIPREFIX_DAV (0x0E) 131 | #define NDEF_URIPREFIX_NEWS (0x0F) 132 | #define NDEF_URIPREFIX_TELNET (0x10) 133 | #define NDEF_URIPREFIX_IMAP (0x11) 134 | #define NDEF_URIPREFIX_RTSP (0x12) 135 | #define NDEF_URIPREFIX_URN (0x13) 136 | #define NDEF_URIPREFIX_POP (0x14) 137 | #define NDEF_URIPREFIX_SIP (0x15) 138 | #define NDEF_URIPREFIX_SIPS (0x16) 139 | #define NDEF_URIPREFIX_TFTP (0x17) 140 | #define NDEF_URIPREFIX_BTSPP (0x18) 141 | #define NDEF_URIPREFIX_BTL2CAP (0x19) 142 | #define NDEF_URIPREFIX_BTGOEP (0x1A) 143 | #define NDEF_URIPREFIX_TCPOBEX (0x1B) 144 | #define NDEF_URIPREFIX_IRDAOBEX (0x1C) 145 | #define NDEF_URIPREFIX_FILE (0x1D) 146 | #define NDEF_URIPREFIX_URN_EPC_ID (0x1E) 147 | #define NDEF_URIPREFIX_URN_EPC_TAG (0x1F) 148 | #define NDEF_URIPREFIX_URN_EPC_PAT (0x20) 149 | #define NDEF_URIPREFIX_URN_EPC_RAW (0x21) 150 | #define NDEF_URIPREFIX_URN_EPC (0x22) 151 | #define NDEF_URIPREFIX_URN_NFC (0x23) 152 | 153 | #define PN532_GPIO_VALIDATIONBIT (0x80) 154 | #define PN532_GPIO_P30 (0) 155 | #define PN532_GPIO_P31 (1) 156 | #define PN532_GPIO_P32 (2) 157 | #define PN532_GPIO_P33 (3) 158 | #define PN532_GPIO_P34 (4) 159 | #define PN532_GPIO_P35 (5) 160 | 161 | #define PN532_SAM_NORMAL_MODE (0x01) 162 | #define PN532_SAM_VIRTUAL_CARD (0x02) 163 | #define PN532_SAM_WIRED_CARD (0x03) 164 | #define PN532_SAM_DUAL_CARD (0x04) 165 | 166 | #define PN532_BRTY_ISO14443A 0x00 167 | #define PN532_BRTY_ISO14443B 0x03 168 | #define PN532_BRTY_212KBPS 0x01 169 | #define PN532_BRTY_424KBPS 0x02 170 | #define PN532_BRTY_JEWEL 0x04 171 | 172 | //#define PN532DEBUG 173 | //#define PN532_P2P_DEBUG 174 | #define NFC_WAIT_TIME 30 175 | #define NFC_CMD_BUF_LEN 64 176 | #define NFC_FRAME_ID_INDEX 6 177 | 178 | typedef enum{ 179 | NFC_STA_TAG, 180 | NFC_STA_GETDATA, 181 | NFC_STA_SETDATA, 182 | }poll_sta_type; 183 | 184 | class NFC_Module{ 185 | public: 186 | NFC_Module(); 187 | void begin(void); 188 | u32 get_version(void); 189 | u8 SAMConfiguration(u8 mode=PN532_SAM_NORMAL_MODE, u8 timeout=20, u8 irq=0); 190 | 191 | u8 InListPassiveTarget(u8 *buf, u8 brty=PN532_BRTY_ISO14443A, 192 | u8 len=0, u8 *idata=NULL, u8 maxtg=1); 193 | u8 InDataExchange(u8 mode, u8 tg, u8 *buf=NULL, u8 len=0); 194 | u8 MifareAuthentication(u8 type, u8 block, u8 *uuid, u8 uuid_len, u8 *key); 195 | u8 MifareReadBlock(u8 block, u8 *buf); 196 | u8 MifareWriteBlock(u8 block, u8 *buf); 197 | 198 | u8 P2PInitiatorInit(); 199 | u8 P2PTargetInit(); 200 | u8 P2PInitiatorTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 201 | u8 P2PTargetTxRx(u8 *t_buf, u8 t_len, u8 *r_buf, u8 *r_len); 202 | 203 | u8 TgInitAsTarget(); 204 | u8 TargetPolling(); 205 | u8 SetParameters(u8 para); 206 | 207 | u8 FelicaPoll(u8 *buf, u8 len, u8 *idata); 208 | 209 | void puthex(u8 *buf, u32 len); 210 | void puthex(u8 data); 211 | private: 212 | 213 | inline u8 send(u8 data); 214 | inline u8 receive(); 215 | 216 | void write_cmd(u8 *cmd, u8 len); 217 | u8 write_cmd_check_ack(u8 *cmd, u8 len); 218 | void read_dt(u8 *buf, u8 len); 219 | u8 read_sta(void); 220 | u8 wait_ready(u8 ms=NFC_WAIT_TIME); 221 | u8 read_ack(void); 222 | }; 223 | 224 | #endif /** __NFC_H */ 225 | -------------------------------------------------------------------------------- /utility/twi.c: -------------------------------------------------------------------------------- 1 | /* 2 | twi.c - TWI/I2C library for Wiring & Arduino 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "Arduino.h" // for digitalWrite 27 | 28 | #ifndef cbi 29 | #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 30 | #endif 31 | 32 | #ifndef sbi 33 | #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 34 | #endif 35 | 36 | #include "pins_arduino.h" 37 | #include "twi.h" 38 | 39 | static volatile uint8_t twi_state; 40 | static uint8_t twi_slarw; 41 | 42 | static void (*twi_onSlaveTransmit)(void); 43 | static void (*twi_onSlaveReceive)(uint8_t*, int); 44 | 45 | static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; 46 | static volatile uint8_t twi_masterBufferIndex; 47 | static uint8_t twi_masterBufferLength; 48 | 49 | static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; 50 | static volatile uint8_t twi_txBufferIndex; 51 | static volatile uint8_t twi_txBufferLength; 52 | 53 | static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; 54 | static volatile uint8_t twi_rxBufferIndex; 55 | 56 | static volatile uint8_t twi_error; 57 | 58 | /* 59 | * Function twi_init 60 | * Desc readys twi pins and sets twi bitrate 61 | * Input none 62 | * Output none 63 | */ 64 | void twi_init(void) 65 | { 66 | // initialize state 67 | twi_state = TWI_READY; 68 | 69 | // activate internal pullups for twi. 70 | digitalWrite(SDA, 1); 71 | digitalWrite(SCL, 1); 72 | 73 | // initialize twi prescaler and bit rate 74 | cbi(TWSR, TWPS0); 75 | cbi(TWSR, TWPS1); 76 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; 77 | 78 | /* twi bit rate formula from atmega128 manual pg 204 79 | SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) 80 | note: TWBR should be 10 or higher for master mode 81 | It is 72 for a 16mhz Wiring board with 100kHz TWI */ 82 | 83 | // enable twi module, acks, and twi interrupt 84 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); 85 | } 86 | 87 | /* 88 | * Function twi_slaveInit 89 | * Desc sets slave address and enables interrupt 90 | * Input none 91 | * Output none 92 | */ 93 | void twi_setAddress(uint8_t address) 94 | { 95 | // set twi slave address (skip over TWGCE bit) 96 | TWAR = address << 1; 97 | } 98 | 99 | /* 100 | * Function twi_readFrom 101 | * Desc attempts to become twi bus master and read a 102 | * series of bytes from a device on the bus 103 | * Input address: 7bit i2c device address 104 | * data: pointer to byte array 105 | * length: number of bytes to read into array 106 | * Output number of bytes read 107 | */ 108 | uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) 109 | { 110 | uint8_t i; 111 | 112 | // ensure data will fit into buffer 113 | if(TWI_BUFFER_LENGTH < length){ 114 | return 0; 115 | } 116 | 117 | // wait until twi is ready, become master receiver 118 | while(TWI_READY != twi_state){ 119 | continue; 120 | } 121 | twi_state = TWI_MRX; 122 | // reset error state (0xFF.. no error occured) 123 | twi_error = 0xFF; 124 | 125 | // initialize buffer iteration vars 126 | twi_masterBufferIndex = 0; 127 | twi_masterBufferLength = length-1; // This is not intuitive, read on... 128 | // On receive, the previously configured ACK/NACK setting is transmitted in 129 | // response to the received byte before the interrupt is signalled. 130 | // Therefor we must actually set NACK when the _next_ to last byte is 131 | // received, causing that NACK to be sent in response to receiving the last 132 | // expected byte of data. 133 | 134 | // build sla+w, slave device address + w bit 135 | twi_slarw = TW_READ; 136 | twi_slarw |= address << 1; 137 | 138 | // send start condition 139 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); 140 | 141 | // wait for read operation to complete 142 | while(TWI_MRX == twi_state){ 143 | continue; 144 | } 145 | 146 | if (twi_masterBufferIndex < length) 147 | length = twi_masterBufferIndex; 148 | 149 | // copy twi buffer to data 150 | for(i = 0; i < length; ++i){ 151 | data[i] = twi_masterBuffer[i]; 152 | } 153 | 154 | return length; 155 | } 156 | 157 | /* 158 | * Function twi_writeTo 159 | * Desc attempts to become twi bus master and write a 160 | * series of bytes to a device on the bus 161 | * Input address: 7bit i2c device address 162 | * data: pointer to byte array 163 | * length: number of bytes in array 164 | * wait: boolean indicating to wait for write or not 165 | * Output 0 .. success 166 | * 1 .. length to long for buffer 167 | * 2 .. address send, NACK received 168 | * 3 .. data send, NACK received 169 | * 4 .. other twi error (lost bus arbitration, bus error, ..) 170 | */ 171 | uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) 172 | { 173 | uint8_t i; 174 | 175 | // ensure data will fit into buffer 176 | if(TWI_BUFFER_LENGTH < length){ 177 | return 1; 178 | } 179 | 180 | // wait until twi is ready, become master transmitter 181 | while(TWI_READY != twi_state){ 182 | continue; 183 | } 184 | twi_state = TWI_MTX; 185 | // reset error state (0xFF.. no error occured) 186 | twi_error = 0xFF; 187 | 188 | // initialize buffer iteration vars 189 | twi_masterBufferIndex = 0; 190 | twi_masterBufferLength = length; 191 | 192 | // copy data to twi buffer 193 | for(i = 0; i < length; ++i){ 194 | twi_masterBuffer[i] = data[i]; 195 | } 196 | 197 | // build sla+w, slave device address + w bit 198 | twi_slarw = TW_WRITE; 199 | twi_slarw |= address << 1; 200 | 201 | // send start condition 202 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); 203 | 204 | // wait for write operation to complete 205 | while(wait && (TWI_MTX == twi_state)){ 206 | continue; 207 | } 208 | 209 | if (twi_error == 0xFF) 210 | return 0; // success 211 | else if (twi_error == TW_MT_SLA_NACK) 212 | return 2; // error: address send, nack received 213 | else if (twi_error == TW_MT_DATA_NACK) 214 | return 3; // error: data send, nack received 215 | else 216 | return 4; // other twi error 217 | } 218 | 219 | /* 220 | * Function twi_transmit 221 | * Desc fills slave tx buffer with data 222 | * must be called in slave tx event callback 223 | * Input data: pointer to byte array 224 | * length: number of bytes in array 225 | * Output 1 length too long for buffer 226 | * 2 not slave transmitter 227 | * 0 ok 228 | */ 229 | uint8_t twi_transmit(const uint8_t* data, uint8_t length) 230 | { 231 | uint8_t i; 232 | 233 | // ensure data will fit into buffer 234 | if(TWI_BUFFER_LENGTH < length){ 235 | return 1; 236 | } 237 | 238 | // ensure we are currently a slave transmitter 239 | if(TWI_STX != twi_state){ 240 | return 2; 241 | } 242 | 243 | // set length and copy data into tx buffer 244 | twi_txBufferLength = length; 245 | for(i = 0; i < length; ++i){ 246 | twi_txBuffer[i] = data[i]; 247 | } 248 | 249 | return 0; 250 | } 251 | 252 | /* 253 | * Function twi_attachSlaveRxEvent 254 | * Desc sets function called before a slave read operation 255 | * Input function: callback function to use 256 | * Output none 257 | */ 258 | void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) 259 | { 260 | twi_onSlaveReceive = function; 261 | } 262 | 263 | /* 264 | * Function twi_attachSlaveTxEvent 265 | * Desc sets function called before a slave write operation 266 | * Input function: callback function to use 267 | * Output none 268 | */ 269 | void twi_attachSlaveTxEvent( void (*function)(void) ) 270 | { 271 | twi_onSlaveTransmit = function; 272 | } 273 | 274 | /* 275 | * Function twi_reply 276 | * Desc sends byte or readys receive line 277 | * Input ack: byte indicating to ack or to nack 278 | * Output none 279 | */ 280 | void twi_reply(uint8_t ack) 281 | { 282 | // transmit master read ready signal, with or without ack 283 | if(ack){ 284 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); 285 | }else{ 286 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); 287 | } 288 | } 289 | 290 | /* 291 | * Function twi_stop 292 | * Desc relinquishes bus master status 293 | * Input none 294 | * Output none 295 | */ 296 | void twi_stop(void) 297 | { 298 | // send stop condition 299 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); 300 | 301 | // wait for stop condition to be exectued on bus 302 | // TWINT is not set after a stop condition! 303 | while(TWCR & _BV(TWSTO)){ 304 | continue; 305 | } 306 | 307 | // update twi state 308 | twi_state = TWI_READY; 309 | } 310 | 311 | /* 312 | * Function twi_releaseBus 313 | * Desc releases bus control 314 | * Input none 315 | * Output none 316 | */ 317 | void twi_releaseBus(void) 318 | { 319 | // release bus 320 | TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); 321 | 322 | // update twi state 323 | twi_state = TWI_READY; 324 | } 325 | 326 | SIGNAL(TWI_vect) 327 | { 328 | switch(TW_STATUS){ 329 | // All Master 330 | case TW_START: // sent start condition 331 | case TW_REP_START: // sent repeated start condition 332 | // copy device address and r/w bit to output register and ack 333 | TWDR = twi_slarw; 334 | twi_reply(1); 335 | break; 336 | 337 | // Master Transmitter 338 | case TW_MT_SLA_ACK: // slave receiver acked address 339 | case TW_MT_DATA_ACK: // slave receiver acked data 340 | // if there is data to send, send it, otherwise stop 341 | if(twi_masterBufferIndex < twi_masterBufferLength){ 342 | // copy data to output register and ack 343 | TWDR = twi_masterBuffer[twi_masterBufferIndex++]; 344 | twi_reply(1); 345 | }else{ 346 | twi_stop(); 347 | } 348 | break; 349 | case TW_MT_SLA_NACK: // address sent, nack received 350 | twi_error = TW_MT_SLA_NACK; 351 | twi_stop(); 352 | break; 353 | case TW_MT_DATA_NACK: // data sent, nack received 354 | twi_error = TW_MT_DATA_NACK; 355 | twi_stop(); 356 | break; 357 | case TW_MT_ARB_LOST: // lost bus arbitration 358 | twi_error = TW_MT_ARB_LOST; 359 | twi_releaseBus(); 360 | break; 361 | 362 | // Master Receiver 363 | case TW_MR_DATA_ACK: // data received, ack sent 364 | // put byte into buffer 365 | twi_masterBuffer[twi_masterBufferIndex++] = TWDR; 366 | case TW_MR_SLA_ACK: // address sent, ack received 367 | // ack if more bytes are expected, otherwise nack 368 | if(twi_masterBufferIndex < twi_masterBufferLength){ 369 | twi_reply(1); 370 | }else{ 371 | twi_reply(0); 372 | } 373 | break; 374 | case TW_MR_DATA_NACK: // data received, nack sent 375 | // put final byte into buffer 376 | twi_masterBuffer[twi_masterBufferIndex++] = TWDR; 377 | case TW_MR_SLA_NACK: // address sent, nack received 378 | twi_stop(); 379 | break; 380 | // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case 381 | 382 | // Slave Receiver 383 | case TW_SR_SLA_ACK: // addressed, returned ack 384 | case TW_SR_GCALL_ACK: // addressed generally, returned ack 385 | case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack 386 | case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack 387 | // enter slave receiver mode 388 | twi_state = TWI_SRX; 389 | // indicate that rx buffer can be overwritten and ack 390 | twi_rxBufferIndex = 0; 391 | twi_reply(1); 392 | break; 393 | case TW_SR_DATA_ACK: // data received, returned ack 394 | case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack 395 | // if there is still room in the rx buffer 396 | if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ 397 | // put byte in buffer and ack 398 | twi_rxBuffer[twi_rxBufferIndex++] = TWDR; 399 | twi_reply(1); 400 | }else{ 401 | // otherwise nack 402 | twi_reply(0); 403 | } 404 | break; 405 | case TW_SR_STOP: // stop or repeated start condition received 406 | // put a null char after data if there's room 407 | if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ 408 | twi_rxBuffer[twi_rxBufferIndex] = '\0'; 409 | } 410 | // sends ack and stops interface for clock stretching 411 | twi_stop(); 412 | // callback to user defined callback 413 | twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); 414 | // since we submit rx buffer to "wire" library, we can reset it 415 | twi_rxBufferIndex = 0; 416 | // ack future responses and leave slave receiver state 417 | twi_releaseBus(); 418 | break; 419 | case TW_SR_DATA_NACK: // data received, returned nack 420 | case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack 421 | // nack back at master 422 | twi_reply(0); 423 | break; 424 | 425 | // Slave Transmitter 426 | case TW_ST_SLA_ACK: // addressed, returned ack 427 | case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack 428 | // enter slave transmitter mode 429 | twi_state = TWI_STX; 430 | // ready the tx buffer index for iteration 431 | twi_txBufferIndex = 0; 432 | // set tx buffer length to be zero, to verify if user changes it 433 | twi_txBufferLength = 0; 434 | // request for txBuffer to be filled and length to be set 435 | // note: user must call twi_transmit(bytes, length) to do this 436 | twi_onSlaveTransmit(); 437 | // if they didn't change buffer & length, initialize it 438 | if(0 == twi_txBufferLength){ 439 | twi_txBufferLength = 1; 440 | twi_txBuffer[0] = 0x00; 441 | } 442 | // transmit first byte from buffer, fall 443 | case TW_ST_DATA_ACK: // byte sent, ack returned 444 | // copy data to output register 445 | TWDR = twi_txBuffer[twi_txBufferIndex++]; 446 | // if there is more to send, ack, otherwise nack 447 | if(twi_txBufferIndex < twi_txBufferLength){ 448 | twi_reply(1); 449 | }else{ 450 | twi_reply(0); 451 | } 452 | break; 453 | case TW_ST_DATA_NACK: // received nack, we are done 454 | case TW_ST_LAST_DATA: // received ack, but we are done already! 455 | // ack future responses 456 | twi_reply(1); 457 | // leave slave receiver state 458 | twi_state = TWI_READY; 459 | break; 460 | 461 | // All 462 | case TW_NO_INFO: // no state information 463 | break; 464 | case TW_BUS_ERROR: // bus error, illegal stop/start 465 | twi_error = TW_BUS_ERROR; 466 | twi_stop(); 467 | break; 468 | } 469 | } 470 | 471 | -------------------------------------------------------------------------------- /utility/twi.h: -------------------------------------------------------------------------------- 1 | /* 2 | twi.h - TWI/I2C library for Wiring & Arduino 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef twi_h 21 | #define twi_h 22 | 23 | #include 24 | 25 | //#define ATMEGA8 26 | 27 | #ifndef TWI_FREQ 28 | #define TWI_FREQ 400000L 29 | #endif 30 | 31 | #ifndef TWI_BUFFER_LENGTH 32 | #define TWI_BUFFER_LENGTH 64 33 | #endif 34 | 35 | #define TWI_READY 0 36 | #define TWI_MRX 1 37 | #define TWI_MTX 2 38 | #define TWI_SRX 3 39 | #define TWI_STX 4 40 | 41 | void twi_init(void); 42 | void twi_setAddress(uint8_t); 43 | uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t); 44 | uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t); 45 | uint8_t twi_transmit(const uint8_t*, uint8_t); 46 | void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); 47 | void twi_attachSlaveTxEvent( void (*)(void) ); 48 | void twi_reply(uint8_t); 49 | void twi_stop(void); 50 | void twi_releaseBus(void); 51 | 52 | #endif 53 | 54 | --------------------------------------------------------------------------------