I need to implement nRF52833 with RFID-RC522 connected by SPI port using the SDK v2.4.2

Hi

It's my first experience with nordic.  I need to implement nfr 52833 with RFID-RC522 connected by SPI port. Does anyone have an example to start using the SPI port in SDK 2.4.2 ?
On the other hand, I have found in the devZone two libraries mfrc522.c and mfrc522.h used for SDK v17. Can I implement these libraries in the newest SDK 2.4.2 ?

#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();

#include "nrf_drv_spi.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
typedef uint8_t byte;
typedef uint8_t PCD_Register;
typedef uint8_t PCD_Command;
typedef uint8_t PCD_RxGain;
typedef uint8_t PICC_Command;
typedef uint8_t PICC_Type;
typedef uint8_t StatusCode;
typedef uint8_t MIFARE_Misc; 
		// Page 0: Command and status
		//						  0x00			// reserved for future use
#define		CommandReg				(0x01 << 1)// starts and stops command execution
#define		ComIEnReg				(0x02 << 1)// enable and disable interrupt request control bits
#define		DivIEnReg				(0x03 << 1)// enable and disable interrupt request control bits
#define		ComIrqReg				(0x04 << 1)// interrupt request bits
#define		DivIrqReg				(0x05 << 1)// interrupt request bits
#define		ErrorReg				(0x06 << 1)// error bits showing the error status of the last command executed 
#define		Status1Reg				(0x07 << 1)// communication status bits
#define		Status2Reg				(0x08 << 1)// receiver and transmitter status bits
#define		FIFODataReg				(0x09 << 1)// input and output of 64 byte FIFO buffer
#define		FIFOLevelReg                            (0x0A << 1)// number of bytes stored in the FIFO buffer
#define		WaterLevelReg                           (0x0B << 1)// level for FIFO underflow and overflow warning
#define		ControlReg				(0x0C << 1)// miscellaneous control registers
#define		BitFramingReg                           (0x0D << 1)// adjustments for bit-oriented frames
#define		CollReg					(0x0E << 1)// bit position of the first bit-collision detected on the RF interface
		//						  0x0F			// reserved for future use
		
		// Page 1: Command
		// 						  0x10			// reserved for future use
#define		ModeReg					(0x11 << 1)// defines general modes for transmitting and receiving 
#define		TxModeReg				(0x12 << 1)// defines transmission data rate and framing
#define		RxModeReg				(0x13 << 1)// defines reception data rate and framing
#define		TxControlReg                            (0x14 << 1)// controls the logical behavior of the antenna driver pins TX1 and TX2
#define		TxASKReg				(0x15 << 1)// controls the setting of the transmission modulation
#define		TxSelReg				(0x16 << 1)// selects the internal sources for the antenna driver
#define		RxSelReg				(0x17 << 1)// selects internal receiver settings
#define		RxThresholdReg                          (0x18 << 1)// selects thresholds for the bit decoder
#define		DemodReg				(0x19 << 1)// defines demodulator settings
		// 						  0x1A			// reserved for future use
		// 						  0x1B			// reserved for future use
#define		MfTxReg					(0x1C << 1)// controls some MIFARE communication transmit parameters
#define		MfRxReg					(0x1D << 1)// controls some MIFARE communication receive parameters
		// 						  0x1E			// reserved for future use
#define		SerialSpeedReg                          (0x1F << 1)// selects the speed of the serial UART interface
		
		// Page 2: Configuration
		// 						  0x20			// reserved for future use
#define		CRCResultRegH                           (0x21 << 1)// shows the MSB and LSB values of the CRC calculation
#define		CRCResultRegL                           (0x22 << 1)
		// 						  0x23			// reserved for future use
#define		ModWidthReg				(0x24 << 1)// controls the ModWidth setting?
		// 						  0x25			// reserved for future use
#define		RFCfgReg				(0x26 << 1)// configures the receiver gain
#define		GsNReg					(0x27 << 1)// selects the conductance of the antenna driver pins TX1 and TX2 for modulation 
#define		CWGsPReg				(0x28 << 1)// defines the conductance of the p-driver output during periods of no modulation
#define		ModGsPReg				(0x29 << 1)// defines the conductance of the p-driver output during periods of modulation
#define		TModeReg				(0x2A << 1)// defines settings for the internal timer
#define		TPrescalerReg                           (0x2B << 1)// the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
#define         TReloadRegH                             (0x2C << 1)//1 defines the 16-bit timer reload value
#define		TReloadRegL				(0x2D << 1)//2
#define		TCounterValueRegH                       (0x2E << 1)// shows the 16-bit timer value
#define		TCounterValueRegL                       (0x2F << 1)
		
		// Page 3: Test Registers
		// 						  0x30			// reserved for future use
