188 lines
8.9 KiB
C++
188 lines
8.9 KiB
C++
#pragma once
|
|
#include "shiftreg.h"
|
|
#include "softspim.h"
|
|
#include "defines.h"
|
|
#include "serial.h"
|
|
|
|
class Mfrc522
|
|
{
|
|
public:
|
|
// Error codes.
|
|
static constexpr uint8_t OK = 0; // Everything A-OK.
|
|
static constexpr uint8_t NOTAGERR = 1; // No tag error
|
|
static constexpr uint8_t TIMEOUT = 2; // Timeout error
|
|
static constexpr uint8_t LEN = 3; // Buffer length error
|
|
static constexpr uint8_t COLLISION = 4; // Chip collision
|
|
static constexpr uint8_t CRC = 5; // CRC incorrect collision
|
|
static constexpr uint8_t ERR = 6; // General error
|
|
|
|
// Command words
|
|
static constexpr uint8_t IDLE = 0x00; // NO action; Cancel the current command
|
|
static constexpr uint8_t MEM = 0x01; // Store 25 byte into the internal buffer.
|
|
static constexpr uint8_t GENID = 0x02; // Generates a 10 byte random ID number.
|
|
static constexpr uint8_t CALCCRC = 0x03; // CRC Calculate or selftest.
|
|
static constexpr uint8_t TRANSMIT = 0x04; // Transmit data
|
|
static constexpr uint8_t NOCMDCH = 0x07; // No command change.
|
|
static constexpr uint8_t RECEIVE = 0x08; // Receive Data
|
|
static constexpr uint8_t TRANSCEIVE = 0x0C; // Transmit and receive data
|
|
static constexpr uint8_t AUTHENT = 0x0E; // Authentication Key
|
|
static constexpr uint8_t SOFTRESET = 0x0F; // Reset
|
|
|
|
// Tag command words
|
|
static constexpr uint8_t MF1_REQIDL = 0x26; // find the antenna area does not enter hibernation
|
|
static constexpr uint8_t MF1_REQALL = 0x52; // find all the tags antenna area
|
|
static constexpr uint8_t MF1_ANTICOLL = 0x93; // anti-collision
|
|
static constexpr uint8_t MF1_SELECTTAG = 0x93; // ??? election tag
|
|
static constexpr uint8_t MF1_AUTHENT1A = 0x60; // authentication key A
|
|
static constexpr uint8_t MF1_AUTHENT1B = 0x61; // authentication key B
|
|
static constexpr uint8_t MF1_READ = 0x30; // Read Block
|
|
static constexpr uint8_t MF1_WRITE = 0xA0; // write block
|
|
static constexpr uint8_t MF1_DECREMENT = 0xC0; // debit
|
|
static constexpr uint8_t MF1_INCREMENT = 0xC1; // recharge
|
|
static constexpr uint8_t MF1_RESTORE = 0xC2; // transfer block data to the buffer
|
|
static constexpr uint8_t MF1_TRANSFER = 0xB0; // save the data in the buffer
|
|
static constexpr uint8_t MF1_HALT = 0x50; // Sleep
|
|
|
|
//Page 0:Command and Status
|
|
static constexpr uint8_t CommandReg = 0x01;
|
|
static constexpr uint8_t ComIEnReg = 0x02;
|
|
static constexpr uint8_t DivIEnReg = 0x03;
|
|
static constexpr uint8_t ComIrqReg = 0x04;
|
|
static constexpr uint8_t DivIrqReg = 0x05;
|
|
static constexpr uint8_t ErrorReg = 0x06;
|
|
static constexpr uint8_t Status1Reg = 0x07;
|
|
static constexpr uint8_t Status2Reg = 0x08;
|
|
static constexpr uint8_t FIFODataReg = 0x09;
|
|
static constexpr uint8_t FIFOLevelReg = 0x0A;
|
|
static constexpr uint8_t WaterLevelReg = 0x0B;
|
|
static constexpr uint8_t ControlReg = 0x0C;
|
|
static constexpr uint8_t BitFramingReg = 0x0D;
|
|
static constexpr uint8_t CollReg = 0x0E;
|
|
//Page 1:Command
|
|
static constexpr uint8_t ModeReg = 0x11;
|
|
static constexpr uint8_t TxModeReg = 0x12;
|
|
static constexpr uint8_t RxModeReg = 0x13;
|
|
static constexpr uint8_t TxControlReg = 0x14;
|
|
static constexpr uint8_t TxAutoReg = 0x15;
|
|
static constexpr uint8_t TxSelReg = 0x16;
|
|
static constexpr uint8_t RxSelReg = 0x17;
|
|
static constexpr uint8_t RxThresholdReg= 0x18;
|
|
static constexpr uint8_t DemodReg = 0x19;
|
|
static constexpr uint8_t MifareReg = 0x1C;
|
|
static constexpr uint8_t SerialSpeedReg= 0x1F;
|
|
//Page 2:CFG
|
|
static constexpr uint8_t CRCResultRegH = 0x21;
|
|
static constexpr uint8_t CRCResultRegL = 0x22;
|
|
static constexpr uint8_t Reserved21 = 0x23;
|
|
static constexpr uint8_t ModWidthReg = 0x24;
|
|
static constexpr uint8_t RFCfgReg = 0x26;
|
|
static constexpr uint8_t GsNReg = 0x27;
|
|
static constexpr uint8_t CWGsPReg = 0x28;
|
|
static constexpr uint8_t ModGsPReg = 0x29;
|
|
static constexpr uint8_t TModeReg = 0x2A;
|
|
static constexpr uint8_t TPrescalerReg = 0x2B;
|
|
static constexpr uint8_t TReloadRegH = 0x2C;
|
|
static constexpr uint8_t TReloadRegL = 0x2D;
|
|
static constexpr uint8_t TCounterValueRegH = 0x2E;
|
|
static constexpr uint8_t TCounterValueRegL = 0x2F;
|
|
//Page 3:TestRegister
|
|
static constexpr uint8_t TestSel1Reg = 0x31;
|
|
static constexpr uint8_t TestSel2Reg = 0x32;
|
|
static constexpr uint8_t TestPinEnReg = 0x33;
|
|
static constexpr uint8_t TestPinValueReg = 0x34;
|
|
static constexpr uint8_t TestBusReg = 0x35;
|
|
static constexpr uint8_t AutoTestReg = 0x36;
|
|
static constexpr uint8_t VersionReg = 0x37;
|
|
static constexpr uint8_t AnalogTestReg = 0x38;
|
|
static constexpr uint8_t TestDAC1Reg = 0x39;
|
|
static constexpr uint8_t TestDAC2Reg = 0x3A;
|
|
static constexpr uint8_t TestADCReg = 0x3B;
|
|
|
|
// PICC (tag) commands
|
|
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
|
|
|
|
// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
|
|
static constexpr uint8_t PICC_CMD_REQA = 0x26;
|
|
// Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
|
|
static constexpr uint8_t PICC_CMD_WUPA = 0x52; // Cascade Tag. Not really a command, but used during anti collision.
|
|
static constexpr uint8_t PICC_CMD_CT = 0x88;
|
|
static constexpr uint8_t PICC_CMD_SEL_CL1 = 0x93; // Anti collision/Select, Cascade Level 1
|
|
static constexpr uint8_t PICC_CMD_SEL_CL2 = 0x95; // Anti collision/Select, Cascade Level 1
|
|
static constexpr uint8_t PICC_CMD_SEL_CL3 = 0x97; // Anti collision/Select, Cascade Level 1
|
|
// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
|
|
// The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
|
|
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
|
|
// The read/write commands can also be used for MIFARE Ultralight.
|
|
static constexpr uint8_t PICC_CMD_HLTA = 0x50;
|
|
static constexpr uint8_t PICC_CMD_MF_AUTH_KEY_A = 0x60; // Perform authentication with Key A
|
|
static constexpr uint8_t PICC_CMD_MF_AUTH_KEY_B = 0x61; // Perform authentication with Key B
|
|
// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
|
static constexpr uint8_t PICC_CMD_MF_READ = 0x30;
|
|
// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
|
static constexpr uint8_t PICC_CMD_MF_WRITE = 0xA0;
|
|
// Decrements the contents of a block and stores the result in the internal data register.
|
|
static constexpr uint8_t PICC_CMD_MF_DECREMENT = 0xC0;
|
|
// Increments the contents of a block and stores the result in the internal data register.
|
|
static constexpr uint8_t PICC_CMD_MF_INCREMENT = 0xC1;
|
|
// Reads the contents of a block into the internal data register.
|
|
static constexpr uint8_t PICC_CMD_MF_RESTORE = 0xC2;
|
|
// Writes the contents of the internal data register to a block.
|
|
static constexpr uint8_t PICC_CMD_MF_TRANSFER = 0xB0;
|
|
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
|
|
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
|
|
static constexpr uint8_t PICC_CMD_UL_WRITE = 0xA2; // Writes one 4 byte page to the PICC
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t size; // Number of bytes in the UID. 4, 7 or 10.
|
|
uint8_t uidByte[10];
|
|
uint8_t sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
|
|
} Uid;
|
|
|
|
|
|
private:
|
|
ShiftReg<NFC_PORTS>* _csReg;
|
|
SpiMaster* _spi;
|
|
|
|
uint8_t _csPin;
|
|
|
|
uint8_t read(uint8_t addr);
|
|
void read(uint8_t addr, uint8_t* data, uint8_t datalen, uint8_t rxAlign = 0);
|
|
void write(uint8_t addr, uint8_t data);
|
|
void write(uint8_t addr, uint8_t* data, uint8_t datalen);
|
|
void updateBit(uint8_t addr, uint8_t bit, bool value);
|
|
|
|
void (*_tagEnterdCb)(Mfrc522*, void*);
|
|
void* _userData;
|
|
|
|
public:
|
|
|
|
inline static Serial* serial = nullptr;
|
|
|
|
Mfrc522(SpiMaster* spi, ShiftReg<NFC_PORTS>* csReg, uint8_t csPin,
|
|
void (*tagEnterdCb)(Mfrc522*, void*) = nullptr, void* userData = nullptr);
|
|
|
|
uint8_t calculateCrc(uint8_t *data, uint8_t length, uint16_t *result);
|
|
|
|
uint8_t commuicateWithTag(uint8_t command, uint8_t waitIrq,
|
|
uint8_t *sendData, uint8_t sendLen,
|
|
uint8_t *recvData, uint8_t *recvLen,
|
|
uint8_t validBits = 0, uint8_t rxAlign = 0,
|
|
uint8_t *rxValidBits = nullptr);
|
|
|
|
uint8_t transceive(uint8_t *sendData, uint8_t sendLen, uint8_t *recvData, uint8_t *recvLen,
|
|
uint8_t validBits = 0, uint8_t rxAlign = 0, uint8_t *rxValidBits = nullptr);
|
|
|
|
uint8_t wakeupTag(uint8_t* bufferATQA, uint8_t *bufferLen);
|
|
|
|
uint8_t selectTag(Uid *uid);
|
|
|
|
void irq();
|
|
|
|
void setRf(bool on);
|
|
|
|
bool cardPresent();
|
|
|
|
static bool probe(SpiMaster* spi, ShiftReg<NFC_PORTS>* csReg, uint8_t csPin);
|
|
};
|