mirror of
https://github.com/Sucareto/ESP32-CardReader.git
synced 2024-11-27 17:00:57 +01:00
复制库,删除未使用函数:
https://github.com/elechouse/PN532 https://github.com/spicetools/spicetools
This commit is contained in:
parent
abaf6d5fe3
commit
7a279737d3
713
src/PN532.cpp
713
src/PN532.cpp
File diff suppressed because it is too large
Load Diff
199
src/PN532.h
199
src/PN532.h
@ -16,139 +16,138 @@
|
|||||||
#include "PN532Interface.h"
|
#include "PN532Interface.h"
|
||||||
|
|
||||||
// PN532 Commands
|
// PN532 Commands
|
||||||
#define PN532_COMMAND_DIAGNOSE (0x00)
|
#define PN532_COMMAND_DIAGNOSE (0x00)
|
||||||
#define PN532_COMMAND_GETFIRMWAREVERSION (0x02)
|
#define PN532_COMMAND_GETFIRMWAREVERSION (0x02)
|
||||||
#define PN532_COMMAND_GETGENERALSTATUS (0x04)
|
#define PN532_COMMAND_GETGENERALSTATUS (0x04)
|
||||||
#define PN532_COMMAND_READREGISTER (0x06)
|
#define PN532_COMMAND_READREGISTER (0x06)
|
||||||
#define PN532_COMMAND_WRITEREGISTER (0x08)
|
#define PN532_COMMAND_WRITEREGISTER (0x08)
|
||||||
#define PN532_COMMAND_READGPIO (0x0C)
|
#define PN532_COMMAND_READGPIO (0x0C)
|
||||||
#define PN532_COMMAND_WRITEGPIO (0x0E)
|
#define PN532_COMMAND_WRITEGPIO (0x0E)
|
||||||
#define PN532_COMMAND_SETSERIALBAUDRATE (0x10)
|
#define PN532_COMMAND_SETSERIALBAUDRATE (0x10)
|
||||||
#define PN532_COMMAND_SETPARAMETERS (0x12)
|
#define PN532_COMMAND_SETPARAMETERS (0x12)
|
||||||
#define PN532_COMMAND_SAMCONFIGURATION (0x14)
|
#define PN532_COMMAND_SAMCONFIGURATION (0x14)
|
||||||
#define PN532_COMMAND_POWERDOWN (0x16)
|
#define PN532_COMMAND_POWERDOWN (0x16)
|
||||||
#define PN532_COMMAND_RFCONFIGURATION (0x32)
|
#define PN532_COMMAND_RFCONFIGURATION (0x32)
|
||||||
#define PN532_COMMAND_RFREGULATIONTEST (0x58)
|
#define PN532_COMMAND_RFREGULATIONTEST (0x58)
|
||||||
#define PN532_COMMAND_INJUMPFORDEP (0x56)
|
#define PN532_COMMAND_INJUMPFORDEP (0x56)
|
||||||
#define PN532_COMMAND_INJUMPFORPSL (0x46)
|
#define PN532_COMMAND_INJUMPFORPSL (0x46)
|
||||||
#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A)
|
#define PN532_COMMAND_INLISTPASSIVETARGET (0x4A)
|
||||||
#define PN532_COMMAND_INATR (0x50)
|
#define PN532_COMMAND_INATR (0x50)
|
||||||
#define PN532_COMMAND_INPSL (0x4E)
|
#define PN532_COMMAND_INPSL (0x4E)
|
||||||
#define PN532_COMMAND_INDATAEXCHANGE (0x40)
|
#define PN532_COMMAND_INDATAEXCHANGE (0x40)
|
||||||
#define PN532_COMMAND_INCOMMUNICATETHRU (0x42)
|
#define PN532_COMMAND_INCOMMUNICATETHRU (0x42)
|
||||||
#define PN532_COMMAND_INDESELECT (0x44)
|
#define PN532_COMMAND_INDESELECT (0x44)
|
||||||
#define PN532_COMMAND_INRELEASE (0x52)
|
#define PN532_COMMAND_INRELEASE (0x52)
|
||||||
#define PN532_COMMAND_INSELECT (0x54)
|
#define PN532_COMMAND_INSELECT (0x54)
|
||||||
#define PN532_COMMAND_INAUTOPOLL (0x60)
|
#define PN532_COMMAND_INAUTOPOLL (0x60)
|
||||||
#define PN532_COMMAND_TGINITASTARGET (0x8C)
|
#define PN532_COMMAND_TGINITASTARGET (0x8C)
|
||||||
#define PN532_COMMAND_TGSETGENERALBYTES (0x92)
|
#define PN532_COMMAND_TGSETGENERALBYTES (0x92)
|
||||||
#define PN532_COMMAND_TGGETDATA (0x86)
|
#define PN532_COMMAND_TGGETDATA (0x86)
|
||||||
#define PN532_COMMAND_TGSETDATA (0x8E)
|
#define PN532_COMMAND_TGSETDATA (0x8E)
|
||||||
#define PN532_COMMAND_TGSETMETADATA (0x94)
|
#define PN532_COMMAND_TGSETMETADATA (0x94)
|
||||||
#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
|
#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
|
||||||
#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
|
#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
|
||||||
#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A)
|
#define PN532_COMMAND_TGGETTARGETSTATUS (0x8A)
|
||||||
|
|
||||||
#define PN532_RESPONSE_INDATAEXCHANGE (0x41)
|
#define PN532_RESPONSE_INDATAEXCHANGE (0x41)
|
||||||
#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B)
|
#define PN532_RESPONSE_INLISTPASSIVETARGET (0x4B)
|
||||||
|
|
||||||
|
|
||||||
#define PN532_MIFARE_ISO14443A (0x00)
|
#define PN532_MIFARE_ISO14443A (0x00)
|
||||||
|
|
||||||
// Mifare Commands
|
// Mifare Commands
|
||||||
#define MIFARE_CMD_AUTH_A (0x60)
|
#define MIFARE_CMD_AUTH_A (0x60)
|
||||||
#define MIFARE_CMD_AUTH_B (0x61)
|
#define MIFARE_CMD_AUTH_B (0x61)
|
||||||
#define MIFARE_CMD_READ (0x30)
|
#define MIFARE_CMD_READ (0x30)
|
||||||
#define MIFARE_CMD_WRITE (0xA0)
|
#define MIFARE_CMD_WRITE (0xA0)
|
||||||
#define MIFARE_CMD_WRITE_ULTRALIGHT (0xA2)
|
#define MIFARE_CMD_WRITE_ULTRALIGHT (0xA2)
|
||||||
#define MIFARE_CMD_TRANSFER (0xB0)
|
#define MIFARE_CMD_TRANSFER (0xB0)
|
||||||
#define MIFARE_CMD_DECREMENT (0xC0)
|
#define MIFARE_CMD_DECREMENT (0xC0)
|
||||||
#define MIFARE_CMD_INCREMENT (0xC1)
|
#define MIFARE_CMD_INCREMENT (0xC1)
|
||||||
#define MIFARE_CMD_STORE (0xC2)
|
#define MIFARE_CMD_STORE (0xC2)
|
||||||
|
|
||||||
// FeliCa Commands
|
// FeliCa Commands
|
||||||
#define FELICA_CMD_POLLING (0x00)
|
#define FELICA_CMD_POLLING (0x00)
|
||||||
#define FELICA_CMD_REQUEST_SERVICE (0x02)
|
#define FELICA_CMD_REQUEST_SERVICE (0x02)
|
||||||
#define FELICA_CMD_REQUEST_RESPONSE (0x04)
|
#define FELICA_CMD_REQUEST_RESPONSE (0x04)
|
||||||
#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06)
|
#define FELICA_CMD_READ_WITHOUT_ENCRYPTION (0x06)
|
||||||
#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08)
|
#define FELICA_CMD_WRITE_WITHOUT_ENCRYPTION (0x08)
|
||||||
#define FELICA_CMD_REQUEST_SYSTEM_CODE (0x0C)
|
#define FELICA_CMD_REQUEST_SYSTEM_CODE (0x0C)
|
||||||
|
|
||||||
// FeliCa consts
|
// FeliCa consts
|
||||||
#define FELICA_READ_MAX_SERVICE_NUM 16
|
#define FELICA_READ_MAX_SERVICE_NUM 16
|
||||||
#define FELICA_READ_MAX_BLOCK_NUM 12 // for typical FeliCa card
|
#define FELICA_READ_MAX_BLOCK_NUM 12 // for typical FeliCa card
|
||||||
#define FELICA_WRITE_MAX_SERVICE_NUM 16
|
#define FELICA_WRITE_MAX_SERVICE_NUM 16
|
||||||
#define FELICA_WRITE_MAX_BLOCK_NUM 10 // for typical FeliCa card
|
#define FELICA_WRITE_MAX_BLOCK_NUM 10 // for typical FeliCa card
|
||||||
#define FELICA_REQ_SERVICE_MAX_NODE_NUM 32
|
#define FELICA_REQ_SERVICE_MAX_NODE_NUM 32
|
||||||
|
|
||||||
class PN532
|
class PN532 {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
PN532(PN532Interface &interface);
|
PN532(PN532Interface &interface);
|
||||||
|
|
||||||
void begin(void);
|
void begin(void);
|
||||||
|
|
||||||
// Generic PN532 functions
|
// Generic PN532 functions
|
||||||
bool SAMConfig(void);
|
bool SAMConfig(void);
|
||||||
uint32_t getFirmwareVersion(void);
|
uint32_t getFirmwareVersion(void);
|
||||||
uint32_t readRegister(uint16_t reg);
|
uint32_t readRegister(uint16_t reg);
|
||||||
uint32_t writeRegister(uint16_t reg, uint8_t val);
|
uint32_t writeRegister(uint16_t reg, uint8_t val);
|
||||||
bool setPassiveActivationRetries(uint8_t maxRetries);
|
bool setPassiveActivationRetries(uint8_t maxRetries);
|
||||||
bool setRFField(uint8_t autoRFCA, uint8_t rFOnOff);
|
bool setRFField(uint8_t autoRFCA, uint8_t rFOnOff);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Init PN532 as a target
|
* @brief Init PN532 as a target
|
||||||
* @param timeout max time to wait, 0 means no timeout
|
* @param timeout max time to wait, 0 means no timeout
|
||||||
* @return > 0 success
|
* @return > 0 success
|
||||||
* = 0 timeout
|
* = 0 timeout
|
||||||
* < 0 failed
|
* < 0 failed
|
||||||
*/
|
*/
|
||||||
int8_t tgInitAsTarget(uint16_t timeout = 0);
|
int8_t tgInitAsTarget(uint16_t timeout = 0);
|
||||||
int8_t tgInitAsTarget(const uint8_t* command, const uint8_t len, const uint16_t timeout = 0);
|
int8_t tgInitAsTarget(const uint8_t *command, const uint8_t len, const uint16_t timeout = 0);
|
||||||
|
|
||||||
int16_t tgGetData(uint8_t *buf, uint8_t len);
|
int16_t tgGetData(uint8_t *buf, uint8_t len);
|
||||||
bool tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
bool tgSetData(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
||||||
|
|
||||||
int16_t inRelease(const uint8_t relevantTarget = 0);
|
int16_t inRelease(const uint8_t relevantTarget = 0);
|
||||||
|
|
||||||
// ISO14443A functions
|
// ISO14443A functions
|
||||||
bool inListPassiveTarget();
|
bool inListPassiveTarget();
|
||||||
bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000);
|
bool readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 1000);
|
||||||
bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength);
|
bool inDataExchange(uint8_t *send, uint8_t sendLength, uint8_t *response, uint8_t *responseLength);
|
||||||
|
|
||||||
// Mifare Classic functions
|
// Mifare Classic functions
|
||||||
bool mifareclassic_IsFirstBlock (uint32_t uiBlock);
|
bool mifareclassic_IsFirstBlock(uint32_t uiBlock);
|
||||||
bool mifareclassic_IsTrailerBlock (uint32_t uiBlock);
|
bool mifareclassic_IsTrailerBlock(uint32_t uiBlock);
|
||||||
uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData);
|
uint8_t mifareclassic_AuthenticateBlock(uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData);
|
||||||
uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data);
|
uint8_t mifareclassic_ReadDataBlock(uint8_t blockNumber, uint8_t *data);
|
||||||
uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data);
|
uint8_t mifareclassic_WriteDataBlock(uint8_t blockNumber, uint8_t *data);
|
||||||
|
|
||||||
// FeliCa Functions
|
// FeliCa Functions
|
||||||
int8_t felica_Polling(uint16_t systemCode, uint8_t requestCode, uint8_t *idm, uint8_t *pmm, uint16_t *systemCodeResponse, uint16_t timeout=1000);
|
int8_t felica_Polling(uint16_t systemCode, uint8_t requestCode, uint8_t *idm, uint8_t *pmm, uint16_t *systemCodeResponse, uint16_t timeout = 1000);
|
||||||
int8_t felica_SendCommand (const uint8_t * command, uint8_t commandlength, uint8_t * response, uint8_t * responseLength);
|
int8_t felica_SendCommand(const uint8_t *command, uint8_t commandlength, uint8_t *response, uint8_t *responseLength);
|
||||||
int8_t felica_RequestService(uint8_t numNode, uint16_t *nodeCodeList, uint16_t *keyVersions) ;
|
int8_t felica_RequestService(uint8_t numNode, uint16_t *nodeCodeList, uint16_t *keyVersions);
|
||||||
int8_t felica_RequestResponse(uint8_t *mode);
|
int8_t felica_RequestResponse(uint8_t *mode);
|
||||||
int8_t felica_ReadWithoutEncryption (uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
int8_t felica_ReadWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
||||||
int8_t felica_WriteWithoutEncryption (uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
int8_t felica_WriteWithoutEncryption(uint8_t numService, const uint16_t *serviceCodeList, uint8_t numBlock, const uint16_t *blockList, uint8_t blockData[][16]);
|
||||||
int8_t felica_RequestSystemCode(uint8_t *numSystemCode, uint16_t *systemCodeList);
|
int8_t felica_RequestSystemCode(uint8_t *numSystemCode, uint16_t *systemCodeList);
|
||||||
int8_t felica_Release();
|
int8_t felica_Release();
|
||||||
|
|
||||||
uint8_t *getBuffer(uint8_t *len) {
|
uint8_t *getBuffer(uint8_t *len) {
|
||||||
*len = sizeof(pn532_packetbuffer) - 4;
|
*len = sizeof(pn532_packetbuffer) - 4;
|
||||||
return pn532_packetbuffer;
|
return pn532_packetbuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _uid[7]; // ISO14443A uid
|
uint8_t _uid[7]; // ISO14443A uid
|
||||||
uint8_t _uidLen; // uid len
|
uint8_t _uidLen; // uid len
|
||||||
uint8_t _key[6]; // Mifare Classic key
|
uint8_t _key[6]; // Mifare Classic key
|
||||||
uint8_t inListedTag; // Tg number of inlisted tag.
|
uint8_t inListedTag; // Tg number of inlisted tag.
|
||||||
uint8_t _felicaIDm[8]; // FeliCa IDm (NFCID2)
|
uint8_t _felicaIDm[8]; // FeliCa IDm (NFCID2)
|
||||||
uint8_t _felicaPMm[8]; // FeliCa PMm (PAD)
|
uint8_t _felicaPMm[8]; // FeliCa PMm (PAD)
|
||||||
|
|
||||||
uint8_t pn532_packetbuffer[64];
|
uint8_t pn532_packetbuffer[64];
|
||||||
|
|
||||||
PN532Interface *_interface;
|
PN532Interface *_interface;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,32 +5,32 @@
|
|||||||
#ifndef __PN532_INTERFACE_H__
|
#ifndef __PN532_INTERFACE_H__
|
||||||
#define __PN532_INTERFACE_H__
|
#define __PN532_INTERFACE_H__
|
||||||
|
|
||||||
#define PN532_PREAMBLE (0x00)
|
#define PN532_PREAMBLE (0x00)
|
||||||
#define PN532_STARTCODE1 (0x00)
|
#define PN532_STARTCODE1 (0x00)
|
||||||
#define PN532_STARTCODE2 (0xFF)
|
#define PN532_STARTCODE2 (0xFF)
|
||||||
#define PN532_POSTAMBLE (0x00)
|
#define PN532_POSTAMBLE (0x00)
|
||||||
|
|
||||||
#define PN532_HOSTTOPN532 (0xD4)
|
#define PN532_HOSTTOPN532 (0xD4)
|
||||||
#define PN532_PN532TOHOST (0xD5)
|
#define PN532_PN532TOHOST (0xD5)
|
||||||
|
|
||||||
#define PN532_ACK_WAIT_TIME (10) // ms, timeout of waiting for ACK
|
#define PN532_ACK_WAIT_TIME (10) // ms, timeout of waiting for ACK
|
||||||
|
|
||||||
#define PN532_INVALID_ACK (-1)
|
#define PN532_INVALID_ACK (-1)
|
||||||
#define PN532_TIMEOUT (-2)
|
#define PN532_TIMEOUT (-2)
|
||||||
#define PN532_INVALID_FRAME (-3)
|
#define PN532_INVALID_FRAME (-3)
|
||||||
#define PN532_NO_SPACE (-4)
|
#define PN532_NO_SPACE (-4)
|
||||||
|
|
||||||
#define REVERSE_BITS_ORDER(b) b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; \
|
#define REVERSE_BITS_ORDER(b) \
|
||||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; \
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; \
|
||||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; \
|
||||||
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1
|
||||||
|
|
||||||
class PN532Interface
|
class PN532Interface {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual void begin() = 0;
|
virtual void begin() = 0;
|
||||||
virtual void wakeup() = 0;
|
virtual void wakeup() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief write a command and check ack
|
* @brief write a command and check ack
|
||||||
* @param header packet header
|
* @param header packet header
|
||||||
* @param hlen length of header
|
* @param hlen length of header
|
||||||
@ -39,9 +39,9 @@ public:
|
|||||||
* @return 0 success
|
* @return 0 success
|
||||||
* not 0 failed
|
* not 0 failed
|
||||||
*/
|
*/
|
||||||
virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) = 0;
|
virtual int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief read the response of a command, strip prefix and suffix
|
* @brief read the response of a command, strip prefix and suffix
|
||||||
* @param buf to contain the response data
|
* @param buf to contain the response data
|
||||||
* @param len lenght to read
|
* @param len lenght to read
|
||||||
@ -49,8 +49,7 @@ public:
|
|||||||
* @return >=0 length of response without prefix and suffix
|
* @return >=0 length of response without prefix and suffix
|
||||||
* <0 failed to read response
|
* <0 failed to read response
|
||||||
*/
|
*/
|
||||||
virtual int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 1000) = 0;
|
virtual int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 1000) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5,195 +5,182 @@
|
|||||||
#include "PN532_SPI.h"
|
#include "PN532_SPI.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
#define STATUS_READ 2
|
#define STATUS_READ 2
|
||||||
#define DATA_WRITE 1
|
#define DATA_WRITE 1
|
||||||
#define DATA_READ 3
|
#define DATA_READ 3
|
||||||
|
|
||||||
PN532_SPI::PN532_SPI(SPIClass &spi, uint8_t ss)
|
PN532_SPI::PN532_SPI(SPIClass &spi, uint8_t ss) {
|
||||||
{
|
command = 0;
|
||||||
command = 0;
|
_spi = &spi;
|
||||||
_spi = &spi;
|
_ss = ss;
|
||||||
_ss = ss;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PN532_SPI::begin()
|
void PN532_SPI::begin() {
|
||||||
{
|
pinMode(_ss, OUTPUT);
|
||||||
pinMode(_ss, OUTPUT);
|
|
||||||
|
|
||||||
_spi->begin();
|
_spi->begin();
|
||||||
_spi->setDataMode(SPI_MODE0); // PN532 only supports mode0
|
_spi->setDataMode(SPI_MODE0); // PN532 only supports mode0
|
||||||
_spi->setBitOrder(LSBFIRST);
|
_spi->setBitOrder(LSBFIRST);
|
||||||
#ifndef __SAM3X8E__
|
#ifndef __SAM3X8E__
|
||||||
_spi->setClockDivider(SPI_CLOCK_DIV8); // set clock 2MHz(max: 5MHz)
|
_spi->setClockDivider(SPI_CLOCK_DIV8); // set clock 2MHz(max: 5MHz)
|
||||||
#else
|
#else
|
||||||
/** DUE spi library does not support SPI_CLOCK_DIV8 macro */
|
/** DUE spi library does not support SPI_CLOCK_DIV8 macro */
|
||||||
_spi->setClockDivider(42); // set clock 2MHz(max: 5MHz)
|
_spi->setClockDivider(42); // set clock 2MHz(max: 5MHz)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PN532_SPI::wakeup()
|
void PN532_SPI::wakeup() {
|
||||||
{
|
digitalWrite(_ss, LOW);
|
||||||
digitalWrite(_ss, LOW);
|
delay(2);
|
||||||
delay(2);
|
digitalWrite(_ss, HIGH);
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
|
int8_t PN532_SPI::writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) {
|
||||||
{
|
command = header[0];
|
||||||
command = header[0];
|
writeFrame(header, hlen, body, blen);
|
||||||
writeFrame(header, hlen, body, blen);
|
|
||||||
|
|
||||||
uint8_t timeout = PN532_ACK_WAIT_TIME;
|
uint8_t timeout = PN532_ACK_WAIT_TIME;
|
||||||
while (!isReady()) {
|
while (!isReady()) {
|
||||||
delay(1);
|
|
||||||
timeout--;
|
|
||||||
if (0 == timeout) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (readAckFrame()) {
|
|
||||||
return PN532_INVALID_ACK;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout)
|
|
||||||
{
|
|
||||||
uint16_t time = 0;
|
|
||||||
while (!isReady()) {
|
|
||||||
delay(1);
|
|
||||||
time++;
|
|
||||||
if (timeout > 0 && time > timeout) {
|
|
||||||
return PN532_TIMEOUT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(1);
|
delay(1);
|
||||||
|
timeout--;
|
||||||
int16_t result;
|
if (0 == timeout) {
|
||||||
do {
|
return -2;
|
||||||
write(DATA_READ);
|
|
||||||
|
|
||||||
if (0x00 != read() || // PREAMBLE
|
|
||||||
0x00 != read() || // STARTCODE1
|
|
||||||
0xFF != read() // STARTCODE2
|
|
||||||
) {
|
|
||||||
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t length = read();
|
|
||||||
if (0 != (uint8_t)(length + read())) { // checksum of length
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t cmd = command + 1; // response command
|
|
||||||
if (PN532_PN532TOHOST != read() || (cmd) != read()) {
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
length -= 2;
|
|
||||||
if (length > len) {
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
}
|
|
||||||
read();
|
|
||||||
read();
|
|
||||||
result = PN532_NO_SPACE; // not enough space
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
|
||||||
for (uint8_t i = 0; i < length; i++) {
|
|
||||||
buf[i] = read();
|
|
||||||
sum += buf[i];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t checksum = read();
|
|
||||||
if (0 != (uint8_t)(sum + checksum)) {
|
|
||||||
result = PN532_INVALID_FRAME;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
read(); // POSTAMBLE
|
|
||||||
|
|
||||||
result = length;
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PN532_SPI::isReady()
|
|
||||||
{
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
|
|
||||||
write(STATUS_READ);
|
|
||||||
uint8_t status = read() & 1;
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
|
|
||||||
{
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(2); // wake up PN532
|
|
||||||
|
|
||||||
write(DATA_WRITE);
|
|
||||||
write(PN532_PREAMBLE);
|
|
||||||
write(PN532_STARTCODE1);
|
|
||||||
write(PN532_STARTCODE2);
|
|
||||||
|
|
||||||
uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
|
|
||||||
write(length);
|
|
||||||
write(~length + 1); // checksum of length
|
|
||||||
|
|
||||||
write(PN532_HOSTTOPN532);
|
|
||||||
uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
|
|
||||||
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < hlen; i++) {
|
|
||||||
write(header[i]);
|
|
||||||
sum += header[i];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < blen; i++) {
|
}
|
||||||
write(body[i]);
|
if (readAckFrame()) {
|
||||||
sum += body[i];
|
return PN532_INVALID_ACK;
|
||||||
|
}
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
|
|
||||||
write(checksum);
|
|
||||||
write(PN532_POSTAMBLE);
|
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t PN532_SPI::readAckFrame()
|
int16_t PN532_SPI::readResponse(uint8_t buf[], uint8_t len, uint16_t timeout) {
|
||||||
{
|
uint16_t time = 0;
|
||||||
const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
|
while (!isReady()) {
|
||||||
|
|
||||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
|
||||||
|
|
||||||
digitalWrite(_ss, LOW);
|
|
||||||
delay(1);
|
delay(1);
|
||||||
|
time++;
|
||||||
|
if (timeout > 0 && time > timeout) {
|
||||||
|
return PN532_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(_ss, LOW);
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
int16_t result;
|
||||||
|
do {
|
||||||
write(DATA_READ);
|
write(DATA_READ);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
|
if (0x00 != read() || // PREAMBLE
|
||||||
ackBuf[i] = read();
|
0x00 != read() || // STARTCODE1
|
||||||
|
0xFF != read() // STARTCODE2
|
||||||
|
) {
|
||||||
|
|
||||||
|
result = PN532_INVALID_FRAME;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
digitalWrite(_ss, HIGH);
|
uint8_t length = read();
|
||||||
|
if (0 != (uint8_t)(length + read())) { // checksum of length
|
||||||
|
result = PN532_INVALID_FRAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
|
uint8_t cmd = command + 1; // response command
|
||||||
|
if (PN532_PN532TOHOST != read() || (cmd) != read()) {
|
||||||
|
result = PN532_INVALID_FRAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
length -= 2;
|
||||||
|
if (length > len) {
|
||||||
|
for (uint8_t i = 0; i < length; i++) {
|
||||||
|
}
|
||||||
|
read();
|
||||||
|
read();
|
||||||
|
result = PN532_NO_SPACE; // not enough space
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sum = PN532_PN532TOHOST + cmd;
|
||||||
|
for (uint8_t i = 0; i < length; i++) {
|
||||||
|
buf[i] = read();
|
||||||
|
sum += buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t checksum = read();
|
||||||
|
if (0 != (uint8_t)(sum + checksum)) {
|
||||||
|
result = PN532_INVALID_FRAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read(); // POSTAMBLE
|
||||||
|
|
||||||
|
result = length;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
digitalWrite(_ss, HIGH);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PN532_SPI::isReady() {
|
||||||
|
digitalWrite(_ss, LOW);
|
||||||
|
|
||||||
|
write(STATUS_READ);
|
||||||
|
uint8_t status = read() & 1;
|
||||||
|
digitalWrite(_ss, HIGH);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PN532_SPI::writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen) {
|
||||||
|
digitalWrite(_ss, LOW);
|
||||||
|
delay(2); // wake up PN532
|
||||||
|
|
||||||
|
write(DATA_WRITE);
|
||||||
|
write(PN532_PREAMBLE);
|
||||||
|
write(PN532_STARTCODE1);
|
||||||
|
write(PN532_STARTCODE2);
|
||||||
|
|
||||||
|
uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
|
||||||
|
write(length);
|
||||||
|
write(~length + 1); // checksum of length
|
||||||
|
|
||||||
|
write(PN532_HOSTTOPN532);
|
||||||
|
uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
|
||||||
|
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hlen; i++) {
|
||||||
|
write(header[i]);
|
||||||
|
sum += header[i];
|
||||||
|
}
|
||||||
|
for (uint8_t i = 0; i < blen; i++) {
|
||||||
|
write(body[i]);
|
||||||
|
sum += body[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
|
||||||
|
write(checksum);
|
||||||
|
write(PN532_POSTAMBLE);
|
||||||
|
|
||||||
|
digitalWrite(_ss, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t PN532_SPI::readAckFrame() {
|
||||||
|
const uint8_t PN532_ACK[] = { 0, 0, 0xFF, 0, 0xFF, 0 };
|
||||||
|
|
||||||
|
uint8_t ackBuf[sizeof(PN532_ACK)];
|
||||||
|
|
||||||
|
digitalWrite(_ss, LOW);
|
||||||
|
delay(1);
|
||||||
|
write(DATA_READ);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
|
||||||
|
ackBuf[i] = read();
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(_ss, HIGH);
|
||||||
|
|
||||||
|
return memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK));
|
||||||
}
|
}
|
||||||
|
@ -9,30 +9,30 @@
|
|||||||
#include "PN532Interface.h"
|
#include "PN532Interface.h"
|
||||||
class PN532_SPI : public PN532Interface {
|
class PN532_SPI : public PN532Interface {
|
||||||
public:
|
public:
|
||||||
PN532_SPI(SPIClass &spi, uint8_t ss);
|
PN532_SPI(SPIClass &spi, uint8_t ss);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void wakeup();
|
void wakeup();
|
||||||
int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
int8_t writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
||||||
|
|
||||||
int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
|
int16_t readResponse(uint8_t buf[], uint8_t len, uint16_t timeout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SPIClass* _spi;
|
SPIClass *_spi;
|
||||||
uint8_t _ss;
|
uint8_t _ss;
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
|
|
||||||
bool isReady();
|
bool isReady();
|
||||||
void writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
void writeFrame(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0);
|
||||||
int8_t readAckFrame();
|
int8_t readAckFrame();
|
||||||
|
|
||||||
inline void write(uint8_t data) {
|
inline void write(uint8_t data) {
|
||||||
_spi->transfer(data);
|
_spi->transfer(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint8_t read() {
|
inline uint8_t read() {
|
||||||
return _spi->transfer(0);
|
return _spi->transfer(0);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
76
src/connection.h
Normal file
76
src/connection.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
库代码来自:https://github.com/spicetools/spicetools/tree/master/api/resources/arduino
|
||||||
|
删除了未使用的函数。
|
||||||
|
*/
|
||||||
|
#ifndef SPICEAPI_CONNECTION_H
|
||||||
|
#define SPICEAPI_CONNECTION_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef SPICEAPI_INTERFACE
|
||||||
|
#define SPICEAPI_INTERFACE Serial
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace spiceapi {
|
||||||
|
|
||||||
|
class Connection {
|
||||||
|
private:
|
||||||
|
uint8_t* receive_buffer;
|
||||||
|
size_t receive_buffer_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Connection(size_t receive_buffer_size);
|
||||||
|
void reset();
|
||||||
|
const char* request(char* json);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
spiceapi::Connection::Connection(size_t receive_buffer_size) {
|
||||||
|
this->receive_buffer = new uint8_t[receive_buffer_size];
|
||||||
|
this->receive_buffer_size = receive_buffer_size;
|
||||||
|
this->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiceapi::Connection::reset() {
|
||||||
|
|
||||||
|
// drop all input
|
||||||
|
while (SPICEAPI_INTERFACE.available()) {
|
||||||
|
SPICEAPI_INTERFACE.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* spiceapi::Connection::request(char* json_data) {
|
||||||
|
auto json_len = strlen(json_data) + 1;
|
||||||
|
|
||||||
|
// send
|
||||||
|
auto send_result = SPICEAPI_INTERFACE.write((const char*)json_data, (int)json_len);
|
||||||
|
SPICEAPI_INTERFACE.flush();
|
||||||
|
if (send_result < (int)json_len) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive
|
||||||
|
size_t receive_data_len = 0;
|
||||||
|
while (SPICEAPI_INTERFACE) {
|
||||||
|
|
||||||
|
// read single byte
|
||||||
|
auto b = SPICEAPI_INTERFACE.read();
|
||||||
|
if (b < 0) continue;
|
||||||
|
receive_buffer[receive_data_len++] = b;
|
||||||
|
|
||||||
|
// check for buffer overflow
|
||||||
|
if (receive_data_len >= receive_buffer_size) {
|
||||||
|
this->reset();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for message end
|
||||||
|
if (receive_buffer[receive_data_len - 1] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return resulting json
|
||||||
|
return (const char*)&receive_buffer[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SPICEAPI_CONNECTION_H
|
140
src/wrappers.h
Normal file
140
src/wrappers.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
库代码来自:https://github.com/spicetools/spicetools/tree/master/api/resources/arduino
|
||||||
|
删除了未使用的函数。
|
||||||
|
*/
|
||||||
|
#ifndef SPICEAPI_WRAPPERS_H
|
||||||
|
#define SPICEAPI_WRAPPERS_H
|
||||||
|
|
||||||
|
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||||
|
#include "ArduinoJson.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "connection.h"
|
||||||
|
|
||||||
|
// default buffer sizes
|
||||||
|
#ifndef SPICEAPI_WRAPPER_BUFFER_SIZE
|
||||||
|
#define SPICEAPI_WRAPPER_BUFFER_SIZE 256
|
||||||
|
#endif
|
||||||
|
#ifndef SPICEAPI_WRAPPER_BUFFER_SIZE_STR
|
||||||
|
#define SPICEAPI_WRAPPER_BUFFER_SIZE_STR 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace spiceapi {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structs
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct InfoAvs {
|
||||||
|
String model, dest, spec, rev, ext;
|
||||||
|
};
|
||||||
|
|
||||||
|
// static storage
|
||||||
|
char JSON_BUFFER_STR[SPICEAPI_WRAPPER_BUFFER_SIZE_STR];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64_t msg_gen_id() {
|
||||||
|
static uint64_t id_global = 0;
|
||||||
|
return ++id_global;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *doc2str(DynamicJsonDocument *doc) {
|
||||||
|
char *buf = JSON_BUFFER_STR;
|
||||||
|
serializeJson(*doc, buf, SPICEAPI_WRAPPER_BUFFER_SIZE_STR);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicJsonDocument *request_gen(const char *module, const char *function) {
|
||||||
|
|
||||||
|
// create document
|
||||||
|
auto doc = new DynamicJsonDocument(SPICEAPI_WRAPPER_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// add attributes
|
||||||
|
(*doc)["id"] = msg_gen_id();
|
||||||
|
(*doc)["module"] = module;
|
||||||
|
(*doc)["function"] = function;
|
||||||
|
|
||||||
|
// add params
|
||||||
|
(*doc).createNestedArray("params");
|
||||||
|
|
||||||
|
// return document
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicJsonDocument *response_get(Connection &con, const char *json) {
|
||||||
|
|
||||||
|
// parse document
|
||||||
|
DynamicJsonDocument *doc = new DynamicJsonDocument(SPICEAPI_WRAPPER_BUFFER_SIZE);
|
||||||
|
auto err = deserializeJson(*doc, (char *)json);
|
||||||
|
|
||||||
|
// check for parse error
|
||||||
|
if (err) {
|
||||||
|
delete doc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check id
|
||||||
|
if (!(*doc)["id"].is<int64_t>()) {
|
||||||
|
delete doc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check errors
|
||||||
|
auto errors = (*doc)["errors"];
|
||||||
|
if (!errors.is<JsonArray>()) {
|
||||||
|
delete doc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check error count
|
||||||
|
if (errors.as<JsonArray>().size() > 0) {
|
||||||
|
delete doc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check data
|
||||||
|
if (!(*doc)["data"].is<JsonArray>()) {
|
||||||
|
delete doc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return document
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool card_insert(Connection &con, size_t index, const char *card_id) {
|
||||||
|
auto req = request_gen("card", "insert");
|
||||||
|
auto params = (*req)["params"].as<JsonArray>();
|
||||||
|
params.add(index);
|
||||||
|
params.add(card_id);
|
||||||
|
auto req_str = doc2str(req);
|
||||||
|
delete req;
|
||||||
|
auto res = response_get(con, con.request(req_str));
|
||||||
|
if (!res)
|
||||||
|
return false;
|
||||||
|
delete res;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool info_avs(Connection &con, InfoAvs &info) {
|
||||||
|
auto req = request_gen("info", "avs");
|
||||||
|
auto req_str = doc2str(req);
|
||||||
|
delete req;
|
||||||
|
auto res = response_get(con, con.request(req_str));
|
||||||
|
if (!res)
|
||||||
|
return false;
|
||||||
|
auto data = (*res)["data"][0];
|
||||||
|
info.model = (const char *)data["model"];
|
||||||
|
info.dest = (const char *)data["dest"];
|
||||||
|
info.spec = (const char *)data["spec"];
|
||||||
|
info.rev = (const char *)data["rev"];
|
||||||
|
info.ext = (const char *)data["ext"];
|
||||||
|
delete res;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //SPICEAPI_WRAPPERS_H
|
Loading…
Reference in New Issue
Block a user