#define		TestSel1Reg				(0x31 << 1)// general test signal configuration
#define		TestSel2Reg				(0x32 << 1)// general test signal configuration
#define		TestPinEnReg                            (0x33 << 1)// enables pin output driver on pins D1 to D7
#define		TestPinValueReg                         (0x34 << 1)// defines the values for D1 to D7 when it is used as an I/O bus
#define		TestBusReg				(0x35 << 1)// shows the status of the internal test bus
#define		AutoTestReg				(0x36 << 1)// controls the digital self-test
#define		VersionReg				(0x37 << 1)// shows the software version
#define		AnalogTestReg                           (0x38 << 1)// controls the pins AUX1 and AUX2
#define		TestDAC1Reg				(0x39 << 1)// defines the test value for TestDAC1
#define		TestDAC2Reg				(0x3A << 1)// defines the test value for TestDAC2
#define		TestADCReg				(0x3B << 1		// shows the value of ADC I and Q channels
		// 						  0x3C			// reserved for production tests
		// 						  0x3D			// reserved for production tests
		// 						  0x3E			// reserved for production tests
		// 						  0x3F			// reserved for production tests


#define		PCD_Idle				(0x00)	// no action, cancels current command execution
#define         PCD_Mem					(0x01)	// stores 25 bytes into the internal buffer
#define		PCD_GenerateRandomID                    (0x02)	// generates a 10-byte random ID number
#define		PCD_CalcCRC				(0x03)	// activates the CRC coprocessor or performs a self-test
#define		PCD_Transmit                            (0x04)	// transmits data from the FIFO buffer
#define		PCD_NoCmdChange                         (0x07)	// no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
#define		PCD_Receive				(0x08)	// activates the receiver circuits
#define		PCD_Transceive                          (0x0C)	// transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
#define		PCD_MFAuthent                           (0x0E)	// performs the MIFARE standard authentication as a reader
#define		PCD_SoftReset                           (0x0F)		// resets the MFRC522



#define		RxGain_18dB				(0x00 << 4)// 000b - 18 dB, minimum
#define		RxGain_23dB				(0x01 << 4)// 001b - 23 dB
#define		RxGain_18dB_2                           (0x02 << 4)// 010b - 18 dB, it seems 010b is a duplicate for 000b
#define		RxGain_23dB_2                           (0x03 << 4)// 011b - 23 dB, it seems 011b is a duplicate for 001b
#define		RxGain_33dB				(0x04 << 4)// 100b - 33 dB, average, and typical default
#define		RxGain_38dB				(0x05 << 4)// 101b - 38 dB
#define		RxGain_43dB				(0x06 << 4)// 110b - 43 dB
#define		RxGain_48dB				(0x07 << 4)// 111b - 48 dB, maximum
#define		RxGain_min				(0x00 << 4)// 000b - 18 dB, minimum, convenience for RxGain_18dB
#define		RxGain_avg				(0x04 << 4)// 100b - 33 dB, average, convenience for RxGain_33dB
#define		RxGain_max				(0x07 << 4		// 111b - 48 dB, maximum, convenience for RxGain_48dB

#define         PICC_CMD_REQA			(0x26)	// REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
#define		PICC_CMD_WUPA			(0x52)	// 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.
#define		PICC_CMD_CT			(0x88)	// Cascade Tag. Not really a command, but used during anti collision.
#define		PICC_CMD_SEL_CL1		(0x93)	// Anti collision/Select, Cascade Level 1
#define		PICC_CMD_SEL_CL2		(0x95)	// Anti collision/Select, Cascade Level 2
#define		PICC_CMD_SEL_CL3		(0x97)	// Anti collision/Select, Cascade Level 3
#define		PICC_CMD_HLTA			(0x50)	// HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
#define		PICC_CMD_RATS           (0xE0,     // Request command for Answer To Reset.
// The commands used for MIFARE Classic (from http://www.mouser.com/ds/2/302/MF1S503x-89574.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.
#define		PICC_CMD_MF_AUTH_KEY_A	(0x60)	// Perform authentication with Key A
#define		PICC_CMD_MF_AUTH_KEY_B	(0x61)	// Perform authentication with Key B
#define		PICC_CMD_MF_READ		(0x30)	// Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
#define		PICC_CMD_MF_WRITE		(0xA0)	// Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
#define		PICC_CMD_MF_DECREMENT	(0xC0)	// Decrements the contents of a block and stores the result in the internal data register.
#define	PICC_CMD_MF_INCREMENT           (0xC1)	// Increments the contents of a block and stores the result in the internal data register.
#define	PICC_CMD_MF_RESTORE		(0xC2)	// Reads the contents of a block into the internal data register.
#define	PICC_CMD_MF_TRANSFER            (0xB0)	// Writes the contents of the internal data register to a block.
        // 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.
