Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of FRDM_MFRC522 by
main.cpp@2:1c050fb3fec0, 2016-10-21 (annotated)
- Committer:
- daniebrink
- Date:
- Fri Oct 21 13:32:28 2016 +0000
- Revision:
- 2:1c050fb3fec0
- Parent:
- 1:8e41a7b03f45
ADD TARGET_NUCLEO_F446ZE
Who changed what in which revision?
User | Revision | Line number | New 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 | } |