#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* _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* 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(); bool testFifo(); static bool probe(SpiMaster* spi, ShiftReg* csReg, uint8_t csPin); };