#define	PICC_CMD_UL_WRITE		(0xA2		// Writes one 4 byte page to the PICC.
	
#define PICC_TYPE_UNKNOWN		(0x00)
#define	PICC_TYPE_ISO_14443_4           (0x01)// PICC compliant with ISO/IEC 14443-4 
#define	PICC_TYPE_ISO_18092		(0x02) 	// PICC compliant with ISO/IEC 18092 (NFC)
#define	PICC_TYPE_MIFARE_MINI           (0x03)// MIFARE Classic protocol, 320 bytes
#define	PICC_TYPE_MIFARE_1K		(0x04)// MIFARE Classic protocol, 1KB
#define	PICC_TYPE_MIFARE_4K		(0x05)// MIFARE Classic protocol, 4KB
#define	PICC_TYPE_MIFARE_UL		(0x06)// MIFARE Ultralight or Ultralight C
#define	PICC_TYPE_MIFARE_PLUS           (0x07)// MIFARE Plus
#define	PICC_TYPE_MIFARE_DESFIRE        (0x08)// MIFARE DESFire
#define	PICC_TYPE_TNP3XXX		(0x09)// Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
#define	PICC_TYPE_NOT_COMPLETE          (0xff)	// SAK indicates UID is not complete.

#define	STATUS_OK			(0x00)// Success
#define	STATUS_ERROR			(0x01)// Error in communication
#define	STATUS_COLLISION		(0x02)// Collission detected
#define	STATUS_TIMEOUT			(0x03)// Timeout in communication.
#define	STATUS_NO_ROOM			(0x04)// A buffer is not big enough.
#define	STATUS_INTERNAL_ERROR           (0x05)// Internal error in the code. Should not happen ;-)
#define	STATUS_INVALID			(0x06)// Invalid argument.
#define	STATUS_CRC_WRONG		(0x07)// The CRC_A does not match
#define	STATUS_MIFARE_NACK		(0xff)	// A MIFARE PICC responded with NAK.

#define		MF_ACK					(0xA)		// The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
#define		MF_KEY_SIZE				(6)			// A Mifare Crypto1 key is 6 bytes.
// A struct used for passing the UID of a PICC.
typedef struct {
        byte		size;			// Number of bytes in the UID. 4, 7 or 10.
        byte		uidByte[10];
        byte		sak;			// The SAK (Select acknowledge) byte returned from the PICC after successful selection.
} Uid;

// A struct used for passing a MIFARE Crypto1 key
typedef struct {
        byte		keyByte[MF_KEY_SIZE];
} MIFARE_Key;
/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
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
void PCD_SetRegisterBitMask(PCD_Register reg, byte mask);
void PCD_ClearRegisterBitMask(PCD_Register reg, byte mask);
StatusCode PCD_CalculateCRC(byte *data, byte length, byte *result);
/////////////////////////////////////////////////////////////////////////////////////
// Functions for manipulating the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_Init();
void PCD_Reset();
void PCD_AntennaOn();
void PCD_AntennaOff();
byte PCD_GetAntennaGain();
void PCD_SetAntennaGain(byte mask);
bool PCD_PerformSelfTest();

/////////////////////////////////////////////////////////////////////////////////////
// Power control functions
/////////////////////////////////////////////////////////////////////////////////////
void PCD_SoftPowerDown();
void PCD_SoftPowerUp();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with PICCs
/////////////////////////////////////////////////////////////////////////////////////
StatusCode PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC); // TODO eclip
StatusCode PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits, byte rxAlign, bool checkCRC); //TODO eclip
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); //TODO eclip
StatusCode PICC_HaltA();

/////////////////////////////////////////////////////////////////////////////////////
// Convenience functions - does not add extra functionality
/////////////////////////////////////////////////////////////////////////////////////
bool PICC_IsNewCardPresent();
bool PICC_ReadCardSerial();


static   void spi_event_handler(nrf_drv_spi_evt_t const * p_event,void *p_context);
static   uint8_t spi_transmit(uint8_t data);
static   void mfrc522_write(uint8_t reg, uint8_t data);
static   uint8_t mfrc522_read(uint8_t reg);
void mfrc522_init();
void mfrc522_reset();

Parents Reply
  • Hi Hakon 

    I am using an example project, I put the two files (file.c and file.h) of the libraries in the same directory as main.c . In main.c I put the line that includes file.h. But in VSCode I have several errors and it does not take the function declarations.
    What is the correct way to add the libraries in an example project? I am using the SDK version 2.4.2.  Thank you very much in advance for your help.

Children
Related