refactor class
move new rats functions to extra class
This commit is contained in:
890
MFRC522.cpp
890
MFRC522.cpp
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <MFRC522.h>
|
||||
#include "MFRC522.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for setting up the Arduino
|
||||
@@ -472,7 +472,7 @@ MFRC522::StatusCode MFRC522::PCD_CommunicateWithPICC( byte command, ///< The co
|
||||
|
||||
byte _validBits = 0;
|
||||
|
||||
// If the caller wants data back, get it from the MFRC522.
|
||||
// If the caller wants data back, get it from the MFRC522.
|
||||
if (backData && backLen) {
|
||||
byte n = PCD_ReadRegister(FIFOLevelReg); // Number of bytes in the FIFO
|
||||
if (n > *backLen) {
|
||||
@@ -790,102 +790,6 @@ MFRC522::StatusCode MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct
|
||||
|
||||
// Set correct uid->size
|
||||
uid->size = 3 * cascadeLevel + 1;
|
||||
|
||||
// IF SAK bit 6 = 1 then it is ISO/IEC 14443-4 (T=CL)
|
||||
// A Request ATS command should be sent
|
||||
// We also check SAK bit 3 is cero, as it stands for UID complete (1 would tell us it is incomplete)
|
||||
if ((uid->sak & 0x24) == 0x20) {
|
||||
Ats ats;
|
||||
result = PICC_RequestATS(&ats);
|
||||
if (result == STATUS_OK) {
|
||||
// Check the ATS
|
||||
if (ats.size > 0)
|
||||
{
|
||||
// TA1 has been transmitted?
|
||||
// PPS must be supported...
|
||||
if (ats.ta1.transmitted)
|
||||
{
|
||||
// TA1
|
||||
// 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | Description
|
||||
// ---+---+---+---+---+---+---+---+------------------------------------------
|
||||
// 0 | - | - | - | 0 | - | - | - | Different D for each direction supported
|
||||
// 1 | - | - | - | 0 | - | - | - | Only same D for both direction supported
|
||||
// - | x | x | x | 0 | - | - | - | DS (Send D)
|
||||
// - | - | - | - | 0 | x | x | x | DR (Receive D)
|
||||
//
|
||||
// D to bitrate table
|
||||
// 3 | 2 | 1 | Value
|
||||
// ---+---+---+-----------------------------
|
||||
// 1 | - | - | 848 kBaud is supported
|
||||
// - | 1 | - | 424 kBaud is supported
|
||||
// - | - | 1 | 212 kBaud is supported
|
||||
// 0 | 0 | 0 | Only 106 kBaud is supported
|
||||
//
|
||||
// Note: 106 kBaud is always supported
|
||||
//
|
||||
// I have almost constant timeouts when changing speeds :(
|
||||
TagBitRates ds = BITRATE_106KBITS;
|
||||
TagBitRates dr = BITRATE_106KBITS;
|
||||
|
||||
//// Not working at 848 or 424
|
||||
//if (ats.ta1.ds & 0x04)
|
||||
//{
|
||||
// ds = BITRATE_848KBITS;
|
||||
//}
|
||||
//else if (ats.ta1.ds & 0x02)
|
||||
//{
|
||||
// ds = BITRATE_424KBITS;
|
||||
//}
|
||||
//else if (ats.ta1.ds & 0x01)
|
||||
//{
|
||||
// ds = BITRATE_212KBITS;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// ds = BITRATE_106KBITS;
|
||||
//}
|
||||
|
||||
if (ats.ta1.ds & 0x01)
|
||||
{
|
||||
ds = BITRATE_212KBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds = BITRATE_106KBITS;
|
||||
}
|
||||
|
||||
//// Not working at 848 or 424
|
||||
//if (ats.ta1.dr & 0x04)
|
||||
//{
|
||||
// dr = BITRATE_848KBITS;
|
||||
//}
|
||||
//else if (ats.ta1.dr & 0x02)
|
||||
//{
|
||||
// dr = BITRATE_424KBITS;
|
||||
//}
|
||||
//else if (ats.ta1.dr & 0x01)
|
||||
//{
|
||||
// dr = BITRATE_212KBITS;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// dr = BITRATE_106KBITS;
|
||||
//}
|
||||
|
||||
if (ats.ta1.dr & 0x01)
|
||||
{
|
||||
dr = BITRATE_212KBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dr = BITRATE_106KBITS;
|
||||
}
|
||||
|
||||
PICC_PPS(ds, dr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} // End PICC_Select()
|
||||
@@ -923,615 +827,6 @@ MFRC522::StatusCode MFRC522::PICC_HaltA() {
|
||||
return result;
|
||||
} // End PICC_HaltA()
|
||||
|
||||
/**
|
||||
* Transmits a Request command for Answer To Select (ATS).
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::PICC_RequestATS(Ats *ats)
|
||||
{
|
||||
byte count;
|
||||
MFRC522::StatusCode result;
|
||||
|
||||
byte bufferATS[FIFO_SIZE];
|
||||
byte bufferSize = FIFO_SIZE;
|
||||
|
||||
memset(bufferATS, 0, FIFO_SIZE);
|
||||
|
||||
// Build command buffer
|
||||
bufferATS[0] = PICC_CMD_RATS;
|
||||
|
||||
// The CID defines the logical number of the addressed card and has a range of 0
|
||||
// through 14; 15 is reserved for future use (RFU).
|
||||
//
|
||||
// FSDI codes the maximum frame size (FSD) that the terminal can receive.
|
||||
//
|
||||
// FSDI | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9-F
|
||||
// ------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------
|
||||
// FSD (bytes) | 16 | 24 | 32 | 40 | 48 | 64 | 96 | 128 | 256 | RFU > 256
|
||||
//
|
||||
bufferATS[1] = 0x50; // FSD=64, CID=0
|
||||
|
||||
// Calculate CRC_A
|
||||
result = PCD_CalculateCRC(bufferATS, 2, &bufferATS[2]);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Transmit the buffer and receive the response, validate CRC_A.
|
||||
result = PCD_TransceiveData(bufferATS, 4, bufferATS, &bufferSize, NULL, 0, true);
|
||||
if (result != STATUS_OK) {
|
||||
PICC_HaltA();
|
||||
}
|
||||
|
||||
// Set the ats structure data
|
||||
ats->size = bufferATS[0];
|
||||
|
||||
// T0 byte:
|
||||
//
|
||||
// b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | Meaning
|
||||
//----+----+----+----+----+----+----+----+---------------------------
|
||||
// 0 | ...| ...| ...| ...|... | ...| ...| Set to 0 (RFU)
|
||||
// 0 | 1 | x | x | ...|... | ...| ...| TC1 transmitted
|
||||
// 0 | x | 1 | x | ...|... | ...| ...| TB1 transmitted
|
||||
// 0 | x | x | 1 | ...|... | ...| ...| TA1 transmitted
|
||||
// 0 | ...| ...| ...| x | x | x | x | Maximum frame size (FSCI)
|
||||
//
|
||||
// FSCI | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9-F
|
||||
// ------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----------
|
||||
// FSC (bytes) | 16 | 24 | 32 | 40 | 48 | 64 | 96 | 128 | 256 | RFU > 256
|
||||
//
|
||||
// Default FSCI is 2 (32 bytes)
|
||||
if (ats->size > 0x01)
|
||||
{
|
||||
// TC1, TB1 and TA1 where NOT transmitted
|
||||
ats->ta1.transmitted = (bool)(bufferATS[1] & 0x40);
|
||||
ats->tb1.transmitted = (bool)(bufferATS[1] & 0x20);
|
||||
ats->tc1.transmitted = (bool)(bufferATS[1] & 0x10);
|
||||
|
||||
// Decode FSCI
|
||||
switch (bufferATS[1] & 0x0F)
|
||||
{
|
||||
case 0x00:
|
||||
ats->fsc = 16;
|
||||
break;
|
||||
case 0x01:
|
||||
ats->fsc = 24;
|
||||
break;
|
||||
case 0x02:
|
||||
ats->fsc = 32;
|
||||
break;
|
||||
case 0x03:
|
||||
ats->fsc = 40;
|
||||
break;
|
||||
case 0x04:
|
||||
ats->fsc = 48;
|
||||
break;
|
||||
case 0x05:
|
||||
ats->fsc = 64;
|
||||
break;
|
||||
case 0x06:
|
||||
ats->fsc = 96;
|
||||
break;
|
||||
case 0x07:
|
||||
ats->fsc = 128;
|
||||
break;
|
||||
case 0x08:
|
||||
// This value cannot be hold by a byte
|
||||
// The reason I ignore it is that MFRC255 FIFO is 64 bytes so this is not a possible value (or atleast it shouldn't)
|
||||
//ats->fsc = 256;
|
||||
break;
|
||||
// TODO: What to do with RFU (Reserved for future use)?
|
||||
}
|
||||
|
||||
// TA1
|
||||
if (ats->ta1.transmitted)
|
||||
{
|
||||
ats->ta1.sameD = (bool)(bufferATS[2] & 0x80);
|
||||
ats->ta1.ds = (TagBitRates)((bufferATS[2] & 0x70) >> 4);
|
||||
ats->ta1.dr = (TagBitRates)(bufferATS[2] & 0x07);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default TA1
|
||||
ats->ta1.ds = BITRATE_106KBITS;
|
||||
ats->ta1.dr = BITRATE_106KBITS;
|
||||
}
|
||||
|
||||
// TB1
|
||||
if (ats->tb1.transmitted)
|
||||
{
|
||||
uint8_t tb1Index = 2;
|
||||
|
||||
if (ats->ta1.transmitted)
|
||||
tb1Index++;
|
||||
|
||||
ats->tb1.fwi = (bufferATS[tb1Index] & 0xF0) >> 4;
|
||||
ats->tb1.sfgi = bufferATS[tb1Index] & 0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Defaults for TB1
|
||||
ats->tb1.fwi = 0; // TODO: Don't know the default for this!
|
||||
ats->tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
||||
}
|
||||
|
||||
// TC1
|
||||
if (ats->tc1.transmitted)
|
||||
{
|
||||
uint8_t tc1Index = 2;
|
||||
|
||||
if (ats->ta1.transmitted)
|
||||
tc1Index++;
|
||||
if (ats->tb1.transmitted)
|
||||
tc1Index++;
|
||||
|
||||
ats->tc1.supportsCID = (bool)(bufferATS[tc1Index] & 0x02);
|
||||
ats->tc1.supportsNAD = (bool)(bufferATS[tc1Index] & 0x01);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Defaults for TC1
|
||||
ats->tc1.supportsCID = true;
|
||||
ats->tc1.supportsNAD = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TC1, TB1 and TA1 where NOT transmitted
|
||||
ats->ta1.transmitted = false;
|
||||
ats->tb1.transmitted = false;
|
||||
ats->tc1.transmitted = false;
|
||||
|
||||
// Default FSCI
|
||||
ats->fsc = 32; // Defaults to FSCI 2 (32 bytes)
|
||||
|
||||
// Default TA1
|
||||
ats->ta1.sameD = false;
|
||||
ats->ta1.ds = BITRATE_106KBITS;
|
||||
ats->ta1.dr = BITRATE_106KBITS;
|
||||
|
||||
// Defaults for TB1
|
||||
ats->tb1.transmitted = false;
|
||||
ats->tb1.fwi = 0; // TODO: Don't know the default for this!
|
||||
ats->tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
||||
|
||||
// Defaults for TC1
|
||||
ats->tc1.transmitted = false;
|
||||
ats->tc1.supportsCID = true;
|
||||
ats->tc1.supportsNAD = false;
|
||||
}
|
||||
|
||||
memcpy(ats->data, bufferATS, bufferSize - 2);
|
||||
|
||||
return result;
|
||||
} // End PICC_RequestATS()
|
||||
|
||||
/**
|
||||
* Transmits Protocol and Parameter Selection Request (PPS) without parameter 1
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::PICC_PPS()
|
||||
{
|
||||
StatusCode result;
|
||||
|
||||
byte ppsBuffer[4];
|
||||
byte ppsBufferSize = 4;
|
||||
// Start byte: The start byte (PPS) consists of two parts:
|
||||
// –The upper nibble(b8–b5) is set to’D'to identify the PPS. All other values are RFU.
|
||||
// -The lower nibble(b4–b1), which is called the ‘card identifier’ (CID), defines the logical number of the addressed card.
|
||||
ppsBuffer[0] = 0xD0; // CID is hardcoded as 0 in RATS
|
||||
ppsBuffer[1] = 0x00; // PPS0 indicates whether PPS1 is present
|
||||
|
||||
// Calculate CRC_A
|
||||
result = PCD_CalculateCRC(ppsBuffer, 2, &ppsBuffer[2]);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Transmit the buffer and receive the response, validate CRC_A.
|
||||
result = PCD_TransceiveData(ppsBuffer, 4, ppsBuffer, &ppsBufferSize, NULL, 0, true);
|
||||
if (result == STATUS_OK)
|
||||
{
|
||||
// Enable CRC for T=CL
|
||||
byte txReg = PCD_ReadRegister(TxModeReg) | 0x80;
|
||||
byte rxReg = PCD_ReadRegister(RxModeReg) | 0x80;
|
||||
|
||||
PCD_WriteRegister(TxModeReg, txReg);
|
||||
PCD_WriteRegister(RxModeReg, rxReg);
|
||||
}
|
||||
|
||||
return result;
|
||||
} // End PICC_PPS()
|
||||
|
||||
/**
|
||||
* Transmits Protocol and Parameter Selection Request (PPS)
|
||||
*
|
||||
* @return STATUS_OK on success, STATUS_??? otherwise.
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::PICC_PPS(TagBitRates sendBitRate, ///< DS
|
||||
TagBitRates receiveBitRate ///< DR
|
||||
) {
|
||||
StatusCode result;
|
||||
|
||||
byte txReg = PCD_ReadRegister(TxModeReg) & 0x8F;
|
||||
byte rxReg = PCD_ReadRegister(RxModeReg) & 0x8F;
|
||||
|
||||
byte ppsBuffer[5];
|
||||
byte ppsBufferSize = 5;
|
||||
// Start byte: The start byte (PPS) consists of two parts:
|
||||
// –The upper nibble(b8–b5) is set to’D'to identify the PPS. All other values are RFU.
|
||||
// -The lower nibble(b4–b1), which is called the ‘card identifier’ (CID), defines the logical number of the addressed card.
|
||||
ppsBuffer[0] = 0xD0; // CID is hardcoded as 0 in RATS
|
||||
ppsBuffer[1] = 0x11; // PPS0 indicates whether PPS1 is present
|
||||
|
||||
// Bit 8 - Set to '0' as MFRC522 allows different bit rates for send and receive
|
||||
// Bit 4 - Set to '0' as it is Reserved for future use.
|
||||
//ppsBuffer[2] = (((sendBitRate & 0x03) << 4) | (receiveBitRate & 0x03)) & 0xE7;
|
||||
ppsBuffer[2] = (((sendBitRate & 0x03) << 2) | (receiveBitRate & 0x03)) & 0xE7;
|
||||
|
||||
// Calculate CRC_A
|
||||
result = PCD_CalculateCRC(ppsBuffer, 3, &ppsBuffer[3]);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Transmit the buffer and receive the response, validate CRC_A.
|
||||
result = PCD_TransceiveData(ppsBuffer, 5, ppsBuffer, &ppsBufferSize, NULL, 0, true);
|
||||
if (result == STATUS_OK)
|
||||
{
|
||||
// Make sure it is an answer to our PPS
|
||||
// We should receive our PPS byte and 2 CRC bytes
|
||||
if ((ppsBufferSize == 3) && (ppsBuffer[0] == 0xD0)) {
|
||||
byte txReg = PCD_ReadRegister(TxModeReg) & 0x8F;
|
||||
byte rxReg = PCD_ReadRegister(RxModeReg) & 0x8F;
|
||||
|
||||
// Set bit rate and enable CRC for T=CL
|
||||
txReg = (txReg & 0x8F) | ((receiveBitRate & 0x03) << 4) | 0x80;
|
||||
rxReg = (rxReg & 0x8F) | ((sendBitRate & 0x03) << 4) | 0x80;
|
||||
rxReg &= 0xF0; //Enforce although this should be set already
|
||||
|
||||
// From ConfigIsoType
|
||||
//rxReg |= 0x06;
|
||||
|
||||
PCD_WriteRegister(TxModeReg, txReg);
|
||||
PCD_WriteRegister(RxModeReg, rxReg);
|
||||
|
||||
// At 212kBps
|
||||
switch (sendBitRate) {
|
||||
case BITRATE_212KBITS:
|
||||
{
|
||||
//PCD_WriteRegister(ModWidthReg, 0x13);
|
||||
PCD_WriteRegister(ModWidthReg, 0x15);
|
||||
}
|
||||
break;
|
||||
case BITRATE_424KBITS:
|
||||
{
|
||||
PCD_WriteRegister(ModWidthReg, 0x0A);
|
||||
}
|
||||
break;
|
||||
case BITRATE_848KBITS:
|
||||
{
|
||||
PCD_WriteRegister(ModWidthReg, 0x05);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
PCD_WriteRegister(ModWidthReg, 0x26); // Default value
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//PCD_WriteRegister(RxThresholdReg, 0x84); // ISO-14443.4 Type A (default)
|
||||
//PCD_WriteRegister(ControlReg, 0x10);
|
||||
|
||||
delayMicroseconds(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} // End PICC_PPS()
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with ISO/IEC 14433-4 cards
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MFRC522::StatusCode MFRC522::TCL_Transceive(PcbBlock *send, PcbBlock *back)
|
||||
{
|
||||
MFRC522::StatusCode result;
|
||||
byte inBuffer[FIFO_SIZE];
|
||||
byte inBufferSize = FIFO_SIZE;
|
||||
byte outBuffer[send->inf.size + 5]; // PCB + CID + NAD + INF + EPILOGUE (CRC)
|
||||
byte outBufferOffset = 1;
|
||||
byte inBufferOffset = 1;
|
||||
|
||||
// Set the PCB byte
|
||||
outBuffer[0] = send->prologue.pcb;
|
||||
|
||||
// Set the CID byte if available
|
||||
if (send->prologue.pcb & 0x08) {
|
||||
outBuffer[outBufferOffset] = send->prologue.cid;
|
||||
outBufferOffset++;
|
||||
}
|
||||
|
||||
// Set the NAD byte if available
|
||||
if (send->prologue.pcb & 0x04) {
|
||||
outBuffer[outBufferOffset] = send->prologue.nad;
|
||||
outBufferOffset++;
|
||||
}
|
||||
|
||||
// Copy the INF field if available
|
||||
if (send->inf.size > 0) {
|
||||
memcpy(&outBuffer[outBufferOffset], send->inf.data, send->inf.size);
|
||||
outBufferOffset += send->inf.size;
|
||||
}
|
||||
|
||||
// Is the CRC enabled for transmission?
|
||||
byte txModeReg = PCD_ReadRegister(TxModeReg);
|
||||
if ((txModeReg & 0x80) != 0x80) {
|
||||
// Calculate CRC_A
|
||||
result = PCD_CalculateCRC(outBuffer, outBufferOffset, &outBuffer[outBufferOffset]);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
outBufferOffset += 2;
|
||||
}
|
||||
|
||||
// Transceive the block
|
||||
result = PCD_TransceiveData(outBuffer, outBufferOffset, inBuffer, &inBufferSize);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// We want to turn the received array back to a PcbBlock
|
||||
back->prologue.pcb = inBuffer[0];
|
||||
|
||||
// CID byte is present?
|
||||
if (send->prologue.pcb & 0x08) {
|
||||
back->prologue.cid = inBuffer[inBufferOffset];
|
||||
inBufferOffset++;
|
||||
}
|
||||
|
||||
// NAD byte is present?
|
||||
if (send->prologue.pcb & 0x04) {
|
||||
back->prologue.nad = inBuffer[inBufferOffset];
|
||||
inBufferOffset++;
|
||||
}
|
||||
|
||||
// Check if CRC is taken care of by MFRC522
|
||||
byte rxModeReg = PCD_ReadRegister(TxModeReg);
|
||||
if ((rxModeReg & 0x80) != 0x80) {
|
||||
Serial.print("CRC is not taken care of by MFRC522: ");
|
||||
Serial.println(rxModeReg, HEX);
|
||||
|
||||
// Check the CRC
|
||||
// We need at least the CRC_A value.
|
||||
if ((int)(inBufferSize - inBufferOffset) < 2) {
|
||||
return STATUS_CRC_WRONG;
|
||||
}
|
||||
|
||||
// Verify CRC_A - do our own calculation and store the control in controlBuffer.
|
||||
byte controlBuffer[2];
|
||||
MFRC522::StatusCode status = PCD_CalculateCRC(inBuffer, inBufferSize - 2, controlBuffer);
|
||||
if (status != STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((inBuffer[inBufferSize - 2] != controlBuffer[0]) || (inBuffer[inBufferSize - 1] != controlBuffer[1])) {
|
||||
return STATUS_CRC_WRONG;
|
||||
}
|
||||
|
||||
// Take away the CRC bytes
|
||||
inBufferSize -= 2;
|
||||
}
|
||||
|
||||
// Got more data?
|
||||
if (inBufferSize > inBufferOffset) {
|
||||
if ((inBufferSize - inBufferOffset) > back->inf.size) {
|
||||
return STATUS_NO_ROOM;
|
||||
}
|
||||
|
||||
memcpy(back->inf.data, &inBuffer[inBufferOffset], inBufferSize - inBufferOffset);
|
||||
back->inf.size = inBufferSize - inBufferOffset;
|
||||
} else {
|
||||
back->inf.size = 0;
|
||||
}
|
||||
|
||||
// If the response is a R-Block check NACK
|
||||
if (((inBuffer[0] & 0xC0) == 0x80) && (inBuffer[0] & 0x20)) {
|
||||
return STATUS_MIFARE_NACK;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Send an I-Block (Application)
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::TCL_Transceive(TagInfo *tag, byte *sendData, byte sendLen, byte *backData, byte *backLen)
|
||||
{
|
||||
MFRC522::StatusCode result;
|
||||
|
||||
PcbBlock out;
|
||||
PcbBlock in;
|
||||
byte outBuffer[FIFO_SIZE];
|
||||
byte outBufferSize = FIFO_SIZE;
|
||||
byte totalBackLen = *backLen;
|
||||
|
||||
// This command sends an I-Block
|
||||
out.prologue.pcb = 0x02;
|
||||
|
||||
if (tag->ats.tc1.supportsCID) {
|
||||
out.prologue.pcb |= 0x08;
|
||||
out.prologue.cid = 0x00; // CID is curentlly hardcoded as 0x00
|
||||
}
|
||||
|
||||
// This command doe not support NAD
|
||||
out.prologue.pcb &= 0xFB;
|
||||
out.prologue.nad = 0x00;
|
||||
|
||||
// Set the block number
|
||||
if (tag->blockNumber) {
|
||||
out.prologue.pcb |= 0x01;
|
||||
}
|
||||
|
||||
// Do we have data to send?
|
||||
if (sendData && (sendLen > 0)) {
|
||||
out.inf.size = sendLen;
|
||||
out.inf.data = sendData;
|
||||
} else {
|
||||
out.inf.size = 0;
|
||||
out.inf.data = NULL;
|
||||
}
|
||||
|
||||
// Initialize the receiving data
|
||||
in.inf.data = outBuffer;
|
||||
in.inf.size = outBufferSize;
|
||||
|
||||
result = TCL_Transceive(&out, &in);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Swap block number on success
|
||||
if (tag->blockNumber)
|
||||
tag->blockNumber = false;
|
||||
else
|
||||
tag->blockNumber = true;
|
||||
|
||||
if (backData && (backLen > 0)) {
|
||||
if (*backLen < in.inf.size)
|
||||
return STATUS_NO_ROOM;
|
||||
|
||||
*backLen = in.inf.size;
|
||||
memcpy(backData, in.inf.data, in.inf.size);
|
||||
}
|
||||
|
||||
// Check chaining
|
||||
if (in.prologue.pcb & 0x10 == 0x00)
|
||||
return result;
|
||||
|
||||
// Result is chained
|
||||
// Send an ACK to receive more data
|
||||
// TODO: Should be checked I've never needed to send an ACK
|
||||
while (in.prologue.pcb & 0x10) {
|
||||
byte ackData[FIFO_SIZE];
|
||||
byte ackDataSize = FIFO_SIZE;
|
||||
|
||||
result = TCL_TransceiveRBlock(tag, true, ackData, &ackDataSize);
|
||||
if (result != STATUS_OK)
|
||||
return result;
|
||||
|
||||
if (backData && (backLen > 0)) {
|
||||
if ((*backLen + ackDataSize) > totalBackLen)
|
||||
return STATUS_NO_ROOM;
|
||||
|
||||
memcpy(&(backData[*backLen]), ackData, ackDataSize);
|
||||
*backLen += ackDataSize;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} // End TCL_Transceive()
|
||||
|
||||
/**
|
||||
* Send R-Block to the PICC.
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData, byte *backLen)
|
||||
{
|
||||
MFRC522::StatusCode result;
|
||||
|
||||
PcbBlock out;
|
||||
PcbBlock in;
|
||||
byte outBuffer[FIFO_SIZE];
|
||||
byte outBufferSize = FIFO_SIZE;
|
||||
|
||||
// This command sends an R-Block
|
||||
if (ack)
|
||||
out.prologue.pcb = 0xA2; // ACK
|
||||
else
|
||||
out.prologue.pcb = 0xB2; // NAK
|
||||
|
||||
|
||||
if (tag->ats.tc1.supportsCID) {
|
||||
out.prologue.pcb |= 0x08;
|
||||
out.prologue.cid = 0x00; // CID is curentlly hardcoded as 0x00
|
||||
}
|
||||
|
||||
// This command doe not support NAD
|
||||
out.prologue.pcb &= 0xFB;
|
||||
out.prologue.nad = 0x00;
|
||||
|
||||
// Set the block number
|
||||
if (tag->blockNumber) {
|
||||
out.prologue.pcb |= 0x01;
|
||||
}
|
||||
|
||||
// No INF data for R-Block
|
||||
out.inf.size = 0;
|
||||
out.inf.data = NULL;
|
||||
|
||||
// Initialize the receiving data
|
||||
in.inf.data = outBuffer;
|
||||
in.inf.size = outBufferSize;
|
||||
|
||||
result = TCL_Transceive(&out, &in);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Swap block number on success
|
||||
if (tag->blockNumber)
|
||||
tag->blockNumber = false;
|
||||
else
|
||||
tag->blockNumber = true;
|
||||
|
||||
if (backData && backLen) {
|
||||
if (*backLen < in.inf.size)
|
||||
return STATUS_NO_ROOM;
|
||||
|
||||
*backLen = in.inf.size;
|
||||
memcpy(backData, in.inf.data, in.inf.size);
|
||||
}
|
||||
|
||||
return result;
|
||||
} // End TCL_TransceiveRBlock()
|
||||
|
||||
/**
|
||||
* Send an S-Block to deselect the card.
|
||||
*/
|
||||
MFRC522::StatusCode MFRC522::TCL_Deselect(TagInfo *tag)
|
||||
{
|
||||
MFRC522::StatusCode result;
|
||||
byte outBuffer[4];
|
||||
byte outBufferSize = 1;
|
||||
byte inBuffer[FIFO_SIZE];
|
||||
byte inBufferSize = FIFO_SIZE;
|
||||
|
||||
outBuffer[0] = 0xC2;
|
||||
if (tag->ats.tc1.supportsCID)
|
||||
{
|
||||
outBuffer[0] |= 0x08;
|
||||
outBuffer[1] = 0x00; // CID is hardcoded
|
||||
outBufferSize = 2;
|
||||
}
|
||||
|
||||
result = PCD_TransceiveData(outBuffer, outBufferSize, inBuffer, &inBufferSize);
|
||||
if (result != STATUS_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO:Maybe do some checks? In my test it returns: CA 00 (Same data as I sent to my card)
|
||||
|
||||
return result;
|
||||
} // End TCL_Deselect()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with MIFARE PICCs
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1963,36 +1258,6 @@ const __FlashStringHelper *MFRC522::GetStatusCodeName(MFRC522::StatusCode code /
|
||||
}
|
||||
} // End GetStatusCodeName()
|
||||
|
||||
/**
|
||||
* Get the PICC type.
|
||||
*
|
||||
* @return PICC_Type
|
||||
*/
|
||||
MFRC522::PICC_Type MFRC522::PICC_GetType(TagInfo *tag ///< The TagInfo returned from PICC_Select().
|
||||
) {
|
||||
// http://www.nxp.com/documents/application_note/AN10833.pdf
|
||||
// 3.2 Coding of Select Acknowledge (SAK)
|
||||
// ignore 8-bit (iso14443 starts with LSBit = bit 1)
|
||||
// fixes wrong type for manufacturer Infineon (http://nfc-tools.org/index.php?title=ISO14443A)
|
||||
byte sak = tag->uid.sak & 0x7F;
|
||||
switch (sak) {
|
||||
case 0x04: return PICC_TYPE_NOT_COMPLETE; // UID not complete
|
||||
case 0x09: return PICC_TYPE_MIFARE_MINI;
|
||||
case 0x08: return PICC_TYPE_MIFARE_1K;
|
||||
case 0x18: return PICC_TYPE_MIFARE_4K;
|
||||
case 0x00: return PICC_TYPE_MIFARE_UL;
|
||||
case 0x10:
|
||||
case 0x11: return PICC_TYPE_MIFARE_PLUS;
|
||||
case 0x01: return PICC_TYPE_TNP3XXX;
|
||||
case 0x20:
|
||||
if (tag->atqa == 0x0344)
|
||||
return PICC_TYPE_MIFARE_DESFIRE;
|
||||
return PICC_TYPE_ISO_14443_4;
|
||||
case 0x40: return PICC_TYPE_ISO_18092;
|
||||
default: return PICC_TYPE_UNKNOWN;
|
||||
}
|
||||
} // End PICC_GetType()
|
||||
|
||||
/**
|
||||
* Translates the SAK (Select Acknowledge) to a PICC type.
|
||||
*
|
||||
@@ -2065,56 +1330,6 @@ void MFRC522::PCD_DumpVersionToSerial() {
|
||||
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
|
||||
} // End PCD_DumpVersionToSerial()
|
||||
|
||||
/**
|
||||
* Dumps debug info about the selected PICC to Serial.
|
||||
* On success the PICC is halted after dumping the data.
|
||||
* For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
|
||||
*/
|
||||
void MFRC522::PICC_DumpToSerial(TagInfo *tag)
|
||||
{
|
||||
MIFARE_Key key;
|
||||
|
||||
// Dump UID, SAK and Type
|
||||
PICC_DumpDetailsToSerial(tag);
|
||||
|
||||
// Dump contents
|
||||
PICC_Type piccType = PICC_GetType(tag->uid.sak);
|
||||
switch (piccType) {
|
||||
case PICC_TYPE_MIFARE_MINI:
|
||||
case PICC_TYPE_MIFARE_1K:
|
||||
case PICC_TYPE_MIFARE_4K:
|
||||
// All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
|
||||
for (byte i = 0; i < 6; i++) {
|
||||
key.keyByte[i] = 0xFF;
|
||||
}
|
||||
PICC_DumpMifareClassicToSerial(&tag->uid, piccType, &key);
|
||||
break;
|
||||
|
||||
case PICC_TYPE_MIFARE_UL:
|
||||
PICC_DumpMifareUltralightToSerial();
|
||||
break;
|
||||
|
||||
case PICC_TYPE_ISO_14443_4:
|
||||
case PICC_TYPE_MIFARE_DESFIRE:
|
||||
PICC_DumpISO14443_4(tag);
|
||||
Serial.println(F("Dumping memory contents not implemented for that PICC type."));
|
||||
break;
|
||||
case PICC_TYPE_ISO_18092:
|
||||
case PICC_TYPE_MIFARE_PLUS:
|
||||
case PICC_TYPE_TNP3XXX:
|
||||
Serial.println(F("Dumping memory contents not implemented for that PICC type."));
|
||||
break;
|
||||
|
||||
case PICC_TYPE_UNKNOWN:
|
||||
case PICC_TYPE_NOT_COMPLETE:
|
||||
default:
|
||||
break; // No memory dump here
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps debug info about the selected PICC to Serial.
|
||||
* On success the PICC is halted after dumping the data.
|
||||
@@ -2164,45 +1379,6 @@ void MFRC522::PICC_DumpToSerial(Uid *uid ///< Pointer to Uid struct returned fro
|
||||
PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
|
||||
} // End PICC_DumpToSerial()
|
||||
|
||||
/**
|
||||
* Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
|
||||
*/
|
||||
void MFRC522::PICC_DumpDetailsToSerial(TagInfo *tag ///< Pointer to TagInfo struct returned from a successful PICC_Select().
|
||||
) {
|
||||
// ATQA
|
||||
Serial.print(F("Card ATQA:"));
|
||||
if (((tag->atqa & 0xFF00u) >> 8) < 0x10)
|
||||
Serial.print(F(" 0"));
|
||||
Serial.print((tag->atqa & 0xFF00u) >> 8, HEX);
|
||||
if ((tag->atqa & 0x00FFu) < 0x10)
|
||||
Serial.print(F("0"));
|
||||
else
|
||||
Serial.print(F(" "));
|
||||
Serial.println(tag->atqa & 0x00FFu, HEX);
|
||||
|
||||
// UID
|
||||
Serial.print(F("Card UID:"));
|
||||
for (byte i = 0; i < tag->uid.size; i++) {
|
||||
if (tag->uid.uidByte[i] < 0x10)
|
||||
Serial.print(F(" 0"));
|
||||
else
|
||||
Serial.print(F(" "));
|
||||
Serial.print(tag->uid.uidByte[i], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// SAK
|
||||
Serial.print(F("Card SAK: "));
|
||||
if (tag->uid.sak < 0x10)
|
||||
Serial.print(F("0"));
|
||||
Serial.println(tag->uid.sak, HEX);
|
||||
|
||||
// (suggested) PICC type
|
||||
PICC_Type piccType = PICC_GetType(tag);
|
||||
Serial.print(F("PICC type: "));
|
||||
Serial.println(PICC_GetTypeName(piccType));
|
||||
} // End PICC_DumpDetailsToSerial()
|
||||
|
||||
/**
|
||||
* Dumps card info (UID,SAK,Type) about the selected PICC to Serial.
|
||||
*
|
||||
@@ -2465,26 +1641,6 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() {
|
||||
}
|
||||
} // End PICC_DumpMifareUltralightToSerial()
|
||||
|
||||
/**
|
||||
* Dumps memory contents of a ISO-14443-4 PICC.
|
||||
*/
|
||||
void MFRC522::PICC_DumpISO14443_4(TagInfo *tag)
|
||||
{
|
||||
// ATS
|
||||
if (tag->ats.size > 0x00) { // The first byte is the ATS length including the length byte
|
||||
Serial.print(F("Card ATS:"));
|
||||
for (byte offset = 0; offset < tag->ats.size; offset++) {
|
||||
if (tag->ats.data[offset] < 0x10)
|
||||
Serial.print(F(" 0"));
|
||||
else
|
||||
Serial.print(F(" "));
|
||||
Serial.print(tag->ats.data[offset], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
} // End PICC_DumpISO14443_4
|
||||
|
||||
/**
|
||||
* Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1).
|
||||
*/
|
||||
@@ -2725,34 +1881,7 @@ bool MFRC522::PICC_IsNewCardPresent() {
|
||||
PCD_WriteRegister(ModWidthReg, 0x26);
|
||||
|
||||
MFRC522::StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
|
||||
|
||||
if (result == STATUS_OK || result == STATUS_COLLISION) {
|
||||
tag.atqa = ((uint16_t)bufferATQA[1] << 8) | bufferATQA[0];
|
||||
tag.ats.size = 0;
|
||||
tag.ats.fsc = 32; // default FSC value
|
||||
|
||||
// Defaults for TA1
|
||||
tag.ats.ta1.transmitted = false;
|
||||
tag.ats.ta1.sameD = false;
|
||||
tag.ats.ta1.ds = BITRATE_106KBITS;
|
||||
tag.ats.ta1.dr = BITRATE_106KBITS;
|
||||
|
||||
// Defaults for TB1
|
||||
tag.ats.tb1.transmitted = false;
|
||||
tag.ats.tb1.fwi = 0; // TODO: Don't know the default for this!
|
||||
tag.ats.tb1.sfgi = 0; // The default value of SFGI is 0 (meaning that the card does not need any particular SFGT)
|
||||
|
||||
// Defaults for TC1
|
||||
tag.ats.tc1.transmitted = false;
|
||||
tag.ats.tc1.supportsCID = true;
|
||||
tag.ats.tc1.supportsNAD = false;
|
||||
|
||||
memset(tag.ats.data, 0, FIFO_SIZE - 2);
|
||||
|
||||
tag.blockNumber = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (result == STATUS_OK || result == STATUS_COLLISION);
|
||||
} // End PICC_IsNewCardPresent()
|
||||
|
||||
/**
|
||||
@@ -2764,15 +1893,6 @@ bool MFRC522::PICC_IsNewCardPresent() {
|
||||
* @return bool
|
||||
*/
|
||||
bool MFRC522::PICC_ReadCardSerial() {
|
||||
MFRC522::StatusCode result = PICC_Select(&tag.uid);
|
||||
|
||||
// Backward compatibility
|
||||
uid.size = tag.uid.size;
|
||||
uid.sak = tag.uid.sak;
|
||||
memcpy(uid.uidByte, tag.uid.uidByte, sizeof(tag.uid.uidByte));
|
||||
|
||||
if (result != STATUS_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
MFRC522::StatusCode result = PICC_Select(&uid);
|
||||
return (result == STATUS_OK);
|
||||
} // End
|
||||
|
||||
84
MFRC522.h
84
MFRC522.h
@@ -77,6 +77,7 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MFRC522_SPICLOCK SPI_CLOCK_DIV4 // MFRC522 accept upto 10MHz
|
||||
|
||||
@@ -306,14 +307,6 @@ public:
|
||||
STATUS_CRC_WRONG , // The CRC_A does not match
|
||||
STATUS_MIFARE_NACK = 0xff // A MIFARE PICC responded with NAK.
|
||||
};
|
||||
|
||||
// ISO/IEC 14443-4 bit rates
|
||||
enum TagBitRates : byte {
|
||||
BITRATE_106KBITS = 0x00,
|
||||
BITRATE_212KBITS = 0x01,
|
||||
BITRATE_424KBITS = 0x02,
|
||||
BITRATE_848KBITS = 0x03
|
||||
};
|
||||
|
||||
// A struct used for passing the UID of a PICC.
|
||||
typedef struct {
|
||||
@@ -322,65 +315,13 @@ public:
|
||||
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
|
||||
} Uid;
|
||||
|
||||
// Structure to store ISO/IEC 14443-4 ATS
|
||||
typedef struct {
|
||||
byte size;
|
||||
byte fsc; // Frame size for proximity card
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
bool sameD; // Only the same D for both directions supported
|
||||
TagBitRates ds; // Send D
|
||||
TagBitRates dr; // Receive D
|
||||
} ta1;
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
byte fwi; // Frame waiting time integer
|
||||
byte sfgi; // Start-up frame guard time integer
|
||||
} tb1;
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
bool supportsCID;
|
||||
bool supportsNAD;
|
||||
} tc1;
|
||||
|
||||
// Raw data from ATS
|
||||
byte data[FIFO_SIZE - 2]; // ATS cannot be bigger than FSD - 2 bytes (CRC), according to ISO 14443-4 5.2.2
|
||||
} Ats;
|
||||
|
||||
// A struct used for passing the PICC information
|
||||
typedef struct {
|
||||
uint16_t atqa;
|
||||
Uid uid;
|
||||
Ats ats;
|
||||
|
||||
// For Block PCB
|
||||
bool blockNumber;
|
||||
} TagInfo;
|
||||
|
||||
// A struct used for passing a MIFARE Crypto1 key
|
||||
typedef struct {
|
||||
byte keyByte[MF_KEY_SIZE];
|
||||
} MIFARE_Key;
|
||||
|
||||
// A struct used for passing PCB Block
|
||||
typedef struct {
|
||||
struct {
|
||||
byte pcb;
|
||||
byte cid;
|
||||
byte nad;
|
||||
} prologue;
|
||||
struct {
|
||||
byte size;
|
||||
byte *data;
|
||||
} inf;
|
||||
} PcbBlock;
|
||||
|
||||
// Member variables
|
||||
Uid uid; // Used by PICC_ReadCardSerial().
|
||||
TagInfo tag;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for setting up the Arduino
|
||||
@@ -422,19 +363,8 @@ public:
|
||||
StatusCode PICC_RequestA(byte *bufferATQA, byte *bufferSize);
|
||||
StatusCode PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
|
||||
StatusCode PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
|
||||
StatusCode PICC_Select(Uid *uid, byte validBits = 0);
|
||||
virtual StatusCode PICC_Select(Uid *uid, byte validBits = 0);
|
||||
StatusCode PICC_HaltA();
|
||||
StatusCode PICC_RequestATS(Ats *ats);
|
||||
StatusCode PICC_PPS(); // PPS command without bitrate parameter
|
||||
StatusCode PICC_PPS(TagBitRates sendBitRate, TagBitRates receiveBitRate); // Different D values
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with ISO/IEC 14433-4 cards
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
StatusCode TCL_Transceive(PcbBlock *send, PcbBlock *back);
|
||||
StatusCode TCL_Transceive(TagInfo * tag, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL);
|
||||
StatusCode TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData = NULL, byte *backLen = NULL);
|
||||
StatusCode TCL_Deselect(TagInfo *tag);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with MIFARE PICCs
|
||||
@@ -460,21 +390,17 @@ public:
|
||||
//const char *GetStatusCodeName(byte code);
|
||||
static const __FlashStringHelper *GetStatusCodeName(StatusCode code);
|
||||
static PICC_Type PICC_GetType(byte sak);
|
||||
static PICC_Type PICC_GetType(TagInfo *tag);
|
||||
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
|
||||
//const char *PICC_GetTypeName(byte type);
|
||||
static const __FlashStringHelper *PICC_GetTypeName(PICC_Type type);
|
||||
|
||||
// Support functions for debuging
|
||||
void PCD_DumpVersionToSerial();
|
||||
void PICC_DumpToSerial(TagInfo *tag);
|
||||
void PICC_DumpToSerial(Uid *uid);
|
||||
void PICC_DumpDetailsToSerial(TagInfo *tag);
|
||||
void PICC_DumpDetailsToSerial(Uid *uid);
|
||||
void PICC_DumpMifareClassicToSerial(Uid *uid, PICC_Type piccType, MIFARE_Key *key);
|
||||
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
|
||||
void PICC_DumpMifareUltralightToSerial();
|
||||
void PICC_DumpISO14443_4(TagInfo *tag);
|
||||
|
||||
// Advanced functions for MIFARE
|
||||
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
||||
@@ -485,10 +411,10 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience functions - does not add extra functionality
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
bool PICC_IsNewCardPresent();
|
||||
bool PICC_ReadCardSerial();
|
||||
virtual bool PICC_IsNewCardPresent();
|
||||
virtual bool PICC_ReadCardSerial();
|
||||
|
||||
private:
|
||||
protected:
|
||||
byte _chipSelectPin; // Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
|
||||
byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
|
||||
StatusCode MIFARE_TwoStepHelper(byte command, byte blockAddr, int32_t data);
|
||||
|
||||
1161
MFRC522Extended.cpp
Normal file
1161
MFRC522Extended.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
MFRC522Extended.h
Normal file
110
MFRC522Extended.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Library extends MFRC522.h to support RATS for ISO-14443-4 PICC.
|
||||
* RATS - Request for Answer To Select.
|
||||
* @author JPG-Consulting
|
||||
*/
|
||||
#ifndef MFRC522Extended_h
|
||||
#define MFRC522Extended_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "MFRC522.h"
|
||||
|
||||
class MFRC522Extended : public MFRC522 {
|
||||
|
||||
public:
|
||||
// ISO/IEC 14443-4 bit rates
|
||||
enum TagBitRates : byte {
|
||||
BITRATE_106KBITS = 0x00,
|
||||
BITRATE_212KBITS = 0x01,
|
||||
BITRATE_424KBITS = 0x02,
|
||||
BITRATE_848KBITS = 0x03
|
||||
};
|
||||
|
||||
// Structure to store ISO/IEC 14443-4 ATS
|
||||
typedef struct {
|
||||
byte size;
|
||||
byte fsc; // Frame size for proximity card
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
bool sameD; // Only the same D for both directions supported
|
||||
TagBitRates ds; // Send D
|
||||
TagBitRates dr; // Receive D
|
||||
} ta1;
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
byte fwi; // Frame waiting time integer
|
||||
byte sfgi; // Start-up frame guard time integer
|
||||
} tb1;
|
||||
|
||||
struct {
|
||||
bool transmitted;
|
||||
bool supportsCID;
|
||||
bool supportsNAD;
|
||||
} tc1;
|
||||
|
||||
// Raw data from ATS
|
||||
byte data[FIFO_SIZE - 2]; // ATS cannot be bigger than FSD - 2 bytes (CRC), according to ISO 14443-4 5.2.2
|
||||
} Ats;
|
||||
|
||||
// A struct used for passing the PICC information
|
||||
typedef struct {
|
||||
uint16_t atqa;
|
||||
Uid uid;
|
||||
Ats ats;
|
||||
|
||||
// For Block PCB
|
||||
bool blockNumber;
|
||||
} TagInfo;
|
||||
|
||||
// A struct used for passing PCB Block
|
||||
typedef struct {
|
||||
struct {
|
||||
byte pcb;
|
||||
byte cid;
|
||||
byte nad;
|
||||
} prologue;
|
||||
struct {
|
||||
byte size;
|
||||
byte *data;
|
||||
} inf;
|
||||
} PcbBlock;
|
||||
|
||||
// Member variables
|
||||
TagInfo tag;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with PICCs
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
StatusCode PICC_Select(Uid *uid, byte validBits = 0); // overwrite
|
||||
StatusCode PICC_RequestATS(Ats *ats);
|
||||
StatusCode PICC_PPS(); // PPS command without bitrate parameter
|
||||
StatusCode PICC_PPS(TagBitRates sendBitRate, TagBitRates receiveBitRate); // Different D values
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions for communicating with ISO/IEC 14433-4 cards
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
StatusCode TCL_Transceive(PcbBlock *send, PcbBlock *back);
|
||||
StatusCode TCL_Transceive(TagInfo * tag, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL);
|
||||
StatusCode TCL_TransceiveRBlock(TagInfo *tag, bool ack, byte *backData = NULL, byte *backLen = NULL);
|
||||
StatusCode TCL_Deselect(TagInfo *tag);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Support functions
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
static PICC_Type PICC_GetType(TagInfo *tag);
|
||||
|
||||
// Support functions for debuging
|
||||
void PICC_DumpToSerial(TagInfo *tag);
|
||||
void PICC_DumpDetailsToSerial(TagInfo *tag);
|
||||
void PICC_DumpISO14443_4(TagInfo *tag);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Convenience functions - does not add extra functionality
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
bool PICC_IsNewCardPresent(); // overwrite
|
||||
bool PICC_ReadCardSerial(); // overwrite
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user