Martin Olejar / Mbed 2 deprecated FRDM_MFRC522

Dependencies:   MFRC522 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "MFRC522.h"
00003 
00004 #if defined(TARGET_KL25Z)
00005 
00006 /* KL25Z Pins for MFRC522 SPI interface */
00007 #define SPI_MOSI    PTC6
00008 #define SPI_MISO    PTC7
00009 #define SPI_SCLK    PTC5
00010 #define SPI_CS      PTC4
00011 
00012 /* KL25Z Pin for MFRC522 reset */
00013 #define MF_RESET    PTC3
00014 
00015 /* KL25Z Pins for UART Debug port */
00016 #define UART_RX     PTA1
00017 #define UART_TX     PTA2
00018 
00019 #elif defined(TARGET_LPC11U24)
00020 
00021 /* LPC11U24 Pins for MFRC522 SPI interface */
00022 #define SPI_MOSI    P0_9
00023 #define SPI_MISO    P0_8
00024 #define SPI_SCLK    P1_29
00025 #define SPI_CS      P0_2
00026 
00027 /* LPC11U24 Pin for MFRC522 reset */
00028 #define MF_RESET    P1_13
00029 
00030 /* LPC11U24 Pins for UART Debug port */
00031 #define UART_RX     P0_18
00032 #define UART_TX     P0_19
00033 
00034 /* LED Pins */
00035 #define LED_RED     P0_7
00036 #define LED_GREEN   P1_22
00037 
00038 #endif
00039 
00040 DigitalOut LedRed   (LED_RED);
00041 DigitalOut LedGreen (LED_GREEN);
00042 
00043 Serial     DebugUART(UART_TX, UART_RX);
00044 MFRC522    RfChip   (SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, MF_RESET);
00045 
00046 /* Local functions */
00047 void DumpMifareClassicToSerial      (MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key);
00048 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector);
00049 void DumpMifareUltralightToSerial   (void);
00050 
00051 /**
00052  * Dumps debug info about the selected PICC to Serial.
00053  * On success the PICC is halted after dumping the data.
00054  * For MIFARE Classic the factory default key of 0xFFFFFFFFFFFF is tried.
00055  */
00056 void DumpToSerial(MFRC522::Uid *uid)
00057 {
00058   MFRC522::MIFARE_Key key;
00059 
00060   // UID
00061   printf("Card UID: ");
00062   for (uint8_t i = 0; i < uid->size; i++)
00063   {
00064     printf(" %X02", uid->uidByte[i]);
00065   }
00066   printf("\n\r");
00067 
00068   // PICC type
00069   uint8_t piccType = RfChip.PICC_GetType(uid->sak);
00070   printf("PICC Type: %s \n\r", RfChip.PICC_GetTypeName(piccType));
00071 
00072 
00073   // Dump contents
00074   switch (piccType)
00075   {
00076     case MFRC522::PICC_TYPE_MIFARE_MINI:
00077     case MFRC522::PICC_TYPE_MIFARE_1K:
00078     case MFRC522::PICC_TYPE_MIFARE_4K:
00079       // All keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
00080       for (uint8_t i = 0; i < 6; i++) { key.keyByte[i] = 0xFF; }
00081       DumpMifareClassicToSerial(uid, piccType, &key);
00082       break;
00083 
00084     case MFRC522::PICC_TYPE_MIFARE_UL:
00085       DumpMifareUltralightToSerial();
00086       break;
00087 
00088     case MFRC522::PICC_TYPE_ISO_14443_4:
00089     case MFRC522::PICC_TYPE_ISO_18092:
00090     case MFRC522::PICC_TYPE_MIFARE_PLUS:
00091     case MFRC522::PICC_TYPE_TNP3XXX:
00092       printf("Dumping memory contents not implemented for that PICC type. \n\r");
00093       break;
00094 
00095     case MFRC522::PICC_TYPE_UNKNOWN:
00096     case MFRC522::PICC_TYPE_NOT_COMPLETE:
00097     default:
00098       break; // No memory dump here
00099   }
00100 
00101   printf("\n\r");
00102 
00103   RfChip.PICC_HaltA(); // Already done if it was a MIFARE Classic PICC.
00104 } // End PICC_DumpToSerial()
00105 
00106 /**
00107  * Dumps memory contents of a MIFARE Classic PICC.
00108  * On success the PICC is halted after dumping the data.
00109  */
00110 void DumpMifareClassicToSerial(MFRC522::Uid *uid, uint8_t piccType, MFRC522::MIFARE_Key *key)
00111 {
00112   uint8_t no_of_sectors = 0;
00113   switch (piccType)
00114   {
00115     case MFRC522::PICC_TYPE_MIFARE_MINI:
00116       // Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
00117       no_of_sectors = 5;
00118       break;
00119 
00120     case MFRC522::PICC_TYPE_MIFARE_1K:
00121       // Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
00122       no_of_sectors = 16;
00123       break;
00124 
00125     case MFRC522::PICC_TYPE_MIFARE_4K:
00126       // Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
00127       no_of_sectors = 40;
00128       break;
00129 
00130     default:
00131       // Should not happen. Ignore.
00132       break;
00133   }
00134 
00135   // Dump sectors, highest address first.
00136   if (no_of_sectors)
00137   {
00138     printf("Sector  Block   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  AccessBits \n\r");
00139     printf("----------------------------------------------------------------------------------------- \n\r");
00140     for (uint8_t i = no_of_sectors - 1; i > 0; i--)
00141     {
00142       DumpMifareClassicSectorToSerial(uid, key, i);
00143     }
00144   }
00145 
00146   RfChip.PICC_HaltA(); // Halt the PICC before stopping the encrypted session.
00147   RfChip.PCD_StopCrypto1();
00148 } // End PICC_DumpMifareClassicToSerial()
00149 
00150 /**
00151  * Dumps memory contents of a sector of a MIFARE Classic PICC.
00152  * Uses PCD_Authenticate(), MIFARE_Read() and PCD_StopCrypto1.
00153  * Always uses PICC_CMD_MF_AUTH_KEY_A because only Key A can always read the sector trailer access bits.
00154  */
00155 void DumpMifareClassicSectorToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key, uint8_t sector)
00156 {
00157   uint8_t status;
00158   uint8_t firstBlock;    // Address of lowest address to dump actually last block dumped)
00159   uint8_t no_of_blocks;    // Number of blocks in sector
00160   bool    isSectorTrailer; // Set to true while handling the "last" (ie highest address) in the sector.
00161 
00162   // The access bits are stored in a peculiar fashion.
00163   // There are four groups:
00164   //    g[3]  Access bits for the sector trailer, block 3 (for sectors 0-31) or block 15 (for sectors 32-39)
00165   //    g[2]  Access bits for block 2 (for sectors 0-31) or blocks 10-14 (for sectors 32-39)
00166   //    g[1]  Access bits for block 1 (for sectors 0-31) or blocks 5-9 (for sectors 32-39)
00167   //    g[0]  Access bits for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39)
00168   // Each group has access bits [C1 C2 C3]. In this code C1 is MSB and C3 is LSB.
00169   // The four CX bits are stored together in a nible cx and an inverted nible cx_.
00170   uint8_t c1, c2, c3;      // Nibbles
00171   uint8_t c1_, c2_, c3_;   // Inverted nibbles
00172   bool    invertedError = false;   // True if one of the inverted nibbles did not match
00173   uint8_t g[4];            // Access bits for each of the four groups.
00174   uint8_t group;           // 0-3 - active group for access bits
00175   bool    firstInGroup;    // True for the first block dumped in the group
00176 
00177   // Determine position and size of sector.
00178   if (sector < 32)
00179   { // Sectors 0..31 has 4 blocks each
00180     no_of_blocks = 4;
00181     firstBlock = sector * no_of_blocks;
00182   }
00183   else if (sector < 40)
00184   { // Sectors 32-39 has 16 blocks each
00185     no_of_blocks = 16;
00186     firstBlock = 128 + (sector - 32) * no_of_blocks;
00187   }
00188   else
00189   { // Illegal input, no MIFARE Classic PICC has more than 40 sectors.
00190     return;
00191   }
00192 
00193   // Dump blocks, highest address first.
00194   uint8_t byteCount;
00195   uint8_t buffer[18];
00196   uint8_t blockAddr;
00197   isSectorTrailer = true;
00198   for (uint8_t blockOffset = no_of_blocks - 1; blockOffset > 0; blockOffset--)
00199   {
00200     blockAddr = firstBlock + blockOffset;
00201 
00202     // Sector number - only on first line
00203     if (isSectorTrailer)
00204     {
00205       printf("  %2d   ", sector);
00206     }
00207     else
00208     {
00209       printf("       ");
00210     }
00211 
00212     // Block number
00213     printf(" %3d  ", blockAddr);
00214 
00215     // Establish encrypted communications before reading the first block
00216     if (isSectorTrailer)
00217     {
00218       status = RfChip.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, firstBlock, key, uid);
00219       if (status != MFRC522::STATUS_OK)
00220       {
00221         printf("PCD_Authenticate() failed: %s \r\n", RfChip.GetStatusCodeName(status));
00222         return;
00223       }
00224     }
00225 
00226     // Read block
00227     byteCount = sizeof(buffer);
00228     status = RfChip.MIFARE_Read(blockAddr, buffer, &byteCount);
00229     if (status != MFRC522::STATUS_OK)
00230     {
00231       printf("MIFARE_Read() failed: %s \r\n", RfChip.GetStatusCodeName(status));
00232       continue;
00233     }
00234 
00235     // Dump data
00236     for (uint8_t index = 0; index < 16; index++)
00237     {
00238       printf(" %3d", buffer[index]);
00239 //      if ((index % 4) == 3)
00240 //      {
00241 //        printf(" ");
00242 //      }
00243     }
00244 
00245     // Parse sector trailer data
00246     if (isSectorTrailer)
00247     {
00248       c1  = buffer[7] >> 4;
00249       c2  = buffer[8] & 0xF;
00250       c3  = buffer[8] >> 4;
00251       c1_ = buffer[6] & 0xF;
00252       c2_ = buffer[6] >> 4;
00253       c3_ = buffer[7] & 0xF;
00254       invertedError = (c1 != (~c1_ & 0xF)) || (c2 != (~c2_ & 0xF)) || (c3 != (~c3_ & 0xF));
00255 
00256       g[0] = ((c1 & 1) << 2) | ((c2 & 1) << 1) | ((c3 & 1) << 0);
00257       g[1] = ((c1 & 2) << 1) | ((c2 & 2) << 0) | ((c3 & 2) >> 1);
00258       g[2] = ((c1 & 4) << 0) | ((c2 & 4) >> 1) | ((c3 & 4) >> 2);
00259       g[3] = ((c1 & 8) >> 1) | ((c2 & 8) >> 2) | ((c3 & 8) >> 3);
00260       isSectorTrailer = false;
00261     }
00262 
00263     // Which access group is this block in?
00264     if (no_of_blocks == 4)
00265     {
00266       group = blockOffset;
00267       firstInGroup = true;
00268     }
00269     else
00270     {
00271       group = blockOffset / 5;
00272       firstInGroup = (group == 3) || (group != (blockOffset + 1) / 5);
00273     }
00274 
00275     if (firstInGroup)
00276     {
00277       // Print access bits
00278       printf("   [ %d %d %d ] ", (g[group] >> 2) & 1, (g[group] >> 1) & 1, (g[group] >> 0) & 1);
00279       if (invertedError)
00280       {
00281         printf(" Inverted access bits did not match! ");
00282       }
00283     }
00284 
00285     if (group != 3 && (g[group] == 1 || g[group] == 6))
00286     { // Not a sector trailer, a value block
00287       printf(" Addr = 0x%02X, Value = 0x%02X%02X%02X%02X", buffer[12],
00288                                                            buffer[3],
00289                                                            buffer[2],
00290                                                            buffer[1],
00291                                                            buffer[0]);
00292     }
00293 
00294     printf("\n\r");
00295   }
00296 
00297   return;
00298 } // End PICC_DumpMifareClassicSectorToSerial()
00299 
00300 /**
00301  * Dumps memory contents of a MIFARE Ultralight PICC.
00302  */
00303 void DumpMifareUltralightToSerial(void)
00304 {
00305   uint8_t status;
00306   uint8_t byteCount;
00307   uint8_t buffer[18];
00308   uint8_t i;
00309 
00310   printf("Page   0  1  2  3");
00311   // Try the mpages of the original Ultralight. Ultralight C has more pages.
00312   for (uint8_t page = 0; page < 16; page +=4)
00313   {
00314     // Read pages
00315     byteCount = sizeof(buffer);
00316     status = RfChip.MIFARE_Read(page, buffer, &byteCount);
00317     if (status != MFRC522::STATUS_OK)
00318     {
00319       printf("MIFARE_Read() failed: %s \n\r", RfChip.GetStatusCodeName(status));
00320       break;
00321     }
00322 
00323     // Dump data
00324     for (uint8_t offset = 0; offset < 4; offset++)
00325     {
00326       i = page + offset;
00327       printf(" %2d  ", i); // Pad with spaces
00328       for (uint8_t index = 0; index < 4; index++)
00329       {
00330         i = 4 * offset + index;
00331         printf(" %02X ", buffer[i]);
00332       }
00333 
00334       printf("\n\r");
00335     }
00336   }
00337 } // End PICC_DumpMifareUltralightToSerial()
00338 
00339 int main()
00340 {
00341   /* Set debug UART speed */
00342   DebugUART.baud(115200);
00343   printf("< mbed RFID demo >\n\r");
00344   printf("\n\r");
00345 
00346   /* Init. RC522 Chip */
00347   RfChip.PCD_Init();
00348 
00349   /* Read RC522 version */
00350   uint8_t temp = RfChip.PCD_ReadRegister(MFRC522::VersionReg);
00351   printf("MFRC522 version: %d\n\r", temp & 0x07);
00352   printf("\n\r");
00353 
00354   while(1)
00355   {
00356     LedRed   = 1;
00357     LedGreen = 1;
00358 
00359     // Look for new cards
00360     if ( ! RfChip.PICC_IsNewCardPresent())
00361     {
00362       wait_ms(500);
00363       continue;
00364     }
00365 
00366     LedRed   = 0;
00367 
00368     // Select one of the cards
00369     if ( ! RfChip.PICC_ReadCardSerial())
00370     {
00371       wait_ms(500);
00372       continue;
00373     }
00374 
00375     LedRed   = 1;
00376     LedGreen = 0;
00377 
00378     // Dump debug info about the card. PICC_HaltA() is automatically called.
00379     DumpToSerial(&(RfChip.uid));
00380     wait_ms(200);
00381   }
00382 }