Class Pn5180
A PN5180 class offering RFID and NFC functionalities. Implement the CardTransceiver class to allow Mifare, Credit Card support
public class Pn5180 : CardTransceiver
- Inheritance
-
Pn5180
Constructors
Pn5180(SpiDevice, int, int, GpioController?, bool, int)
Create a PN5180 RFID/NFC reader
public Pn5180(SpiDevice spiDevice, int pinBusy, int pinNss, GpioController? gpioController = null, bool shouldDispose = true, int pinIrq = -1)
Parameters
spiDeviceSpiDeviceThe SPI device
pinBusyintThe pin for the busy line
pinNssintThe pin for the SPI select line. This has to be handle differently than thru the normal process as PN5180 has a specific way of working
gpioControllerGpioControllerA GPIO controller, null will use a default one
shouldDisposeboolDispose the SPI and the GPIO controller at the end if true
pinIrqintOptional pin connected to the PN5180 IRQ line. When >= 0 the pin is opened as input and WaitForIrq(int, int) can use it to detect IRQ assertion without continuous SPI polling. Pass -1 (default) to use register-polling only.
Fields
DefaultSpiMode
Only SPI Mode supported is Mode0
public const SpiMode DefaultSpiMode = Mode0
Field Value
MaximumSpiClockFrequency
PN532 SPI Clock Frequency
public const int MaximumSpiClockFrequency = 7000000
Field Value
RadioFrequencyConfigurationSize
A radio Frequency configuration element size is 5 bytes Byte 1 = Register Address next 4 bytes = data of the register
public const int RadioFrequencyConfigurationSize = 5
Field Value
Properties
CrcReceptionTransfer
Set on of off the CRC calculation for the Transfer and Reception Switch off is needed for anticollision operation on type A cards. Otherwise normal state is on
public bool CrcReceptionTransfer { get; set; }
Property Value
MaximumReadSize
Gets the maximum read size supported by this transceiver.
public override uint MaximumReadSize { get; }
Property Value
MaximumWriteSize
Gets the maximum write size supported by this transceiver.
public override uint MaximumWriteSize { get; }
Property Value
RadioFrequencyCollision
True to disable the Radio Frequency collision avoidance according to ISO/IEC 18092 False to use Active Communication mode according to ISO/IEC 18092
public RadioFrequencyCollision RadioFrequencyCollision { get; set; }
Property Value
RadioFrequencyField
Get or set the radio frequency field. True for on, false for off
public bool RadioFrequencyField { get; set; }
Property Value
Methods
CalculateCrcA(SpanByte, SpanByte)
Provide a calculation of CRC for Type A cards
public void CalculateCrcA(SpanByte buffer, SpanByte crc)
Parameters
CalculateCrcB(SpanByte, SpanByte)
Provide a calculation of CRC for Type B cards
public void CalculateCrcB(SpanByte buffer, SpanByte crc)
Parameters
DeselectCardTypeB(Data106kbpsTypeB)
Deselect a 14443 Type B card
public bool DeselectCardTypeB(Data106kbpsTypeB card)
Parameters
cardData106kbpsTypeBThe card to deselect
Returns
- bool
True if success
Dispose()
Dispose
public void Dispose()
ExitCardEmulationMode()
Exit card emulation (Autocoll / target) mode and return the PN5180 to normal (initiator / reader) mode.
public bool ExitCardEmulationMode()
Returns
- bool
True if the PN5180 was successfully returned to normal mode.
Remarks
Sends SWITCH_MODE with sub-mode 0x00 (NormalMode) to leave Autocoll. If the command times out (which can happen on some firmware versions), the PN5180 is not automatically reset; the caller should perform a hardware reset if needed.
After exiting, all IRQs are cleared and the PN5180 is ready to be used in reader/initiator mode again (e.g. calling ListenToCardIso14443TypeA(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration, out Data106kbpsTypeA?, int) or ListenToCardIso14443TypeB(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration, out Data106kbpsTypeB?, int)).
GetIdentifier(SpanByte)
Get the PN5180 identifier, this is a 16 byte long
public bool GetIdentifier(SpanByte outputIdentifier)
Parameters
outputIdentifierSpanByteA 16 byte buffer
Returns
- bool
True if success
GetNumberOfBytesReceivedAndValidBits()
Get the number of bytes to read and the valid number of bits in the last byte If the full byte is valid then the value of the valid bit is 0
public Doublet GetNumberOfBytesReceivedAndValidBits()
Returns
- Doublet
A tuple whit the number of bytes to read and the number of valid bits in the last byte. If all bits are valid, then the value of valid bits is 0
GetRadioFrequencyConfigSize(ReceiverRadioFrequencyConfiguration)
Get the size of the configuration of a specific receiver configuration
public int GetRadioFrequencyConfigSize(ReceiverRadioFrequencyConfiguration receiver)
Parameters
receiverReceiverRadioFrequencyConfigurationThe receiver configuration
Returns
- int
True if success
GetRadioFrequencyConfigSize(TransmitterRadioFrequencyConfiguration)
Get the size of the configuration of a specific transmitter configuration
public int GetRadioFrequencyConfigSize(TransmitterRadioFrequencyConfiguration transmitter)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration
Returns
- int
True if success
GetRadioFrequencyStatus()
Get the radio frenquency status
public RadioFrequencyStatus GetRadioFrequencyStatus()
Returns
- RadioFrequencyStatus
The radio frequence status
GetRawRfStatus(SpanByte)
Get the raw RF_STATUS register bytes for diagnostic purposes. The PN5180 returns 4 bytes (LSByte first) from register 0x1D.
public bool GetRawRfStatus(SpanByte status)
Parameters
statusSpanByteA 4-byte buffer to receive the raw register value.
Returns
- bool
True if the register was read successfully.
GetVersions()
Get the Product, Firmware and EEPROM versions of the PN8150
public TripletVersion GetVersions()
Returns
- TripletVersion
A tuple with the Product, Firmware and EEPROM versions
IsRadioFrequencyFieldExternal()
Is the external field activated?
public bool IsRadioFrequencyFieldExternal()
Returns
- bool
True if active, false if not
ListenToCardIso14443TypeA(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration, out Data106kbpsTypeA?, int)
Listen to any 14443 Type A card
public bool ListenToCardIso14443TypeA(TransmitterRadioFrequencyConfiguration transmitter, ReceiverRadioFrequencyConfiguration receiver, out Data106kbpsTypeA? card, int timeoutPollingMilliseconds)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration, should be compatible with type A card
receiverReceiverRadioFrequencyConfigurationThe receiver configuration, should be compatible with type A card
cardData106kbpsTypeAThe type A card once detected
timeoutPollingMillisecondsintThe time to poll the card in milliseconds. Card detection will stop once the detection time will be over
Returns
- bool
True if a 14443 Type A card has been detected
ListenToCardIso14443TypeB(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration, out Data106kbpsTypeB?, int)
Listen to any 14443 Type B card
public bool ListenToCardIso14443TypeB(TransmitterRadioFrequencyConfiguration transmitter, ReceiverRadioFrequencyConfiguration receiver, out Data106kbpsTypeB? card, int timeoutPollingMilliseconds)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration, should be compatible with type B card
receiverReceiverRadioFrequencyConfigurationThe receiver configuration, should be compatible with type A card
cardData106kbpsTypeBThe type B card once detected
timeoutPollingMillisecondsintThe time to poll the card in milliseconds. Card detection will stop once the detection time will be over
Returns
- bool
True if a 14443 Type B card has been detected
ListenToCardIso15693(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration, out ArrayList, int)
Listen to 15693 cards with 16 slots.
public bool ListenToCardIso15693(TransmitterRadioFrequencyConfiguration transmitter, ReceiverRadioFrequencyConfiguration receiver, out ArrayList cards, int timeoutPollingMilliseconds)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration, should be compatible with 15693 card.
receiverReceiverRadioFrequencyConfigurationThe receiver configuration, should be compatible with 15693 card.
cardsArrayListAn ArrayList of Data26_53kbps once detected.
timeoutPollingMillisecondsintThe time to poll the card in milliseconds. Card detection will stop once the detection time will be over.
Returns
- bool
True if a 15693 card has been detected.
LoadRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration)
Load a specific radio frequency configuration
public bool LoadRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration transmitter, ReceiverRadioFrequencyConfiguration receiver)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration
receiverReceiverRadioFrequencyConfigurationThe receiver configuration
Returns
- bool
True if success
MifareAuthenticate(SpanByte, MifareCardCommand, byte, SpanByte)
Specific function to authenticate Mifare cards
public bool MifareAuthenticate(SpanByte key, MifareCardCommand mifareCommand, byte blockAddress, SpanByte cardUid)
Parameters
keySpanByteA 6 bytes key
mifareCommandMifareCardCommandMifareCardCommand.AuthenticationA or MifareCardCommand.AuthenticationB
blockAddressbyteThe block address to authenticate
cardUidSpanByteThe 4 bytes UUID of the card
Returns
- bool
True if success
ReadAllEeprom(SpanByte)
Read the full EEPROM
public bool ReadAllEeprom(SpanByte eeprom)
Parameters
eepromSpanByteAt 255 bytes buffer
Returns
- bool
True if success
ReadDataFromCard(SpanByte)
Read data from a card.
public bool ReadDataFromCard(SpanByte toRead)
Parameters
toReadSpanByteThe span of byte to read
Returns
- bool
True if success
Remarks
Using this function you'll have to manage yourself the possible low level communication protocol. This function write directly to the card all the bytes. Please make sure you'll first load specific radio frequence settings, detect a card, select it and then send data
ReadDataFromCard(SpanByte, out int)
Read all the data from the card
public bool ReadDataFromCard(SpanByte toRead, out int bytesRead)
Parameters
Returns
- bool
A byte array with all the read elements, null if nothing can be read
Remarks
Using this function you'll have to manage yourself the possible low level communication protocol. This function write directly to the card all the bytes. Please make sure you'll first load specific radio frequence settings, detect a card, select it and then send data
ReadEeprom(EepromAddress, SpanByte)
Read a specific part of the EEPROM
public bool ReadEeprom(EepromAddress address, SpanByte eeprom)
Parameters
addressEepromAddressThe EEPROM address
eepromSpanByteA span of byte to read the EEPROM
Returns
- bool
True if success
ReceiveCommandFromReader(SpanByte, int)
Wait for and receive the next command frame from the external reader while in card emulation (target) mode.
public int ReceiveCommandFromReader(SpanByte buffer, int timeoutMilliseconds)
Parameters
bufferSpanByteBuffer to receive the command data.
timeoutMillisecondsintMaximum time to wait for a command, in milliseconds.
Returns
- int
The number of bytes received, or -1 on timeout or error.
Remarks
The method sets the PN5180 into IDLE, activates TRANSCEIVE to
listen for the next reader frame, then polls IRQ_STATUS for
RX_IRQ (bit 2). On reception it reads the data into
buffer.
If the external RF field is lost (RF_ACTIVE_ERROR_IRQ, bit 8), the method returns -1.
ReselectTarget(byte)
Once you have an authentication operation failing with Mifare cards or a read/write, the card stop. TYhe only way to have it back is to send the unselect and anti collision. This function provides this feature
public override bool ReselectTarget(byte targetNumber)
Parameters
targetNumberbyteThe target number to reselect
Returns
- bool
True if success
ResetPN5180Configuration(TransmitterRadioFrequencyConfiguration, ReceiverRadioFrequencyConfiguration)
Reset PN5180 RF Configuration and some registers. Useful when switching between different card protocols (e.g., ISO 14443 and ISO 15693).
public bool ResetPN5180Configuration(TransmitterRadioFrequencyConfiguration transmitter, ReceiverRadioFrequencyConfiguration receiver)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration.
receiverReceiverRadioFrequencyConfigurationThe receiver configuration.
Returns
- bool
True if success.
RetrieveRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration, SpanByte)
Retrieve the radio frequency configuration
public bool RetrieveRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration receiver, SpanByte configuration)
Parameters
receiverReceiverRadioFrequencyConfigurationThe receiver configuration
configurationSpanByteA span of bytes for the configuration. Should be a multiple of 5 with the size of
Returns
- bool
True if success
RetrieveRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration, SpanByte)
Retrieve the radio frequency configuration
public bool RetrieveRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration transmitter, SpanByte configuration)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration
configurationSpanByteA span of bytes for the configuration. Should be a multiple of 5 with the size of
Returns
- bool
True if success
SendDataToCard(SpanByte, int)
Send data to a card.
public bool SendDataToCard(SpanByte toSend, int numberValidBitsLastByte = 8)
Parameters
toSendSpanByteThe span of byte to send
numberValidBitsLastByteintThe number of bits valid in the last byte, 8 is the default. If validBits == 3 then it's equivalent to apply a mask of 0b000_0111 to get the correct valid bits
Returns
- bool
True if success
Remarks
Using this function you'll have to manage yourself the possible low level communication protocol. This function write directly to the card all the bytes. Please make sure you'll first load specific radio frequence settings, detect a card, select it and then send data
SendResponseToReader(SpanByte)
Send a response frame to the external reader while in card emulation (target) mode.
public bool SendResponseToReader(SpanByte data)
Parameters
dataSpanByteThe response data to transmit. Must not exceed MaximumWriteSize bytes.
Returns
- bool
True if the data was transmitted successfully.
Remarks
Call this after receiving a command from the reader (via ReceiveCommandFromReader(SpanByte, int) or the initial data in RxData).
CRC is appended automatically by the PN5180 hardware when
CrcReceptionTransfer is true (the default
after Autocoll activation for NFC-A ISO-DEP). Adjust CRC
settings before calling if your protocol requires it.
The method sets the PN5180 into IDLE, activates TRANSCEIVE, sends the data, then polls for TX_IRQ (bit 1) to confirm transmission.
SetFelicaPollingResponse(byte[])
Set the FeliCa Polling Response used during Autocoll card emulation when NFC-F collision resolution is enabled.
public bool SetFelicaPollingResponse(byte[] responseData)
Parameters
responseDatabyte[]Up to 10 bytes of FeliCa polling response configuration data. The EEPROM area at 0x46 holds the PAD0, PAD1, MRTI_check, MRTI_update, PAD2 and RD fields (see PN5180A0XX-C3.pdf EEPROM map). The full SENSF_RES IDm/NFCID2 (8 bytes) and PMm (8 bytes) are managed separately by the PN5180 firmware. Must be between 1 and 10 bytes.
Returns
- bool
True if the EEPROM write succeeded.
Remarks
Writes to EEPROM starting at address 0x46 (FELICA_POLLING_RESPONSE). The PN5180 uses these bytes together with the internally managed NFCID2 to construct the SENSF_RES sent in response to a SENSF_REQ polling command from an external reader when Autocoll is configured for NFC-F (212 or 424 kbps). See PN5180A0XX-C3.pdf EEPROM map.
SetNfcId1(byte[])
Set the NFCID1 (UID) bytes used during Autocoll card emulation.
public bool SetNfcId1(byte[] nfcId)
Parameters
nfcIdbyte[]Exactly 3 bytes. During Autocoll the PN5180 uses these as the last 3 bytes of the single-size (4-byte) UID.
Returns
- bool
True if the EEPROM write succeeded.
Remarks
Writes 3 bytes to EEPROM address 0x42 (NFCID1). The first byte of the 4-byte UID is fixed at 0x08 by the PN5180 (NXP manufacturer code) unless random UID is enabled. See PN5180A0XX-C3.pdf EEPROM map.
SetSelRes(byte)
Set the SEL_RES (SAK) byte used during Autocoll card emulation.
public bool SetSelRes(byte selRes)
Parameters
selResbyteThe SAK value. Common values: 0x20 = ISO 14443-4 compliant (ISO-DEP), 0x40 = ISO 18092 (NFC-DEP), 0x60 = Both ISO-DEP and NFC-DEP.
Returns
- bool
True if the EEPROM write succeeded.
Remarks
Writes 1 byte to EEPROM address 0x45 (SEL_RES). The reader uses this value to determine which protocol layers the target supports after anti-collision. See PN5180A0XX-C3.pdf EEPROM map and ISO 14443-3A §6.5.
SetSensRes(byte, byte)
Set the SENS_RES (ATQA) value used during Autocoll card emulation.
public bool SetSensRes(byte byte0, byte byte1)
Parameters
byte0byteFirst byte of SENS_RES (e.g. 0x44 for NTAG-like, 0x04 for generic).
byte1byteSecond byte of SENS_RES (e.g. 0x00).
Returns
- bool
True if the EEPROM write succeeded.
Remarks
Writes 2 bytes to EEPROM address 0x40 (SENS_RES). The PN5180 sends this value in response to SENS_REQ / ALL_REQ from an external reader during Autocoll mode. See PN5180A0XX-C3.pdf EEPROM map and ISO 14443-3A.
SwitchToAutocoll(AutocollMode)
Switch the PN5180 into Autocoll (card emulation / target) mode.
public bool SwitchToAutocoll(AutocollMode mode)
Parameters
modeAutocollModeThe NFC technologies to listen for. Can be a combination of AutocollMode flags.
Returns
- bool
True if the SWITCH_MODE command was sent successfully.
Remarks
Before calling this method, configure the emulated card identity using SetSensRes(byte, byte), SetNfcId1(byte[]) and SetSelRes(byte) (for NFC-A), or SetFelicaPollingResponse(byte[]) (for NFC-F).
This method turns OFF the PN5180's own RF field, clears all pending IRQs, then sends the SWITCH_MODE command with sub-mode 0x02 (Autocoll). After this call the PN5180 passively waits for an external RF field and autonomously handles anti-collision.
Use WaitForActivation(int) to poll for activation by an external reader.
See PN5180A0XX-C3.pdf §11.4.4 "SWITCH_MODE" and §7.1 "Autocoll".
Transceive(byte, SpanByte, SpanByte, NfcProtocol)
This function has to be implemented by all NFC/RFID/Card readers. This function is used in exchange of data with the reader and the cards.
public override int Transceive(byte targetNumber, SpanByte dataToSend, SpanByte dataFromCard, NfcProtocol protocol)
Parameters
targetNumberbyteSome readers have a notion of target number for the cards as they can read multiple ones
dataToSendSpanByteA standardized raw buffer with the command at the position 0 in the array
dataFromCardSpanByteIf any data are read from the card, they will be put into this array
protocolNfcProtocolThe NFC protocol to use for this transceive operation
Returns
- int
-1 in case of error, otherwise the number of bytes read and copied into the
dataFromCardarray
TransceiveTargetMode(SpanByte, SpanByte, int)
Send a response to the reader and then wait for the reader's next command, in a single call.
public int TransceiveTargetMode(SpanByte response, SpanByte nextCommand, int timeoutMilliseconds)
Parameters
responseSpanByteThe response data to send to the reader.
nextCommandSpanByteBuffer to receive the reader's next command frame.
timeoutMillisecondsintMaximum time to wait for the next command after sending the response.
Returns
- int
The number of bytes received in the next command, or -1 on error or timeout.
Remarks
This is a convenience wrapper that calls SendResponseToReader(SpanByte) followed by ReceiveCommandFromReader(SpanByte, int).
UpdateRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration, SpanByte)
Update the radio frequency configuration
public bool UpdateRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration receiver, SpanByte configuration)
Parameters
receiverReceiverRadioFrequencyConfigurationThe receiver configuration
configurationSpanByteA span of bytes for the configuration. Should be a multiple of 5 with the size of
Returns
- bool
True if success
UpdateRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration, SpanByte)
Update the radio frequency configuration
public bool UpdateRadioFrequencyConfiguration(TransmitterRadioFrequencyConfiguration transmitter, SpanByte configuration)
Parameters
transmitterTransmitterRadioFrequencyConfigurationThe transmitter configuration
configurationSpanByteA span of bytes for the configuration. Should be a multiple of 5 with the size of
Returns
- bool
True if success
WaitForActivation(int)
Wait for an external reader to activate the PN5180 after SwitchToAutocoll(AutocollMode) has been called.
public CardEmulationData WaitForActivation(int timeoutMilliseconds)
Parameters
timeoutMillisecondsintMaximum time to wait for activation, in milliseconds.
Returns
- CardEmulationData
A CardEmulationData with the activated protocol and any initial data received from the reader, or
nullif activation did not occur within the timeout or an error was detected.
Remarks
This method polls the IRQ_STATUS register for
CARD_ACTIVATED_IRQ (bit 13). If AUTOCOLL_ERR_IRQ (bit 11) is
detected instead, it means the Autocoll process failed
(e.g. RF field lost or protocol error) and null is returned.
On successful activation the method reads RF_STATUS bits [16:14] to determine whether NFC-A or NFC-F was used, reads any data already received from the reader (e.g. RATS or ATR_REQ), clears the IRQs, and returns the result.
See PN5180A0XX-C3.pdf Table 22 (IRQ_STATUS) and Table 28 (RF_STATUS).
WaitForIrq(int, int)
Wait for one or more IRQ bits to become set in the IRQ_STATUS register.
public int WaitForIrq(int irqMask, int timeoutMilliseconds)
Parameters
irqMaskintBitmask of the IRQ bits to wait for. The method returns as soon as any of the specified bits is set.
timeoutMillisecondsintMaximum time to wait, in milliseconds.
Returns
- int
The full 32-bit IRQ_STATUS register value when at least one requested bit is set, or 0 on timeout.
Remarks
When an IRQ pin was provided in the constructor this method first waits for the pin to go HIGH (IRQ asserted) before reading the SPI register, significantly reducing bus traffic. Without an IRQ pin the register is polled directly.
This helper centralises IRQ waiting for both reader and card-emulation (target) modes.
WriteAllEeprom(SpanByte)
Write all the EEPROM
public bool WriteAllEeprom(SpanByte eeprom)
Parameters
eepromSpanByteA 255 bytes buffer
Returns
- bool
True if success
WriteEeprom(EepromAddress, SpanByte)
Write the EEPROM at a specific address
public bool WriteEeprom(EepromAddress address, SpanByte eeprom)
Parameters
addressEepromAddressThe EEPROM address
eepromSpanByteA span of byte to write the EEPROM
Returns
- bool
True if success