Hi,
Im developing NRF52 DK.
I'm building library C SPI mfrc522 for NRF52.
I'm implement PCD_Read and write PCD_register look OK, But i call function PICC_IsNewCardPresent() in main loop not detected NFC tag, nothing happened!!! ????
Help me. I worked for more than 2 weeks but couldn't ~.~
void PCD_WriteRegister(PCD_Register reg, byte value);
void PCD_WriteRegister_long(PCD_Register reg, byte count, byte *values);
byte PCD_ReadRegister(PCD_Register reg);
void PCD_ReadRegister_long(PCD_Register reg, byte count, byte *values, byte rxAlign); //TODO rxAlign = 0
static uint8_t m_tx_buf[2]; /**< TX buffer. */
static uint8_t m_rx_buf[1]; /**< RX buffer. */
static uint8_t m_write_buf[1]; /**< RX buffer. */
static const uint8_t m_length = 1; /**< Transfer length. */
static const uint8_t m_tx_length = 2; /**< Transfer length. */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
spi_xfer_done = true;
// NRF_LOG_INFO("Transfer completed.");
// if (m_rx_buf[0] != 0)
// {
// NRF_LOG_INFO(" Received:");
// NRF_LOG_HEXDUMP_INFO(m_rx_buf,1);
// }
}
void PCD_WriteRegister(PCD_Register reg, byte value){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = reg &0x7E;
m_tx_buf[1] = value;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
void PCD_WriteRegister_long(PCD_Register reg, byte count, byte *values){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = reg & 0x7E;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
for (byte index = 0; index < count; index++) {
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
debug_info("long value[%d]:%x",index,values[index]);
nrf_drv_spi_transfer(&spi, &values[index], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
}
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
byte PCD_ReadRegister(PCD_Register reg){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = (0x80 | (reg & 0x7E));
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
_reg = 0x00;
nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
nrf_gpio_pin_write(SPI_SS_PIN,1);
return m_rx_buf[0];
}
void PCD_ReadRegister_long(PCD_Register reg, byte count, byte *values, byte rxAlign){
nrf_gpio_pin_write(SPI_SS_PIN,0);
if (count == 0) {
return;
}
byte address = 0x80 | (reg& 0x7E); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
byte index = 0;
count--;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
if (rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7
byte mask = (0xFF << rxAlign) & 0xFF;
// Read value and tell that we want to read the same address again.
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
byte value = m_rx_buf[0];
// 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) {
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
values[index] = m_rx_buf[0];
index++;
}
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
uint8_t _reg = 0x00;
nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
values[index] = m_rx_buf[0];
nrf_gpio_pin_write(SPI_SS_PIN,1);
}Im include mfrc522.c mfrc522.h.
#include "mfrc522.h"
#define debug_info(...) NRF_LOG_INFO(__VA_ARGS__)
#define SPI_INSTANCE 0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
static volatile bool spi_xfer_done; /**< Flag used to indicate that SPI instance completed the transfer. */
static uint8_t m_tx_buf[2];// = TEST_STRING; /**< TX buffer. */
static uint8_t m_rx_buf[1]; /**< RX buffer. */
static uint8_t m_write_buf[1]; /**< RX buffer. */
static const uint8_t m_length = 1; /**< Transfer length. */
static const uint8_t m_tx_length = 2; /**< Transfer length. */
/**
* @brief SPI user event handler.
* @param event
*/
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
spi_xfer_done = true;
// NRF_LOG_INFO("Transfer completed.");
// if (m_rx_buf[0] != 0)
// {
// NRF_LOG_INFO(" Received:");
// NRF_LOG_HEXDUMP_INFO(m_rx_buf,1);
// }
}
void PCD_WriteRegister(PCD_Register reg, byte value){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = reg &0x7E;
m_tx_buf[1] = value;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
// m_tx_buf[1] = value;
// memset(m_rx_buf, 0, m_length);
// spi_xfer_done = false;
//
// nrf_drv_spi_transfer(&spi, &m_tx_buf[1], m_length, NULL, 0);
//
// while (!spi_xfer_done)
// {
// __WFE();
// }
// NRF_LOG_FLUSH();
// byte cpm = PCD_ReadRegister(reg);
// if(cpm!=value) debug_info("WTF %x: %x - %x",reg>>1,cpm,value);
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
void PCD_WriteRegister_long(PCD_Register reg, byte count, byte *values){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = reg & 0x7E;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
for (byte index = 0; index < count; index++) {
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi, &values[index], m_length, NULL, 0);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
}
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
byte PCD_ReadRegister(PCD_Register reg){
nrf_gpio_pin_write(SPI_SS_PIN,0);
m_tx_buf[0] = (0x80 | (reg & 0x7E));
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&m_tx_buf[0], m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
uint8_t _reg;
_reg = 0x00;
nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
nrf_gpio_pin_write(SPI_SS_PIN,1);
return m_rx_buf[0];
}
void PCD_ReadRegister_long(PCD_Register reg, byte count, byte *values, byte rxAlign){
nrf_gpio_pin_write(SPI_SS_PIN,0);
if (count == 0) {
return;
}
byte address = 0x80 | (reg& 0x7E); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
byte index = 0;
count--;
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
if (rxAlign) { // Only update bit positions rxAlign..7 in values[0]
// Create bit mask for bit positions rxAlign..7
byte mask = (0xFF << rxAlign) & 0xFF;
// Read value and tell that we want to read the same address again.
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
byte value = m_rx_buf[0];
// 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) {
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi,&address, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
values[index] = m_rx_buf[0];
index++;
}
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
uint8_t _reg = 0x00;
nrf_drv_spi_transfer(&spi,&_reg, m_length, m_rx_buf, m_length);
while (!spi_xfer_done)
{
__WFE();
}
values[index] = m_rx_buf[0];
nrf_gpio_pin_write(SPI_SS_PIN,1);
}
void PCD_ClearRegisterBitMask( PCD_Register reg, ///< The register to update. One of the PCD_Register enums.
byte mask ///< The bits to clear.
) {
byte tmp;
tmp = PCD_ReadRegister(reg);
PCD_WriteRegister(reg, tmp & (~mask)); // clear bit mask
} // End PCD_ClearRegisterBitMask()
void PCD_SetRegisterBitMask( PCD_Register reg, ///< The register to update. One of the PCD_Register enums.
byte mask ///< The bits to set.
) {
byte tmp;
tmp = PCD_ReadRegister(reg);
PCD_WriteRegister(reg, tmp | mask); // set bit mask
} // End PCD_SetRegisterBitMask()
StatusCode PCD_CalculateCRC( byte *data, ///< In: Pointer to the data to transfer to the FIFO for CRC calculation.
byte length, ///< In: The number of bytes to transfer.
byte *result ///< Out: Pointer to result buffer. Result is written to result[0..1], low byte first.
) {
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
PCD_WriteRegister(DivIrqReg, 0x04); // Clear the CRCIRq interrupt request bit
PCD_WriteRegister(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
PCD_WriteRegister_long(FIFODataReg, length, data); // Write data to the FIFO
PCD_WriteRegister(CommandReg, PCD_CalcCRC); // Start the calculation
// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73μs.
// TODO check/modify for other architectures than Arduino Uno 16bit
// Wait for the CRC calculation to complete. Each iteration of the while-loop takes 17.73us.
for (uint16_t i = 5000; i > 0; i--) {
// DivIrqReg[7..0] bits are: Set2 reserved reserved MfinActIRq reserved CRCIRq reserved reserved
byte n = PCD_ReadRegister(DivIrqReg);
if (n & 0x04) { // CRCIRq bit set - calculation done
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// Transfer the result from the registers to the result buffer
result[0] = PCD_ReadRegister(CRCResultRegL);
result[1] = PCD_ReadRegister(CRCResultRegH);
return STATUS_OK;
}
}
// 89ms passed and nothing happend. Communication with the MFRC522 might be down.
return STATUS_TIMEOUT;
} // End PCD_CalculateCRC()
void PCD_AntennaOn() {
uint8_t value = PCD_ReadRegister(TxControlReg);
if ((value & 0x03) != 0x03) {
PCD_WriteRegister(TxControlReg, value | 0x03);
value = PCD_ReadRegister(TxControlReg);
}
} // End PCD_AntennaOn()
StatusCode PICC_RequestA(byte *bufferATQA, ///< The buffer to store the ATQA (Answer to request) in
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
) {
return PICC_REQA_or_WUPA(PICC_CMD_REQA, bufferATQA, bufferSize);
} // End PICC_RequestA()
void printf_value(uint8_t count, uint8_t *values){
for (uint8_t index = 0; index < count; index++) {
debug_info("%p - %x\n",&values[index],values[index]);
}
}
StatusCode PCD_CommunicateWithPICC( byte command, ///< The command to execute. One of the PCD_Command enums.
byte waitIRq, ///< The bits in the ComIrqReg register that signals successful completion of the command.
byte *sendData, ///< Pointer to the data to transfer to the FIFO.
byte sendLen, ///< Number of bytes to transfer to the FIFO.
byte *backData, ///< nullptr or pointer to buffer if data should be read back after executing the command.
byte *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
byte *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits.
byte rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
bool checkCRC ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
) {
// Prepare values for BitFramingReg
byte txLastBits = validBits ? *validBits : 0;
byte bitFraming = (rxAlign << 4) + txLastBits; // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0]
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop any active command.
byte mcmd = PCD_ReadRegister(CommandReg);
PCD_WriteRegister(ComIrqReg, 0x7F); // Clear all seven interrupt request bits
PCD_WriteRegister(FIFOLevelReg, 0x80); // FlushBuffer = 1, FIFO initialization
PCD_WriteRegister_long(FIFODataReg, sendLen, sendData); // Write sendData to the FIFO
PCD_WriteRegister(BitFramingReg, bitFraming); // Bit adjustments
PCD_WriteRegister(CommandReg, command); // Execute the command
if (command == PCD_Transceive) {
PCD_SetRegisterBitMask(BitFramingReg, 0x80); // StartSend=1, transmission of data starts
}
// Wait for the command to complete.
// In PCD_Init() we set the TAuto flag in TModeReg. This means the timer automatically starts when the PCD stops transmitting.
// Each iteration of the do-while-loop takes 17.86μs.
// TODO check/modify for other architectures than Arduino Uno 16bit
uint16_t i;
for (i = 2000; i > 0; i--) {
byte n = PCD_ReadRegister(ComIrqReg); // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq HiAlertIRq LoAlertIRq ErrIRq TimerIRq
// debug_info("n:%x",n);
if (n & waitIRq) { // One of the interrupts that signal success has been set.
break;
}
if (n & 0x01) { // Timer interrupt - nothing received in 25ms
return STATUS_TIMEOUT;
}
}
// 35.7ms and nothing happend. Communication with the MFRC522 might be down.
if (i == 0) {
debug_info("STATUS_TIMEOUT2");
return STATUS_TIMEOUT;
}
// Stop now if any errors except collisions were detected.
byte errorRegValue = PCD_ReadRegister(ErrorReg); // ErrorReg[7..0] bits are: WrErr TempErr reserved BufferOvfl CollErr CRCErr ParityErr ProtocolErr
if (errorRegValue & 0x13) { // BufferOvfl ParityErr ProtocolErr
return STATUS_ERROR;
}
byte _validBits = 0;
// 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) {
return STATUS_NO_ROOM;
}
*backLen = n; // Number of bytes returned
PCD_ReadRegister_long(FIFODataReg, n, backData, rxAlign); // Get received data from FIFO
_validBits = PCD_ReadRegister(ControlReg) & 0x07; // RxLastBits[2:0] indicates the number of valid bits in the last received byte. If this value is 000b, the whole byte is valid.
if (validBits) {
*validBits = _validBits;
}
}
// Tell about collisions
if (errorRegValue & 0x08) { // CollErr
return STATUS_COLLISION;
}
// Perform CRC_A validation if requested.
if (backData && backLen && checkCRC) {
// In this case a MIFARE Classic NAK is not OK.
if (*backLen == 1 && _validBits == 4) {
return STATUS_MIFARE_NACK;
}
// We need at least the CRC_A value and all 8 bits of the last byte must be received.
if (*backLen < 2 || _validBits != 0) {
return STATUS_CRC_WRONG;
}
// Verify CRC_A - do our own calculation and store the control in controlBuffer.
byte controlBuffer[2];
StatusCode status = PCD_CalculateCRC(&backData[0], *backLen - 2, &controlBuffer[0]);
if (status != STATUS_OK) {
return status;
}
if ((backData[*backLen - 2] != controlBuffer[0]) || (backData[*backLen - 1] != controlBuffer[1])) {
return STATUS_CRC_WRONG;
}
}
return STATUS_OK;
} // End PCD_CommunicateWithPICC()
StatusCode PCD_TransceiveData( byte *sendData, ///< Pointer to the data to transfer to the FIFO.
byte sendLen, ///< Number of bytes to transfer to the FIFO.
byte *backData, ///< nullptr or pointer to buffer if data should be read back after executing the command.
byte *backLen, ///< In: Max number of bytes to write to *backData. Out: The number of bytes returned.
byte *validBits, ///< In/Out: The number of valid bits in the last byte. 0 for 8 valid bits. Default nullptr.
byte rxAlign, ///< In: Defines the bit position in backData[0] for the first bit received. Default 0.
bool checkCRC ///< In: True => The last two bytes of the response is assumed to be a CRC_A that must be validated.
) {
byte waitIRq = 0x30; // RxIRq and IdleIRq
return PCD_CommunicateWithPICC(PCD_Transceive, waitIRq, sendData, sendLen, backData, backLen, validBits, rxAlign, checkCRC);
} // End PCD_TransceiveData()
StatusCode PICC_REQA_or_WUPA( byte command, ///< The command to send - PICC_CMD_REQA or PICC_CMD_WUPA
byte *bufferATQA, ///< The buffer to store the ATQA (Answer to request) in
byte *bufferSize ///< Buffer size, at least two bytes. Also number of bytes returned if STATUS_OK.
) {
byte validBits;
StatusCode status;
if (bufferATQA == NULL || *bufferSize < 2) { // The ATQA response is 2 bytes long.
return STATUS_NO_ROOM;
}
PCD_ClearRegisterBitMask(CollReg, 0x80); // ValuesAfterColl=1 => Bits received after collision are cleared.
validBits = 7; // For REQA and WUPA we need the short frame format - transmit only 7 bits of the last (and only) byte. TxLastBits = BitFramingReg[2..0]
status = PCD_TransceiveData(&command, 1, bufferATQA, bufferSize, &validBits,0,false);
if (status != STATUS_OK) {
return status;
}
if (*bufferSize != 2 || validBits != 0) { // ATQA must be exactly 16 bits.
return STATUS_ERROR;
}
return STATUS_OK;
} // End PICC_REQA_or_WUPA()
bool PICC_IsNewCardPresent() {
byte bufferATQA[2];
byte bufferSize = sizeof(bufferATQA);
// Reset baud rates
PCD_WriteRegister(TxModeReg, 0x00);
PCD_WriteRegister(RxModeReg, 0x00);
// Reset ModWidthReg
PCD_WriteRegister(ModWidthReg, 0x26);
StatusCode result = PICC_RequestA(bufferATQA, &bufferSize);
debug_info("result:%x",result);
return (result == STATUS_OK || result == STATUS_COLLISION);
} // End PICC_IsNewCardPresent()
void PCD_Reset() {
PCD_WriteRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
// The datasheet does not mention how long the SoftRest command takes to complete.
// But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
// Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74μs. Let us be generous: 50ms.
uint8_t count = 0;
do {
// Wait for the PowerDown bit in CommandReg to be cleared (max 3x50ms)
nrf_delay_ms(50);
} while ((PCD_ReadRegister(CommandReg) & (1 << 4)) && (++count) < 3);
} // End PCD_Reset()
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
bool PCD_PerformSelfTest() {
// This follows directly the steps outlined in 16.1.1
// 1. Perform a soft reset.
PCD_Reset();
// 2. Clear the internal buffer by writing 25 bytes of 00h
byte ZEROES[25] = {0x00};
PCD_WriteRegister(FIFOLevelReg, 0x80); // flush the FIFO buffer
PCD_WriteRegister_long(FIFODataReg, 25, ZEROES); // write 25 bytes of 00h to FIFO
PCD_WriteRegister(CommandReg, PCD_Mem); // transfer to internal buffer
// 3. Enable self-test
PCD_WriteRegister(AutoTestReg, 0x09);
// 4. Write 00h to FIFO buffer
PCD_WriteRegister(FIFODataReg, 0x00);
// 5. Start self-test by issuing the CalcCRC command
PCD_WriteRegister(CommandReg, PCD_CalcCRC);
// 6. Wait for self-test to complete
byte n;
for (uint8_t i = 0; i < 0xFF; i++) {
// The datasheet does not specify exact completion condition except
// that FIFO buffer should contain 64 bytes.
// While selftest is initiated by CalcCRC command
// it behaves differently from normal CRC computation,
// so one can't reliably use DivIrqReg to check for completion.
// It is reported that some devices does not trigger CRCIRq flag
// during selftest.
n = PCD_ReadRegister(FIFOLevelReg);
if (n >= 64) {
debug_info("nnn:%x",n);
NRF_LOG_FLUSH();
break;
}
}
PCD_WriteRegister(CommandReg, PCD_Idle); // Stop calculating CRC for new content in the FIFO.
// 7. Read out resulting 64 bytes from the FIFO buffer.
byte result[64];
PCD_ReadRegister_long(FIFODataReg, 64, result, 0);
// Auto self-test done
// Reset AutoTestReg register to be 0 again. Required for normal operation.
PCD_WriteRegister(AutoTestReg, 0x00);
// Determine firmware version (see section 9.3.4.8 in spec)
byte version = PCD_ReadRegister(VersionReg);
// Pick the appropriate reference values
const byte *reference;
debug_info("version:%x",version);
// Verify that the results match up to our expectations
for (uint8_t i = 0; i < 64; i++) {
debug_info("result[%d]:%x",i,result[i]);
NRF_LOG_FLUSH();
// if (result[i] != pgm_read_byte(&(reference[i]))) {
// return false;
// }
}
debug_info("Test passed; all is good");
// Test passed; all is good.
return true;
} // End PCD_PerformSelfTest()
void mfrc522_init()
{
nrf_gpio_cfg_output(SPI_SS_PIN);
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.ss_pin = SPI_SS_PIN;
spi_config.miso_pin = SPI_MISO_PIN;
spi_config.mosi_pin = SPI_MOSI_PIN;
spi_config.sck_pin = SPI_SCK_PIN;
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
PCD_Reset();
uint8_t v = PCD_ReadRegister(VersionReg);
NRF_LOG_INFO("version:%x",v);
// Reset baud rates
PCD_WriteRegister(TxModeReg, 0x00);
PCD_WriteRegister(RxModeReg, 0x00);
// Reset ModWidthReg
PCD_WriteRegister(ModWidthReg, 0x26);
// When communicating with a PICC we need a timeout if something goes wrong.
// f_timer = 13.56 MHz / (2*TPreScaler+1) where TPreScaler = [TPrescaler_Hi:TPrescaler_Lo].
// TPrescaler_Hi are the four low bits in TModeReg. TPrescaler_Lo is TPrescalerReg.
PCD_WriteRegister(TModeReg, 0x80); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
v=PCD_ReadRegister(TModeReg);
NRF_LOG_INFO("TModeReg:%x",v);
PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
v=PCD_ReadRegister(TPrescalerReg);
NRF_LOG_INFO("TPrescalerReg:%x",v);
PCD_WriteRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25μs.
v=PCD_ReadRegister(TPrescalerReg);
NRF_LOG_INFO("TPrescalerReg:%x",v);
PCD_WriteRegister(TReloadRegH, 0x04); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
PCD_WriteRegister(TReloadRegL, 0xE8);
PCD_WriteRegister(TxASKReg, 0x40); // Default 0x00. Force a 100 % ASK modulation independent of the register setting
PCD_WriteRegister(ModeReg, 0x3D); // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
PCD_AntennaOn();
NRF_LOG_FLUSH();
}