MFRC522 example project for FRDM

Dependencies:   MFRC522 mbed

Fork of FRDM_MFRC522 by Martin Olejar

Committer:
daniebrink
Date:
Fri Oct 21 13:35:13 2016 +0000
Revision:
3:d5f3d4c8f9ae
Parent:
2:1c050fb3fec0
TARGET_NUCLEO_F446ZE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AtomX 0:1d9c7c0b5015 1 #include "mbed.h"
AtomX 0:1d9c7c0b5015 2 #include "MFRC522.h"
AtomX 0:1d9c7c0b5015 3
AtomX 1:8e41a7b03f45 4 #if defined(TARGET_KL25Z)
AtomX 0:1d9c7c0b5015 5
AtomX 0:1d9c7c0b5015 6 /* KL25Z Pins for MFRC522 SPI interface */
AtomX 1:8e41a7b03f45 7 #define SPI_MOSI PTC6
AtomX 1:8e41a7b03f45 8 #define SPI_MISO PTC7
AtomX 1:8e41a7b03f45 9 #define SPI_SCLK PTC5
AtomX 1:8e41a7b03f45 10 #define SPI_CS PTC4
AtomX 0:1d9c7c0b5015 11
AtomX 0:1d9c7c0b5015 12 /* KL25Z Pin for MFRC522 reset */
AtomX 1:8e41a7b03f45 13 #define MF_RESET PTC3
AtomX 0:1d9c7c0b5015 14
AtomX 0:1d9c7c0b5015 15 /* KL25Z Pins for UART Debug port */
AtomX 0:1d9c7c0b5015 16 #define UART_RX PTA1
AtomX 0:1d9c7c0b5015 17 #define UART_TX PTA2
AtomX 0:1d9c7c0b5015 18
AtomX 1:8e41a7b03f45 19 #elif defined(TARGET_LPC11U24)
AtomX 0:1d9c7c0b5015 20
AtomX 0:1d9c7c0b5015 21 /* LPC11U24 Pins for MFRC522 SPI interface */
AtomX 1:8e41a7b03f45 22 #define SPI_MOSI P0_9
AtomX 1:8e41a7b03f45 23 #define SPI_MISO P0_8
AtomX 1:8e41a7b03f45 24 #define SPI_SCLK P1_29
AtomX 1:8e41a7b03f45 25 #define SPI_CS P0_2
AtomX 0:1d9c7c0b5015 26
AtomX 0:1d9c7c0b5015 27 /* LPC11U24 Pin for MFRC522 reset */
AtomX 1:8e41a7b03f45 28 #define MF_RESET P1_13
AtomX 0:1d9c7c0b5015 29
AtomX 0:1d9c7c0b5015 30 /* LPC11U24 Pins for UART Debug port */
AtomX 1:8e41a7b03f45 31 #define UART_RX P0_18
AtomX 1:8e41a7b03f45 32 #define UART_TX P0_19
AtomX 1:8e41a7b03f45 33
AtomX 1:8e41a7b03f45 34 /* LED Pins */
AtomX 1:8e41a7b03f45 35 #define LED_RED P0_7
AtomX 1:8e41a7b03f45 36 #define LED_GREEN P1_22
AtomX 0:1d9c7c0b5015 37
daniebrink 2:1c050fb3fec0 38 #elif defined(TARGET_NUCLEO_F446ZE)
daniebrink 2:1c050fb3fec0 39 /* NUCLEO_F446ZE Pins for MFRC522 SPI interface */
daniebrink 2:1c050fb3fec0 40 #define SPI_MOSI D11
daniebrink 2:1c050fb3fec0 41 #define SPI_MISO D12
daniebrink 2:1c050fb3fec0 42 #define SPI_SCLK D13
daniebrink 2:1c050fb3fec0 43 #define SPI_CS D10
daniebrink 2:1c050fb3fec0 44
daniebrink 2:1c050fb3fec0 45 /* NUCLEO_F446ZE Pin for MFRC522 reset */
daniebrink 2:1c050fb3fec0 46 #define MF_RESET D9
daniebrink 2:1c050fb3fec0 47
daniebrink 2:1c050fb3fec0 48 /* NUCLEO_F446ZE Pins for UART Debug port */
daniebrink 2:1c050fb3fec0 49 #define UART_RX PD_9
daniebrink 2:1c050fb3fec0 50 #define UART_TX PD_8
daniebrink 2:1c050fb3fec0 51
daniebrink 2:1c050fb3fec0 52 /* LED Pins */
daniebrink 2:1c050fb3fec0 53 #define LED_RED LED2
daniebrink 2:1c050fb3fec0 54 #define LED_GREEN LED3
daniebrink 2:1c050fb3fec0 55
AtomX 0:1d9c7c0b5015 56 #endif
AtomX 0:1d9c7c0b5015 57
AtomX 1:8e41a7b03f45 58 DigitalOut LedRed (LED_RED);
AtomX 1:8e41a7b03f45 59 DigitalOut LedGreen (LED_GREEN);
AtomX 0:1d9c7c0b5015 60
AtomX 1:8e41a7b03f45 61 Serial DebugUART(UART_TX, UART_RX);
AtomX 1:8e41a7b03f45 62 MFRC522 RfChip (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET);
AtomX 0:1d9c7c0b5015 63
AtomX 1:8e41a7b03f45 64 /* Local functions */
AtomX 0:1d9c7c0b5015 65 void DumpMifareClassicToSerial (MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key);
AtomX 0:1d9c7c0b5015 66 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector);
AtomX 0:1d9c7c0b5015 67 void DumpMifareUltralightToSerial (void);
AtomX 0:1d9c7c0b5015 68
AtomX 0:1d9c7c0b5015 69 /**
AtomX 0:1d9c7c0b5015 70 * Dumps debug info about the selected PICC to Serial.
AtomX 0:1d9c7c0b5015 71 * On success the PICC is halted after dumping the data.
AtomX 0:1d9c7c0b5015 72 * For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
AtomX 0:1d9c7c0b5015 73 */
AtomX 0:1d9c7c0b5015 74 void DumpToSerial(MFRC522::Uid *uid)
AtomX 0:1d9c7c0b5015 75 {
AtomX 0:1d9c7c0b5015 76 MFRC522::MIFARE_Key key;
AtomX 0:1d9c7c0b5015 77
AtomX 0:1d9c7c0b5015 78 // UID
AtomX 1:8e41a7b03f45 79 printf("Card UID: ");
AtomX 0:1d9c7c0b5015 80 for (uint8_t i = 0; i < uid->size; i++)
AtomX 0:1d9c7c0b5015 81 {
AtomX 0:1d9c7c0b5015 82 printf(" %X02", uid->uidByte[i]);
AtomX 0:1d9c7c0b5015 83 }
AtomX 0:1d9c7c0b5015 84 printf("\n\r");
AtomX 0:1d9c7c0b5015 85
AtomX 0:1d9c7c0b5015 86 // PICC type
AtomX 0:1d9c7c0b5015 87 uint8_t piccType = RfChip.PICC_GetType(uid->sak);
AtomX 1:8e41a7b03f45 88 printf("PICC Type: %s \n\r", RfChip.PICC_GetTypeName(piccType));
AtomX 0:1d9c7c0b5015 89
AtomX 0:1d9c7c0b5015 90
AtomX 0:1d9c7c0b5015 91 // Dump contents
AtomX 0:1d9c7c0b5015 92 switch (piccType)
AtomX 0:1d9c7c0b5015 93 {
AtomX 0:1d9c7c0b5015 94 case MFRC522::PICC_TYPE_MIFARE_MINI:
AtomX 0:1d9c7c0b5015 95 case MFRC522::PICC_TYPE_MIFARE_1K:
AtomX 0:1d9c7c0b5015 96 case MFRC522::PICC_TYPE_MIFARE_4K:
AtomX 0:1d9c7c0b5015 97 // All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
AtomX 1:8e41a7b03f45 98 for (uint8_t i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; }
AtomX 0:1d9c7c0b5015 99 DumpMifareClassicToSerial(uid, piccType, &key);
AtomX 0:1d9c7c0b5015 100 break;
AtomX 0:1d9c7c0b5015 101
AtomX 0:1d9c7c0b5015 102 case MFRC522::PICC_TYPE_MIFARE_UL:
AtomX 0:1d9c7c0b5015 103 DumpMifareUltralightToSerial();
AtomX 0:1d9c7c0b5015 104 break;
AtomX 0:1d9c7c0b5015 105
AtomX 0:1d9c7c0b5015 106 case MFRC522::PICC_TYPE_ISO_14443_4:
AtomX 0:1d9c7c0b5015 107 case MFRC522::PICC_TYPE_ISO_18092:
AtomX 0:1d9c7c0b5015 108 case MFRC522::PICC_TYPE_MIFARE_PLUS:
AtomX 0:1d9c7c0b5015 109 case MFRC522::PICC_TYPE_TNP3XXX:
AtomX 0:1d9c7c0b5015 110 printf("Dumping memory contents not implemented for that PICC type. \n\r");
AtomX 0:1d9c7c0b5015 111 break;
AtomX 0:1d9c7c0b5015 112
AtomX 0:1d9c7c0b5015 113 case MFRC522::PICC_TYPE_UNKNOWN:
AtomX 0:1d9c7c0b5015 114 case MFRC522::PICC_TYPE_NOT_COMPLETE:
AtomX 0:1d9c7c0b5015 115 default:
AtomX 0:1d9c7c0b5015 116 break; // No memory dump here
AtomX 0:1d9c7c0b5015 117 }
AtomX 0:1d9c7c0b5015 118
AtomX 0:1d9c7c0b5015 119 printf("\n\r");
AtomX 0:1d9c7c0b5015 120
AtomX 0:1d9c7c0b5015 121 RfChip.PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
AtomX 0:1d9c7c0b5015 122 } // End PICC_DumpToSerial()
AtomX 0:1d9c7c0b5015 123
AtomX 0:1d9c7c0b5015 124 /**
AtomX 0:1d9c7c0b5015 125 * Dumps memory contents of a MIFARE Classic PICC.
AtomX 0:1d9c7c0b5015 126 * On success the PICC is halted after dumping the data.
AtomX 0:1d9c7c0b5015 127 */
AtomX 0:1d9c7c0b5015 128 void DumpMifareClassicToSerial(MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key)
AtomX 0:1d9c7c0b5015 129 {
AtomX 0:1d9c7c0b5015 130 uint8_t no_of_sectors = 0;
AtomX 0:1d9c7c0b5015 131 switch (piccType)
AtomX 0:1d9c7c0b5015 132 {
AtomX 0:1d9c7c0b5015 133 case MFRC522::PICC_TYPE_MIFARE_MINI:
AtomX 0:1d9c7c0b5015 134 // Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
AtomX 0:1d9c7c0b5015 135 no_of_sectors = 5;
AtomX 0:1d9c7c0b5015 136 break;
AtomX 0:1d9c7c0b5015 137
AtomX 0:1d9c7c0b5015 138 case MFRC522::PICC_TYPE_MIFARE_1K:
AtomX 0:1d9c7c0b5015 139 // Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
AtomX 0:1d9c7c0b5015 140 no_of_sectors = 16;
AtomX 0:1d9c7c0b5015 141 break;
AtomX 0:1d9c7c0b5015 142
AtomX 0:1d9c7c0b5015 143 case MFRC522::PICC_TYPE_MIFARE_4K:
AtomX 0:1d9c7c0b5015 144 // Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
AtomX 0:1d9c7c0b5015 145 no_of_sectors = 40;
AtomX 0:1d9c7c0b5015 146 break;
AtomX 0:1d9c7c0b5015 147
AtomX 1:8e41a7b03f45 148 default:
AtomX 1:8e41a7b03f45 149 // Should not happen. Ignore.
AtomX 0:1d9c7c0b5015 150 break;
AtomX 0:1d9c7c0b5015 151 }
AtomX 0:1d9c7c0b5015 152
AtomX 0:1d9c7c0b5015 153 // Dump sectors, highest address first.
AtomX 0:1d9c7c0b5015 154 if (no_of_sectors)
AtomX 0:1d9c7c0b5015 155 {
AtomX 1:8e41a7b03f45 156 printf("Sector Block 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AccessBits \n\r");
AtomX 1:8e41a7b03f45 157 printf("----------------------------------------------------------------------------------------- \n\r");
AtomX 1:8e41a7b03f45 158 for (uint8_t i = no_of_sectors - 1; i > 0; i--)
AtomX 0:1d9c7c0b5015 159 {
AtomX 0:1d9c7c0b5015 160 DumpMifareClassicSectorToSerial(uid, key, i);
AtomX 0:1d9c7c0b5015 161 }
AtomX 0:1d9c7c0b5015 162 }
AtomX 0:1d9c7c0b5015 163
AtomX 0:1d9c7c0b5015 164 RfChip.PICC_HaltA(); // Halt the PICC before stopping the encrypted session.
AtomX 0:1d9c7c0b5015 165 RfChip.PCD_StopCrypto1();
AtomX 0:1d9c7c0b5015 166 } // End PICC_DumpMifareClassicToSerial()
AtomX 0:1d9c7c0b5015 167
AtomX 0:1d9c7c0b5015 168 /**
AtomX 0:1d9c7c0b5015 169 * Dumps memory contents of a sector of a MIFARE Classic PICC.
AtomX 0:1d9c7c0b5015 170 * Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1.
AtomX 0:1d9c7c0b5015 171 * Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits.
AtomX 0:1d9c7c0b5015 172 */
AtomX 0:1d9c7c0b5015 173 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector)
AtomX 0:1d9c7c0b5015 174 {
AtomX 0:1d9c7c0b5015 175 uint8_t status;
AtomX 0:1d9c7c0b5015 176 uint8_t firstBlock; // Address of lowest address to dump actually last block dumped)
AtomX 0:1d9c7c0b5015 177 uint8_t no_of_blocks; // Number of blocks in sector
AtomX 0:1d9c7c0b5015 178 bool isSectorTrailer; // Set to true while handling the "last" (ie highest address) in the sector.
AtomX 0:1d9c7c0b5015 179
AtomX 0:1d9c7c0b5015 180 // The access bits are stored in a peculiar fashion.
AtomX 0:1d9c7c0b5015 181 // There are four groups:
AtomX 0:1d9c7c0b5015 182 // g[3] Access bits for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
AtomX 0:1d9c7c0b5015 183 // g[2] Access bits for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
AtomX 0:1d9c7c0b5015 184 // g[1] Access bits for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
AtomX 0:1d9c7c0b5015 185 // g[0] Access bits for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
AtomX 0:1d9c7c0b5015 186 // Each group has access bits [C1 C2 C3]. In this code C1 is MSB and C3 is LSB.
AtomX 0:1d9c7c0b5015 187 // The four CX bits are stored together in a nible cx and an inverted nible cx_.
AtomX 0:1d9c7c0b5015 188 uint8_t c1, c2, c3; // Nibbles
AtomX 0:1d9c7c0b5015 189 uint8_t c1_, c2_, c3_; // Inverted nibbles
AtomX 1:8e41a7b03f45 190 bool invertedError = false; // True if one of the inverted nibbles did not match
AtomX 0:1d9c7c0b5015 191 uint8_t g[4]; // Access bits for each of the four groups.
AtomX 0:1d9c7c0b5015 192 uint8_t group; // 0-3 - active group for access bits
AtomX 0:1d9c7c0b5015 193 bool firstInGroup; // True for the first block dumped in the group
AtomX 0:1d9c7c0b5015 194
AtomX 0:1d9c7c0b5015 195 // Determine position and size of sector.
AtomX 0:1d9c7c0b5015 196 if (sector < 32)
AtomX 0:1d9c7c0b5015 197 { // Sectors 0..31 has 4 blocks each
AtomX 0:1d9c7c0b5015 198 no_of_blocks = 4;
AtomX 0:1d9c7c0b5015 199 firstBlock = sector * no_of_blocks;
AtomX 0:1d9c7c0b5015 200 }
AtomX 0:1d9c7c0b5015 201 else if (sector < 40)
AtomX 0:1d9c7c0b5015 202 { // Sectors 32-39 has 16 blocks each
AtomX 0:1d9c7c0b5015 203 no_of_blocks = 16;
AtomX 0:1d9c7c0b5015 204 firstBlock = 128 + (sector - 32) * no_of_blocks;
AtomX 0:1d9c7c0b5015 205 }
AtomX 0:1d9c7c0b5015 206 else
AtomX 0:1d9c7c0b5015 207 { // Illegal input, no MIFARE Classic PICC has more than 40 sectors.
AtomX 0:1d9c7c0b5015 208 return;
AtomX 0:1d9c7c0b5015 209 }
AtomX 0:1d9c7c0b5015 210
AtomX 0:1d9c7c0b5015 211 // Dump blocks, highest address first.
AtomX 0:1d9c7c0b5015 212 uint8_t byteCount;
AtomX 0:1d9c7c0b5015 213 uint8_t buffer[18];
AtomX 0:1d9c7c0b5015 214 uint8_t blockAddr;
AtomX 0:1d9c7c0b5015 215 isSectorTrailer = true;
AtomX 1:8e41a7b03f45 216 for (uint8_t blockOffset = no_of_blocks - 1; blockOffset > 0; blockOffset--)
AtomX 0:1d9c7c0b5015 217 {
AtomX 0:1d9c7c0b5015 218 blockAddr = firstBlock + blockOffset;
AtomX 1:8e41a7b03f45 219
AtomX 0:1d9c7c0b5015 220 // Sector number - only on first line
AtomX 0:1d9c7c0b5015 221 if (isSectorTrailer)
AtomX 0:1d9c7c0b5015 222 {
AtomX 0:1d9c7c0b5015 223 printf(" %2d ", sector);
AtomX 0:1d9c7c0b5015 224 }
AtomX 0:1d9c7c0b5015 225 else
AtomX 0:1d9c7c0b5015 226 {
AtomX 0:1d9c7c0b5015 227 printf(" ");
AtomX 0:1d9c7c0b5015 228 }
AtomX 1:8e41a7b03f45 229
AtomX 0:1d9c7c0b5015 230 // Block number
AtomX 1:8e41a7b03f45 231 printf(" %3d ", blockAddr);
AtomX 1:8e41a7b03f45 232
AtomX 0:1d9c7c0b5015 233 // Establish encrypted communications before reading the first block
AtomX 0:1d9c7c0b5015 234 if (isSectorTrailer)
AtomX 0:1d9c7c0b5015 235 {
AtomX 0:1d9c7c0b5015 236 status = RfChip.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid);
AtomX 0:1d9c7c0b5015 237 if (status != MFRC522::STATUS_OK)
AtomX 0:1d9c7c0b5015 238 {
AtomX 1:8e41a7b03f45 239 printf("PCD_Authenticate() failed: %s \r\n", RfChip.GetStatusCodeName(status));
AtomX 0:1d9c7c0b5015 240 return;
AtomX 0:1d9c7c0b5015 241 }
AtomX 0:1d9c7c0b5015 242 }
AtomX 1:8e41a7b03f45 243
AtomX 0:1d9c7c0b5015 244 // Read block
AtomX 0:1d9c7c0b5015 245 byteCount = sizeof(buffer);
AtomX 0:1d9c7c0b5015 246 status = RfChip.MIFARE_Read(blockAddr, buffer, &byteCount);
AtomX 0:1d9c7c0b5015 247 if (status != MFRC522::STATUS_OK)
AtomX 0:1d9c7c0b5015 248 {
AtomX 1:8e41a7b03f45 249 printf("MIFARE_Read() failed: %s \r\n", RfChip.GetStatusCodeName(status));
AtomX 0:1d9c7c0b5015 250 continue;
AtomX 0:1d9c7c0b5015 251 }
AtomX 1:8e41a7b03f45 252
AtomX 0:1d9c7c0b5015 253 // Dump data
AtomX 0:1d9c7c0b5015 254 for (uint8_t index = 0; index < 16; index++)
AtomX 0:1d9c7c0b5015 255 {
AtomX 1:8e41a7b03f45 256 printf(" %3d", buffer[index]);
AtomX 1:8e41a7b03f45 257 // if ((index % 4) == 3)
AtomX 1:8e41a7b03f45 258 // {
AtomX 1:8e41a7b03f45 259 // printf(" ");
AtomX 1:8e41a7b03f45 260 // }
AtomX 0:1d9c7c0b5015 261 }
AtomX 1:8e41a7b03f45 262
AtomX 0:1d9c7c0b5015 263 // Parse sector trailer data
AtomX 0:1d9c7c0b5015 264 if (isSectorTrailer)
AtomX 0:1d9c7c0b5015 265 {
AtomX 0:1d9c7c0b5015 266 c1 = buffer[7] >> 4;
AtomX 0:1d9c7c0b5015 267 c2 = buffer[8] & 0xF;
AtomX 0:1d9c7c0b5015 268 c3 = buffer[8] >> 4;
AtomX 0:1d9c7c0b5015 269 c1_ = buffer[6] & 0xF;
AtomX 0:1d9c7c0b5015 270 c2_ = buffer[6] >> 4;
AtomX 0:1d9c7c0b5015 271 c3_ = buffer[7] & 0xF;
AtomX 0:1d9c7c0b5015 272 invertedError = (c1 != (~c1_ & 0xF)) || (c2 != (~c2_ & 0xF)) || (c3 != (~c3_ & 0xF));
AtomX 1:8e41a7b03f45 273
AtomX 0:1d9c7c0b5015 274 g[0] = ((c1 & 1) << 2) | ((c2 & 1) << 1) | ((c3 & 1) << 0);
AtomX 0:1d9c7c0b5015 275 g[1] = ((c1 & 2) << 1) | ((c2 & 2) << 0) | ((c3 & 2) >> 1);
AtomX 0:1d9c7c0b5015 276 g[2] = ((c1 & 4) << 0) | ((c2 & 4) >> 1) | ((c3 & 4) >> 2);
AtomX 0:1d9c7c0b5015 277 g[3] = ((c1 & 8) >> 1) | ((c2 & 8) >> 2) | ((c3 & 8) >> 3);
AtomX 0:1d9c7c0b5015 278 isSectorTrailer = false;
AtomX 0:1d9c7c0b5015 279 }
AtomX 0:1d9c7c0b5015 280
AtomX 0:1d9c7c0b5015 281 // Which access group is this block in?
AtomX 0:1d9c7c0b5015 282 if (no_of_blocks == 4)
AtomX 0:1d9c7c0b5015 283 {
AtomX 0:1d9c7c0b5015 284 group = blockOffset;
AtomX 0:1d9c7c0b5015 285 firstInGroup = true;
AtomX 0:1d9c7c0b5015 286 }
AtomX 0:1d9c7c0b5015 287 else
AtomX 0:1d9c7c0b5015 288 {
AtomX 0:1d9c7c0b5015 289 group = blockOffset / 5;
AtomX 0:1d9c7c0b5015 290 firstInGroup = (group == 3) || (group != (blockOffset + 1) / 5);
AtomX 0:1d9c7c0b5015 291 }
AtomX 0:1d9c7c0b5015 292
AtomX 0:1d9c7c0b5015 293 if (firstInGroup)
AtomX 0:1d9c7c0b5015 294 {
AtomX 0:1d9c7c0b5015 295 // Print access bits
AtomX 1:8e41a7b03f45 296 printf(" [ %d %d %d ] ", (g[group] >> 2) & 1, (g[group] >> 1) & 1, (g[group] >> 0) & 1);
AtomX 0:1d9c7c0b5015 297 if (invertedError)
AtomX 0:1d9c7c0b5015 298 {
AtomX 0:1d9c7c0b5015 299 printf(" Inverted access bits did not match! ");
AtomX 0:1d9c7c0b5015 300 }
AtomX 0:1d9c7c0b5015 301 }
AtomX 0:1d9c7c0b5015 302
AtomX 0:1d9c7c0b5015 303 if (group != 3 && (g[group] == 1 || g[group] == 6))
AtomX 0:1d9c7c0b5015 304 { // Not a sector trailer, a value block
AtomX 0:1d9c7c0b5015 305 printf(" Addr = 0x%02X, Value = 0x%02X%02X%02X%02X", buffer[12],
AtomX 0:1d9c7c0b5015 306 buffer[3],
AtomX 0:1d9c7c0b5015 307 buffer[2],
AtomX 0:1d9c7c0b5015 308 buffer[1],
AtomX 0:1d9c7c0b5015 309 buffer[0]);
AtomX 0:1d9c7c0b5015 310 }
AtomX 0:1d9c7c0b5015 311
AtomX 0:1d9c7c0b5015 312 printf("\n\r");
AtomX 0:1d9c7c0b5015 313 }
AtomX 0:1d9c7c0b5015 314
AtomX 0:1d9c7c0b5015 315 return;
AtomX 0:1d9c7c0b5015 316 } // End PICC_DumpMifareClassicSectorToSerial()
AtomX 0:1d9c7c0b5015 317
AtomX 0:1d9c7c0b5015 318 /**
AtomX 0:1d9c7c0b5015 319 * Dumps memory contents of a MIFARE Ultralight PICC.
AtomX 0:1d9c7c0b5015 320 */
AtomX 0:1d9c7c0b5015 321 void DumpMifareUltralightToSerial(void)
AtomX 0:1d9c7c0b5015 322 {
AtomX 0:1d9c7c0b5015 323 uint8_t status;
AtomX 0:1d9c7c0b5015 324 uint8_t byteCount;
AtomX 0:1d9c7c0b5015 325 uint8_t buffer[18];
AtomX 0:1d9c7c0b5015 326 uint8_t i;
AtomX 0:1d9c7c0b5015 327
AtomX 1:8e41a7b03f45 328 printf("Page 0 1 2 3");
AtomX 0:1d9c7c0b5015 329 // Try the mpages of the original Ultralight. Ultralight C has more pages.
AtomX 0:1d9c7c0b5015 330 for (uint8_t page = 0; page < 16; page +=4)
AtomX 0:1d9c7c0b5015 331 {
AtomX 0:1d9c7c0b5015 332 // Read pages
AtomX 0:1d9c7c0b5015 333 byteCount = sizeof(buffer);
AtomX 0:1d9c7c0b5015 334 status = RfChip.MIFARE_Read(page, buffer, &byteCount);
AtomX 0:1d9c7c0b5015 335 if (status != MFRC522::STATUS_OK)
AtomX 0:1d9c7c0b5015 336 {
AtomX 1:8e41a7b03f45 337 printf("MIFARE_Read() failed: %s \n\r", RfChip.GetStatusCodeName(status));
AtomX 0:1d9c7c0b5015 338 break;
AtomX 0:1d9c7c0b5015 339 }
AtomX 0:1d9c7c0b5015 340
AtomX 0:1d9c7c0b5015 341 // Dump data
AtomX 0:1d9c7c0b5015 342 for (uint8_t offset = 0; offset < 4; offset++)
AtomX 0:1d9c7c0b5015 343 {
AtomX 0:1d9c7c0b5015 344 i = page + offset;
AtomX 1:8e41a7b03f45 345 printf(" %2d ", i); // Pad with spaces
AtomX 0:1d9c7c0b5015 346 for (uint8_t index = 0; index < 4; index++)
AtomX 0:1d9c7c0b5015 347 {
AtomX 0:1d9c7c0b5015 348 i = 4 * offset + index;
AtomX 0:1d9c7c0b5015 349 printf(" %02X ", buffer[i]);
AtomX 0:1d9c7c0b5015 350 }
AtomX 0:1d9c7c0b5015 351
AtomX 0:1d9c7c0b5015 352 printf("\n\r");
AtomX 0:1d9c7c0b5015 353 }
AtomX 0:1d9c7c0b5015 354 }
AtomX 0:1d9c7c0b5015 355 } // End PICC_DumpMifareUltralightToSerial()
AtomX 0:1d9c7c0b5015 356
AtomX 0:1d9c7c0b5015 357 int main()
AtomX 0:1d9c7c0b5015 358 {
AtomX 1:8e41a7b03f45 359 /* Set debug UART speed */
AtomX 0:1d9c7c0b5015 360 DebugUART.baud(115200);
AtomX 1:8e41a7b03f45 361 printf("< mbed RFID demo >\n\r");
AtomX 1:8e41a7b03f45 362 printf("\n\r");
AtomX 0:1d9c7c0b5015 363
AtomX 1:8e41a7b03f45 364 /* Init. RC522 Chip */
AtomX 0:1d9c7c0b5015 365 RfChip.PCD_Init();
AtomX 0:1d9c7c0b5015 366
AtomX 1:8e41a7b03f45 367 /* Read RC522 version */
AtomX 1:8e41a7b03f45 368 uint8_t temp = RfChip.PCD_ReadRegister(MFRC522::VersionReg);
AtomX 1:8e41a7b03f45 369 printf("MFRC522 version: %d\n\r", temp & 0x07);
AtomX 1:8e41a7b03f45 370 printf("\n\r");
AtomX 1:8e41a7b03f45 371
AtomX 0:1d9c7c0b5015 372 while(1)
AtomX 0:1d9c7c0b5015 373 {
AtomX 1:8e41a7b03f45 374 LedRed = 1;
AtomX 1:8e41a7b03f45 375 LedGreen = 1;
AtomX 1:8e41a7b03f45 376
AtomX 0:1d9c7c0b5015 377 // Look for new cards
AtomX 0:1d9c7c0b5015 378 if ( ! RfChip.PICC_IsNewCardPresent())
AtomX 0:1d9c7c0b5015 379 {
AtomX 1:8e41a7b03f45 380 wait_ms(500);
AtomX 0:1d9c7c0b5015 381 continue;
AtomX 0:1d9c7c0b5015 382 }
AtomX 0:1d9c7c0b5015 383
AtomX 1:8e41a7b03f45 384 LedRed = 0;
AtomX 1:8e41a7b03f45 385
AtomX 0:1d9c7c0b5015 386 // Select one of the cards
AtomX 0:1d9c7c0b5015 387 if ( ! RfChip.PICC_ReadCardSerial())
AtomX 0:1d9c7c0b5015 388 {
AtomX 1:8e41a7b03f45 389 wait_ms(500);
AtomX 0:1d9c7c0b5015 390 continue;
AtomX 0:1d9c7c0b5015 391 }
AtomX 0:1d9c7c0b5015 392
AtomX 1:8e41a7b03f45 393 LedRed = 1;
AtomX 1:8e41a7b03f45 394 LedGreen = 0;
AtomX 1:8e41a7b03f45 395
AtomX 0:1d9c7c0b5015 396 // Dump debug info about the card. PICC_HaltA() is automatically called.
AtomX 0:1d9c7c0b5015 397 DumpToSerial(&(RfChip.uid));
AtomX 1:8e41a7b03f45 398 wait_ms(200);
AtomX 0:1d9c7c0b5015 399 }
AtomX 0:1d9c7c0b5015 400 }