DANIE BRINK / Mbed 2 deprecated FRDM_MFRC522

Dependencies:   MFRC522 mbed

Fork of FRDM_MFRC522 by Martin Olejar

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