Skip to content
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ If you got a bad board and you can tell us how to detect those boards (silk, chi
* Use of IRQ pin. But there is a proof-of-concept example.
* With Intel Galileo (Gen2) see [#310](https://github.com/miguelbalboa/rfid/issues/310), not supported by software.
* Power reduction modes [#269](https://github.com/miguelbalboa/rfid/issues/269), not supported by software.
* UART instead of SPI [#281](https://github.com/miguelbalboa/rfid/issues/281), not supported by software.

* **Need more?**

Expand Down
67 changes: 67 additions & 0 deletions examples/CustomUART/CustomUART.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <Arduino.h>
#include "MFRC522v2.h"
#include "MFRC522DriverPinSimple.h"
#include "MFRC522Debug.h"
#include "MFRC522DriverUART.h"
#include "MFRC522DriverSPI.h"

// This exampe was tested with an ESP32.
// It needs the following wiring (which can be fully customized due to the powerful pinmux of the ESP32):
// RC-522 module | ESP32
// SDA (RX) | 22 (txPin)
// MISO (TX) | 23 (rxPin)
// RESET | 21
//
// Don't forget to modify the RC-522: Disconnect the EA pin (32) from Vcc and wire it to GND.
// See RC522-UART-mod.jpg for reference.

MFRC522DriverUART driver{Serial1}; // Create UART driver.

MFRC522 mfrc522{driver}; // Create MFRC522 instance.

#define RESET_PIN 21

void setup()
{
pinMode(RESET_PIN, OUTPUT);
digitalWrite(RESET_PIN, LOW); // power down
delay(100);
digitalWrite(RESET_PIN, HIGH); // Reset by positive edge.
//--- Start serial
Serial.begin (115200) ;
#ifdef ESP32
Serial1.begin(9600, SERIAL_8N1, /* rxPin */ 23, /* txPin */ 22);
#else
// AVR does not support specifying of the pins when initializing a Serial device.
Serial1.begin(9600, SERIAL_8N1);
#endif
//--- Wait for serial (blink led at 10 Hz during waiting)
while (!Serial) {
delay (50) ;
}

while (!Serial1) {
delay (50) ;
}

delay(1000);

driver.PCD_ReadRegister(MFRC522Constants::PCD_Register::VersionReg);
mfrc522.PCD_Init(); // Init MFRC522 board.
MFRC522Debug::PCD_DumpVersionToSerial(mfrc522, Serial); // Show details of PCD - MFRC522 Card Reader details.

Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop()
{
Serial.println("Checking for card...");
if ( mfrc522.PICC_IsNewCardPresent())
{
Serial.println("Card present.");
if (mfrc522.PICC_ReadCardSerial()) {
MFRC522Debug::PICC_DumpToSerial(mfrc522, Serial, &(mfrc522.uid));
}
}
delay(1000);
}
Binary file added examples/CustomUART/RC522-UART-mod.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions src/MFRC522Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,61 @@ void MFRC522Debug::PICC_DumpMifareUltralightToSerial(MFRC522 &device, Print &log
}
}
} // End PICC_DumpMifareUltralightToSerial()

String MFRC522Debug::toString(PCD_Register reg)
{
switch(reg)
{
case PCD_Register::CommandReg : return "CommandReg ";
case PCD_Register::ComIEnReg : return "ComIEnReg ";
case PCD_Register::DivIEnReg : return "DivIEnReg ";
case PCD_Register::ComIrqReg : return "ComIrqReg ";
case PCD_Register::DivIrqReg : return "DivIrqReg ";
case PCD_Register::ErrorReg : return "ErrorReg ";
case PCD_Register::Status1Reg : return "Status1Reg ";
case PCD_Register::Status2Reg : return "Status2Reg ";
case PCD_Register::FIFODataReg : return "FIFODataReg ";
case PCD_Register::FIFOLevelReg : return "FIFOLevelReg ";
case PCD_Register::WaterLevelReg : return "WaterLevelReg ";
case PCD_Register::ControlReg : return "ControlReg ";
case PCD_Register::BitFramingReg : return "BitFramingReg ";
case PCD_Register::CollReg : return "CollReg ";
case PCD_Register::ModeReg : return "ModeReg ";
case PCD_Register::TxModeReg : return "TxModeReg ";
case PCD_Register::RxModeReg : return "RxModeReg ";
case PCD_Register::TxControlReg : return "TxControlReg ";
case PCD_Register::TxASKReg : return "TxASKReg ";
case PCD_Register::TxSelReg : return "TxSelReg ";
case PCD_Register::RxSelReg : return "RxSelReg ";
case PCD_Register::RxThresholdReg : return "RxThresholdReg ";
case PCD_Register::DemodReg : return "DemodReg ";
case PCD_Register::MfTxReg : return "MfTxReg ";
case PCD_Register::MfRxReg : return "MfRxReg ";
case PCD_Register::SerialSpeedReg : return "SerialSpeedReg ";
case PCD_Register::CRCResultRegH : return "CRCResultRegH ";
case PCD_Register::CRCResultRegL : return "CRCResultRegL ";
case PCD_Register::ModWidthReg : return "ModWidthReg ";
case PCD_Register::RFCfgReg : return "RFCfgReg ";
case PCD_Register::GsNReg : return "GsNReg ";
case PCD_Register::CWGsPReg : return "CWGsPReg ";
case PCD_Register::ModGsPReg : return "ModGsPReg ";
case PCD_Register::TModeReg : return "TModeReg ";
case PCD_Register::TPrescalerReg : return "TPrescalerReg ";
case PCD_Register::TReloadRegH : return "TReloadRegH ";
case PCD_Register::TReloadRegL : return "TReloadRegL ";
case PCD_Register::TCounterValueRegH : return "TCounterValueRegH";
case PCD_Register::TCounterValueRegL : return "TCounterValueRegL";
case PCD_Register::TestSel1Reg : return "TestSel1Reg ";
case PCD_Register::TestSel2Reg : return "TestSel2Reg ";
case PCD_Register::TestPinEnReg : return "TestPinEnReg ";
case PCD_Register::TestPinValueReg : return "TestPinValueReg ";
case PCD_Register::TestBusReg : return "TestBusReg ";
case PCD_Register::AutoTestReg : return "AutoTestReg ";
case PCD_Register::VersionReg : return "VersionReg ";
case PCD_Register::AnalogTestReg : return "AnalogTestReg ";
case PCD_Register::TestDAC1Reg : return "TestDAC1Reg ";
case PCD_Register::TestDAC2Reg : return "TestDAC2Reg ";
case PCD_Register::TestADCReg : return "TestADCReg ";
default : return String("Unknown Register: ") + reg;
}
}
3 changes: 3 additions & 0 deletions src/MFRC522Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class MFRC522Debug {
using PCD_Version = MFRC522Constants::PCD_Version;
using Uid = MFRC522Constants::Uid;
using MIFARE_Key = MFRC522Constants::MIFARE_Key;
using PCD_Register = MFRC522Constants::PCD_Register;

public:
// Get human readable code and type
Expand All @@ -30,4 +31,6 @@ class MFRC522Debug {
static void PICC_DumpMifareClassicToSerial(MFRC522 &device, Print &logPrint, Uid *uid, PICC_Type piccType, MIFARE_Key *key);
static void PICC_DumpMifareClassicSectorToSerial(MFRC522 &device, Print &logPrint, Uid *uid, MIFARE_Key *key, byte sector);
static void PICC_DumpMifareUltralightToSerial(MFRC522 &device, Print &logPrint);

static String toString(PCD_Register reg);
};
90 changes: 90 additions & 0 deletions src/MFRC522DriverUART.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: LGPL-2.1 */
#include "MFRC522Debug.h"
#include "MFRC522DriverUART.h"

/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522DriverUART
/////////////////////////////////////////////////////////////////////////////////////

bool MFRC522DriverUART::init() {
// Surrounding code should initialize the serial port.
_serial.setTimeout(10);
return true;
}

/**
* Writes a byte to the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.4.
*/
void MFRC522DriverUART::PCD_WriteRegister(const PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
const byte value ///< The value to write.
) {
// PCD_ReadRegister(reg);
_serial.write(reg);
// read back the echoes address:
byte readBack = 0xff;
_serial.readBytes(&readBack, 1);
_serial.write(value);
} // End PCD_WriteRegister().

/**
* Writes a number of bytes to the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.4.
*/
void MFRC522DriverUART::PCD_WriteRegister(const MFRC522Constants::PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
const byte count, ///< The number of bytes to write to the register.
byte *const values ///< The values to write. Byte array.
) {
for (byte i = 0; i < count; i++)
{
PCD_WriteRegister(reg, values[i]);
}
} // End PCD_WriteRegister()

/**
* Reads a byte from the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.4.
*/
byte MFRC522DriverUART::PCD_ReadRegister(const PCD_Register reg ///< The register to read from. One of the PCD_Register enums.
) {
byte value = 0;
byte regRead = reg | 0xC0;
_serial.write(regRead);
_serial.readBytes(&value, 1);
return value;
} // End PCD_ReadRegister()

/**
* Reads a number of bytes from the specified register in the MFRC522 chip.
* The interface is described in the datasheet section 8.1.2.
*/
void MFRC522DriverUART::PCD_ReadRegister(const PCD_Register reg, ///< The register to read from. One of the PCD_Register enums.
const byte count, ///< The number of bytes to read.
byte *const values, ///< Byte array to store the values in.
const byte rxAlign ///< Only bit positions rxAlign..7 in values[0] are updated.
) {
// Sanity check.
if(count == 0 || values == nullptr) {
return;
}

byte index = 0;

while(index < count) {
if(index == 0 && rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7
byte mask = 0;

for(byte i = rxAlign; i <= 7; i++) {
mask |= (1 << i);
}
byte value = PCD_ReadRegister(reg);

// Apply mask to both current value of values[0] and the new data in value.
values[0] = (values[index] & ~mask) | (value & mask);
} else { // Normal case
values[index] = PCD_ReadRegister(reg);
}
index++;
}
} // End PCD_ReadRegister()
32 changes: 32 additions & 0 deletions src/MFRC522DriverUART.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* SPDX-License-Identifier: LGPL-2.1 */
#pragma once

#include <Stream.h>
#include <MFRC522Driver.h>

class MFRC522DriverUART : public MFRC522Driver {
public:
//using PCD_Register = MFRC522Constants::PCD_Register;
/////////////////////////////////////////////////////////////////////////////////////
// Functions for setting up the Arduino.
/////////////////////////////////////////////////////////////////////////////////////

bool init() override;

/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522.
/////////////////////////////////////////////////////////////////////////////////////
void PCD_WriteRegister(const PCD_Register reg, const byte value) override;
void PCD_WriteRegister(const PCD_Register reg, const byte count, byte *const values) override;
byte PCD_ReadRegister(const PCD_Register reg) override;
void PCD_ReadRegister(const PCD_Register reg, const byte count, byte *const values, const byte rxAlign = 0) override;


MFRC522DriverUART(Stream& serial) :
MFRC522Driver(),
_serial(serial)
{}

protected:
Stream& _serial;
};