Table of Contents

Class Pn5180

Namespace
Iot.Device.Pn5180
Assembly
Iot.Device.Pn5180.dll

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

spiDevice SpiDevice

The SPI device

pinBusy int

The pin for the busy line

pinNss int

The 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

gpioController GpioController

A GPIO controller, null will use a default one

shouldDispose bool

Dispose the SPI and the GPIO controller at the end if true

pinIrq int

Optional 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

SpiMode

MaximumSpiClockFrequency

PN532 SPI Clock Frequency

public const int MaximumSpiClockFrequency = 7000000

Field Value

int

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

int

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

bool

MaximumReadSize

Gets the maximum read size supported by this transceiver.

public override uint MaximumReadSize { get; }

Property Value

uint

MaximumWriteSize

Gets the maximum write size supported by this transceiver.

public override uint MaximumWriteSize { get; }

Property Value

uint

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

RadioFrequencyCollision

RadioFrequencyField

Get or set the radio frequency field. True for on, false for off

public bool RadioFrequencyField { get; set; }

Property Value

bool

Methods

CalculateCrcA(SpanByte, SpanByte)

Provide a calculation of CRC for Type A cards

public void CalculateCrcA(SpanByte buffer, SpanByte crc)

Parameters

buffer SpanByte

The buffer to process

crc SpanByte

The CRC, Must be a 2 bytes buffer

CalculateCrcB(SpanByte, SpanByte)

Provide a calculation of CRC for Type B cards

public void CalculateCrcB(SpanByte buffer, SpanByte crc)

Parameters

buffer SpanByte

The buffer to process

crc SpanByte

The CRC, Must be a 2 bytes buffer

DeselectCardTypeB(Data106kbpsTypeB)

Deselect a 14443 Type B card

public bool DeselectCardTypeB(Data106kbpsTypeB card)

Parameters

card Data106kbpsTypeB

The 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

outputIdentifier SpanByte

A 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

receiver ReceiverRadioFrequencyConfiguration

The 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

transmitter TransmitterRadioFrequencyConfiguration

The 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

status SpanByte

A 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration, should be compatible with type A card

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration, should be compatible with type A card

card Data106kbpsTypeA

The type A card once detected

timeoutPollingMilliseconds int

The 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration, should be compatible with type B card

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration, should be compatible with type A card

card Data106kbpsTypeB

The type B card once detected

timeoutPollingMilliseconds int

The 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration, should be compatible with 15693 card.

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration, should be compatible with 15693 card.

cards ArrayList

An ArrayList of Data26_53kbps once detected.

timeoutPollingMilliseconds int

The 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration

receiver ReceiverRadioFrequencyConfiguration

The 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

key SpanByte

A 6 bytes key

mifareCommand MifareCardCommand

MifareCardCommand.AuthenticationA or MifareCardCommand.AuthenticationB

blockAddress byte

The block address to authenticate

cardUid SpanByte

The 4 bytes UUID of the card

Returns

bool

True if success

ReadAllEeprom(SpanByte)

Read the full EEPROM

public bool ReadAllEeprom(SpanByte eeprom)

Parameters

eeprom SpanByte

At 255 bytes buffer

Returns

bool

True if success

ReadDataFromCard(SpanByte)

Read data from a card.

public bool ReadDataFromCard(SpanByte toRead)

Parameters

toRead SpanByte

The 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

toRead SpanByte

The span of byte to read

bytesRead int

number of bytes read

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

address EepromAddress

The EEPROM address

eeprom SpanByte

A 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

buffer SpanByte

Buffer to receive the command data.

timeoutMilliseconds int

Maximum 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

targetNumber byte

The 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration.

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration.

Returns

bool

True if success.

RetrieveRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration, SpanByte)

Retrieve the radio frequency configuration

public bool RetrieveRadioFrequencyConfiguration(ReceiverRadioFrequencyConfiguration receiver, SpanByte configuration)

Parameters

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration

configuration SpanByte

A 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration

configuration SpanByte

A 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

toSend SpanByte

The span of byte to send

numberValidBitsLastByte int

The 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

data SpanByte

The 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

responseData byte[]

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

nfcId byte[]

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

selRes byte

The 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

byte0 byte

First byte of SENS_RES (e.g. 0x44 for NTAG-like, 0x04 for generic).

byte1 byte

Second 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

mode AutocollMode

The 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

targetNumber byte

Some readers have a notion of target number for the cards as they can read multiple ones

dataToSend SpanByte

A standardized raw buffer with the command at the position 0 in the array

dataFromCard SpanByte

If any data are read from the card, they will be put into this array

protocol NfcProtocol

The 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 dataFromCard array

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

response SpanByte

The response data to send to the reader.

nextCommand SpanByte

Buffer to receive the reader's next command frame.

timeoutMilliseconds int

Maximum 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

receiver ReceiverRadioFrequencyConfiguration

The receiver configuration

configuration SpanByte

A 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

transmitter TransmitterRadioFrequencyConfiguration

The transmitter configuration

configuration SpanByte

A 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

timeoutMilliseconds int

Maximum time to wait for activation, in milliseconds.

Returns

CardEmulationData

A CardEmulationData with the activated protocol and any initial data received from the reader, or null if 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

irqMask int

Bitmask of the IRQ bits to wait for. The method returns as soon as any of the specified bits is set.

timeoutMilliseconds int

Maximum 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

eeprom SpanByte

A 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

address EepromAddress

The EEPROM address

eeprom SpanByte

A span of byte to write the EEPROM

Returns

bool

True if success