On my road to get more familiar with microcontrollers I bought an RFID module kit.
It came with a MFRC522 module, a blue RFID key holder and a white RFID card.
Of course there are some libraries to deal with this module more easily, but I decided
that doing everything from scratch would teach me more about the RFID ecosystem and
Let’s start with the basic information about the module. It’s an 13.56MHz RFID module that should be capable of both reading and writing RFID tags. At least in Europe 13.56Mhz RFID tags seem to be much more common. The other common standard is 125kHz and it’s used for more long range applications like animal identification. I’ve found that all the RFID tags I have are 13.56Mhz (bank cards, ISIC cards, dorm access card). The 13.56Mhz standard should also be more advanced.
The RFID system consists of 2 devices: proximity integrated circuit card (PICC) and proximity coupling device (PCD). The PCD generates a 13.56MHz field which it can use to send data to the PICC. The PICC also generates power from that field to power itself. Once PCD has sent data the PICC can choose to respond. From what I understand the PICC does not create it’s own field, but modulates the PCD’s field to transmit data back. It does so by changing the load on the PCD’s generated field, the PCD can then sense those changes. Basically imagine shorting a wire in chaning magnetic field - the presence of that wire will induce extra load on the device generating the magnetic field. By changing the resistance of the wire and detecting changes in load, the devices can communicate. This is my unprofessional understanding of it, do your own research.
The rest of this post is gonna be about the ISO 14443 Type A standard for proximity cards. There’s also a newer 13.56MHz standard ISO 15693 that’s for vicinity cards. The main functional difference is range - 10cm vs 1m. I think the MFRC522 module can only deal with ISO 14443 tags, but some readers can do both.
The ISO 14443 standard is divided into 4 parts:
- Physcal characteristics
- Radio frequency power and signal interface
- Initialization and anticollision
- Transmission protocol
I’m looking to program existing hardware, so I’m gonna start with the 3rd part. All the cards I have use the ISO 14443-3 standard, but only 1 of them uses ISO 14443-4 standard (the transmission protocol). Just to be clear 14443-4 isn’t an alternative to 14443-3 - ISO 14443 is a stack of standards built on top of eachother. Pretty much all hardware chooses to use the first 3 parts of the stack, but often not the last one. Most of the cards I had (including the tags that came with the RFID module) use MIFARE standards for the higher transmission protocol on top of ISO 14443-3. Let’s get started with the low level ISO 14443-3 protocol.
The RFID tags operate at the same frequency, thus you need a way to avoid interference between multiple tags. The ISO 14443-3 protocol achieves this by allowing you to change the PICC’s state and select one specific PICC. After you’ve selected the PICC you can either transmit data or you can halt it, so that you can select a different one without interference. This is mostly what this part of the standard is about - the low level states and selecting a device.
At the heart of the protocol is a simple state machine:
As you can see, most state transitions happen when a command is sent to the PICC. Brief descriptions of the commands:
- REQA - request command Type A, most likely the first command sent to a PICC
- WUPA - Wake-Up command Type A, wake up from HALT or IDLE
- SELECT/ANTICOLLISION - select PICC, the part of select sequence where PCD reads UID from PICC is called ANTICOLLISION
- HALT - don’t respond to any command besides WUPA
The steps to get the PICC into active state:
- Send REQA command
- If you receive a ATQA then one or more PICC are present
- Get PICC UID by running the anticollision loop
- Send full select command with the acquired UID
- Receive SAK from PICC, return to step 3 if there’s another cascade level
UID can be divided in up to 3 cascade levels. The UID consists of 4, 7 or 10 bytes. Once you’ve selected all cascade levels the PICC goes into ACTIVE state and you can proceed with a higher level protocol. The presence of another cascade level is detected by the first byte in UID of current cascade level (0x88) and the cascade bit in SAK. The SAK (1 byte) can also be used determine the higher level protocol.
The trickiest part is probably the anticollision loop. Basically you send an ANTICOLLISION command and the PICC will respond with UID bytes. In ideal case there is only 1 PICC present and you’ll receive the entire UID of current cascade level just like that and select the PICC with it. However if there are more PICCs present the UID will collide because multiple PICC report different UID. The RFID reader (PCD) should be able to detect the sequence number of first colliding bit. The ISO 14443-3 standard notes that in that case a typical implementation assumes the colliding bit was 1. In the next iteration the PCD will send the known bits back (bits before collision + the assumed bit). When a collision occured one of the PICC had 1 as that bit and the other one had 0. Since you assumed the bit to be 1, only 1 of those PICCs will respond with remaining bits. This process is repeated until you have all the bits.
ANTICOLLISION command consists of 2+n bytes and the last byte can be further divided to bits (collision can occur at any UID bit).
The UID of each cascade level consists of 4 bytes, in case it’s not the last cascade level, the first byte will be the cascade tag (0x88).
The first byte is the SEL byte and determines the cascade level. (0x93 CL1, 0x95 CL2, 0x97 CL3). The second byte is NVB byte, which determines number of valid bytes and bits, the PICC will expect exactly that many bits to follow the first 2 bytes. Higher nibble is number of valid bytes and lower nibble is number of valid bits. Thus NVB for first ANTICOLLISION command is 0x20 (2 bytes and we don’t know any UID bytes).
The PICC will respond with up to 4 UID bytes + BCC byte (bitwise XOR of UID bytes). More known bits are added to the command on every loop iteration and PICC will start sending less and less bits back, until all bits are known. Basically you’ll get all the bits once all PICCs except 1 are masked out by the known bits.
Once you have all the bits you can send the SELECT command. It’s basically the same command except that the PCD will have to include the entire 4 bytes of UID, a BCC byte and a 2 byte CRC of the first 7 bytes, totalling 9 bytes (SEL, NVB(0x70), 4 bytes UID (first byte 0x88 if not last cascade level, BCC, 2 bytes CRC_A).
This is pretty much all that the ISO 14443-3 Type A standard is about. All the RFID tags that I have seem to use this standard, thus I haven’t even felt the need to look into the Type B version yet. In next post I’ll try to talk about programming the MFRC522 module from scratch. Then I’ll probably go on to the MIFARE higher level protocol.