[P111] Enable support for configurable SPI bus (and reformat source)

This commit is contained in:
Ton Huisman
2025-08-13 12:18:03 +02:00
parent 9e560d2c52
commit b753fea2ba
5 changed files with 83 additions and 63 deletions
+24 -23
View File
@@ -29,11 +29,12 @@ MFRC522::MFRC522( uint8_t resetPowerDownPin ///< Arduino pin connected to MFRC52
* Prepares the output pins.
*/
MFRC522::MFRC522( uint8_t chipSelectPin, ///< Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
uint8_t resetPowerDownPin ///< Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low). If there is no connection from the CPU to NRSTPD, set this to UINT8_MAX. In this case, only soft reset will be used in PCD_Init().
) {
_chipSelectPin = chipSelectPin;
_resetPowerDownPin = resetPowerDownPin;
} // End constructor
uint8_t resetPowerDownPin, ///< Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low). If there is no connection from the CPU to NRSTPD, set this to UINT8_MAX. In this case, only soft reset will be used in PCD_Init().
SPIClass& spi) :
_chipSelectPin(chipSelectPin),
_resetPowerDownPin(resetPowerDownPin),
_spi(spi)
{} // End constructor
/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522
@@ -46,12 +47,12 @@ MFRC522::MFRC522( uint8_t chipSelectPin, ///< Arduino pin connected to MFRC522'
void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
uint8_t value ///< The value to write.
) {
SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
_spi.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
SPI.transfer(value);
_spi.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
_spi.transfer(value);
digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus
_spi.endTransaction(); // Stop using the SPI bus
} // End PCD_WriteRegister()
/**
@@ -62,14 +63,14 @@ void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to
uint8_t count, ///< The number of bytes to write to the register
uint8_t *values ///< The values to write. Byte array.
) {
SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
_spi.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
_spi.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
for (uint8_t index = 0; index < count; index++) {
SPI.transfer(values[index]);
_spi.transfer(values[index]);
}
digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus
_spi.endTransaction(); // Stop using the SPI bus
} // End PCD_WriteRegister()
/**
@@ -79,12 +80,12 @@ void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to
uint8_t MFRC522::PCD_ReadRegister( PCD_Register reg ///< The register to read from. One of the PCD_Register enums.
) {
uint8_t value;
SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
_spi.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave
SPI.transfer(0x80 | reg); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
value = SPI.transfer(0); // Read the value back. Send 0 to stop reading.
_spi.transfer(0x80 | reg); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
value = _spi.transfer(0); // Read the value back. Send 0 to stop reading.
digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus
_spi.endTransaction(); // Stop using the SPI bus
return value;
} // End PCD_ReadRegister()
@@ -103,26 +104,26 @@ void MFRC522::PCD_ReadRegister( PCD_Register reg, ///< The register to read from
//Serial.print(F("Reading ")); Serial.print(count); Serial.println(F(" bytes from register."));
uint8_t address = 0x80 | reg; // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
uint8_t index = 0; // Index in values array.
SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
_spi.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
digitalWrite(_chipSelectPin, LOW); // Select slave
count--; // One read is performed outside of the loop
SPI.transfer(address); // Tell MFRC522 which address we want to read
_spi.transfer(address); // Tell MFRC522 which address we want to read
if (rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7
uint8_t mask = (0xFF << rxAlign) & 0xFF;
// Read value and tell that we want to read the same address again.
uint8_t value = SPI.transfer(address);
uint8_t value = _spi.transfer(address);
// Apply mask to both current value of values[0] and the new data in value.
values[0] = (values[0] & ~mask) | (value & mask);
index++;
}
while (index < count) {
values[index] = SPI.transfer(address); // Read value and tell that we want to read the same address again.
values[index] = _spi.transfer(address); // Read value and tell that we want to read the same address again.
index++;
}
values[index] = SPI.transfer(0); // Read the final byte. Send 0 to stop reading.
values[index] = _spi.transfer(0); // Read the final byte. Send 0 to stop reading.
digitalWrite(_chipSelectPin, HIGH); // Release slave again
SPI.endTransaction(); // Stop using the SPI bus
_spi.endTransaction(); // Stop using the SPI bus
} // End PCD_ReadRegister()
/**
+2 -1
View File
@@ -293,7 +293,7 @@ public:
/////////////////////////////////////////////////////////////////////////////////////
MFRC522();
MFRC522(uint8_t resetPowerDownPin);
MFRC522(uint8_t chipSelectPin, uint8_t resetPowerDownPin);
MFRC522(uint8_t chipSelectPin, uint8_t resetPowerDownPin, SPIClass& spi = SPI);
virtual ~MFRC522() {};
/////////////////////////////////////////////////////////////////////////////////////
@@ -389,6 +389,7 @@ public:
protected:
uint8_t _chipSelectPin; // Arduino pin connected to MFRC522's SPI slave select input (Pin 24, NSS, active low)
uint8_t _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
SPIClass& _spi = SPI;
StatusCode MIFARE_TwoStepHelper(uint8_t command, uint8_t blockAddr, int32_t data);
};
+4 -1
View File
@@ -6,6 +6,7 @@
// #######################################################################################################
/** Changelog:
* 2025-08-13 tonhuisman: Enable use of secondary SPI bus
* 2025-06-14 tonhuisman: Add support for Custom Value Type per task value
* 2025-01-12 tonhuisman: Add support for MQTT AutoDiscovery (not supported for RFID)
* Update changelog
@@ -45,6 +46,7 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string)
dev.ValueCount = 1;
dev.SendDataOption = true;
dev.CustomVTypeVar = true;
dev.SpiBusSelect = true;
break;
}
@@ -161,7 +163,8 @@ boolean Plugin_111(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_INIT:
{
initPluginTaskData(event->TaskIndex, new (std::nothrow) P111_data_struct(P111_CS_PIN, P111_RST_PIN, P111_IRQ_PIN));
const uint8_t spi_bus = Settings.getSPIBusForTask(event->TaskIndex);
initPluginTaskData(event->TaskIndex, new (std::nothrow) P111_data_struct(P111_CS_PIN, P111_RST_PIN, P111_IRQ_PIN, spi_bus));
P111_data_struct *P111_data = static_cast<P111_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr != P111_data) {
+32 -21
View File
@@ -10,10 +10,11 @@
# include <MFRC522.h>
P111_data_struct::P111_data_struct(int8_t csPin,
int8_t rstPin,
int8_t irqPin)
: mfrc522(nullptr), _csPin(csPin), _rstPin(rstPin), _irqPin(irqPin)
P111_data_struct::P111_data_struct(int8_t csPin,
int8_t rstPin,
int8_t irqPin,
uint8_t spi_bus)
: mfrc522(nullptr), _csPin(csPin), _rstPin(rstPin), _irqPin(irqPin), _spi_bus(spi_bus)
{}
P111_data_struct::~P111_data_struct() {
@@ -28,12 +29,17 @@ P111_data_struct::~P111_data_struct() {
void P111_data_struct::init() {
delete mfrc522;
mfrc522 = new (std::nothrow) MFRC522(_csPin, _rstPin); // Instantiate a MFRC522
// Instantiate a MFRC522
mfrc522 = new (std::nothrow) MFRC522(_csPin, _rstPin
# ifdef ESP32
, 0 == _spi_bus ? SPI : SPI1
# endif // ifdef ESP32
);
if (mfrc522 != nullptr) {
mfrc522->PCD_Init(); // Initialize MFRC522 reader
mfrc522->PCD_Init(); // Initialize MFRC522 reader
mfrc522->PCD_WriteRegister(MFRC522::ComIEnReg, 0b10100000); // enable receiver interrupt
mfrc522->PCD_WriteRegister(MFRC522::DivIEnReg, 0x80); // Set as CMOS output pin
mfrc522->PCD_WriteRegister(MFRC522::DivIEnReg, 0x80); // Set as CMOS output pin
initPhase = P111_initPhases::Ready;
if (validGpio(_irqPin)) {
@@ -134,7 +140,7 @@ bool P111_data_struct::reset(int8_t csPin,
(initPhase == P111_initPhases::Ready)) {
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLogMove(
LOG_LEVEL_INFO,
LOG_LEVEL_INFO,
concat(F("MFRC522: Reset on pin: "), resetPin));
}
@@ -161,9 +167,9 @@ bool P111_data_struct::reset(int8_t csPin,
pinMode(csPin, OUTPUT);
digitalWrite(csPin, LOW);
mfrc522->PCD_Init(csPin, resetPin); // Init MFRC522 module
mfrc522->PCD_Init(csPin, resetPin); // Init MFRC522 module
mfrc522->PCD_WriteRegister(MFRC522::ComIEnReg, 0b10100000); // enable receiver interrupt
mfrc522->PCD_WriteRegister(MFRC522::DivIEnReg, 0x80); // Set as CMOS output pin
mfrc522->PCD_WriteRegister(MFRC522::DivIEnReg, 0x80); // Set as CMOS output pin
// If you set Antenna Gain to Max it will increase reading distance
mfrc522->PCD_SetAntennaGain(mfrc522->RxGain_max);
@@ -232,23 +238,25 @@ uint8_t P111_data_struct::readPassiveTargetID(uint8_t *uid,
*uidLength = 4;
#ifndef BUILD_NO_DEBUG
# ifndef BUILD_NO_DEBUG
if (loglevelActiveFor(LOG_LEVEL_DEBUG))
{
PrintToString p2str;
mfrc522->PICC_DumpToSerial(&(mfrc522->uid), p2str);
if (p2str.length()) {
addLog(LOG_LEVEL_DEBUG, concat(F("MFRC522: "), p2str.get()));
}
}
#endif
# endif // ifndef BUILD_NO_DEBUG
mfrc522->PICC_HaltA(); // Stop reading
return P111_NO_ERROR;
}
void P111_data_struct::mfrc522_interrupt(P111_data_struct * self)
void P111_data_struct::mfrc522_interrupt(P111_data_struct *self)
{
self->_irq_pin_time_micros = getMicros64();
}
@@ -272,11 +280,11 @@ bool P111_data_struct::loop(struct EventStruct *event) {
return success;
}
counter++; // This variable replaces a static variable in the original implementation
const bool ComIrqReg_bits = (mfrc522->PCD_ReadRegister(MFRC522::ComIrqReg) & (1<<5)) != 0;
counter++; // This variable replaces a static variable in the original implementation
const bool ComIrqReg_bits = (mfrc522->PCD_ReadRegister(MFRC522::ComIrqReg) & (1 << 5)) != 0;
mfrc522->PCD_WriteRegister(MFRC522::ComIrqReg, 0x34);
if (counter >= 10 || ComIrqReg_bits) { // Only every 3rd 0.1 second we do a read
if ((counter >= 10) || ComIrqReg_bits) { // Only every 3rd 0.1 second we do a read
counter = 0;
uint32_t key = P111_NO_KEY;
@@ -346,24 +354,28 @@ bool P111_data_struct::plugin_fifty_per_second(struct EventStruct *event) {
}
}
}
if (_irq_pin_time_micros > _last_served_irq_pin_time_micros) {
_last_served_irq_pin_time_micros = _irq_pin_time_micros;
//addLog(LOG_LEVEL_INFO, F("P111: acting on interrupt"));
// addLog(LOG_LEVEL_INFO, F("P111: acting on interrupt"));
loop(event);
}
return true;
}
String P111_data_struct::PCD_getVersion(uint8_t& v) {
v = 0xFF;
if (mfrc522) {
v = mfrc522->PCD_ReadRegister(MFRC522::VersionReg);
if (v != 0xFF && v != 0) {
if ((v != 0xFF) && (v != 0)) {
// Human readable version.
String res = concat(formatToHex(v, 2), F(" = "));
switch(v) {
switch (v) {
case 0xb2:
res += F("FM17522_1");
break;
@@ -395,5 +407,4 @@ String P111_data_struct::PCD_getVersion(uint8_t& v) {
return EMPTY_STRING;
}
#endif // ifdef USES_P111
+21 -17
View File
@@ -6,6 +6,8 @@
# include <MFRC522.h>
# include "../Globals/SPI1.h"
# define P111_CS_PIN PIN(0)
# define P111_RST_PIN PIN(1)
# define P111_IRQ_PIN PIN(2)
@@ -31,15 +33,16 @@ enum class P111_initPhases : uint8_t {
};
struct P111_data_struct : public PluginTaskData_base {
P111_data_struct(int8_t csPin,
int8_t rstPin,
int8_t irqPin);
P111_data_struct(int8_t csPin,
int8_t rstPin,
int8_t irqPin,
uint8_t spi_bus);
P111_data_struct() = delete;
virtual ~P111_data_struct();
void init();
bool plugin_ten_per_second(struct EventStruct *event);
bool plugin_fifty_per_second(struct EventStruct *event);
void init();
bool plugin_ten_per_second(struct EventStruct *event);
bool plugin_fifty_per_second(struct EventStruct *event);
String PCD_getVersion(uint8_t& v);
@@ -51,21 +54,22 @@ private:
uint8_t counter = 0;
String getCardName();
uint8_t readCardStatus(uint32_t *key,
bool *removedTag);
bool reset(int8_t csPin,
int8_t resetPin);
uint8_t readPassiveTargetID(uint8_t *uid,
uint8_t *uidLength);
String getCardName();
uint8_t readCardStatus(uint32_t *key,
bool *removedTag);
bool reset(int8_t csPin,
int8_t resetPin);
uint8_t readPassiveTargetID(uint8_t *uid,
uint8_t *uidLength);
static void mfrc522_interrupt(P111_data_struct * self);
static void mfrc522_interrupt(P111_data_struct *self);
int32_t timeToWait = 0;
int8_t _csPin;
int8_t _rstPin;
int8_t _irqPin;
int8_t _csPin;
int8_t _rstPin;
int8_t _irqPin;
uint8_t _spi_bus;
uint8_t errorCount = 0;
bool removedState = true; // On startup, there will usually not be a tag nearby