﻿/ *
 * Documentation: RFID.pde
 * Created: Dr.Leong (WWW.B2CQSHOP.COM)
 * Creation Date: 2011.09.19
 * Modified:
 * Modified:
 * Description: Mifarel find cards → anti-collision → election card → to read and write interface
 * /
 / / The sensor communicates using the SPI, so include the the library:
# Include <SPI.h>


# Define uchar, an unsigned char
# Define uint, an unsigned int


/ / Maximum length of an array
# Define MAX_LEN 16


/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / Set the pin
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
const int chipSelectPin = 53;
const int NRSTPD = 5;


/ / The MF522 command word
# Define PCD_IDLE 0x00 / / NO action; cancel the current command
# The define PCD_AUTHENT 0x0E / / authentication key
# The define PCD_RECEIVE 0x08 / / receive data
# The define PCD_TRANSMIT 0x04 / / send data
# The define PCD_TRANSCEIVE 0x0C / / send and receive data
# The define PCD_RESETPHASE 0x0F / / reset
# The define PCD_CALCCRC 0x03 / / CRC calculation


/ / Mifare_One card command word
# The define PICC_REQIDL 0x26 / / look for antenna region does not enter hibernation
# The define PICC_REQALL 0x52 / / look for the antenna all the cards in the region
# The define PICC_ANTICOLL 0x93 / / anti-collision
# The define PICC_SElECTTAG 0x93 / / election card
# The define PICC_AUTHENT1A 0x60 / / Verify A key
# The define PICC_AUTHENT1B 0x61 / / verify the B key
# Define PICC_READ 0x30 / / read block
# Define PICC_WRITE, 0xA0 / / write block
# The define PICC_DECREMENT 0xC0 / / chargeback
# The define PICC_INCREMENT 0xC1 / / recharge
# Define PICC_RESTORE 0xC2 / / adjust the block data to buffer
# Define PICC_TRANSFER, 0xB0 / / save the buffer data
# Define PICC_HALT, 0x50 / / sleep




/ / And the MF522 communication error code returned
# Define MI_OK 0
# Define MI_NOTAGERR 1
# Define MI_ERR 2




/ / The ------------------ MFRC522 register ---------------
/ / 0: Command and the Status
# Define Reserved00 0x00
# The define CommandReg 0x01
# The define CommIEnReg 0x02
# The define DivlEnReg 0x03
# The define CommIrqReg 0x04
# The define DivIrqReg 0x05
# The define ErrorReg 0x06
# The define Status1Reg 0x07
# The define Status2Reg 0x08
# The define FIFODataReg 0x09
# The define FIFOLevelReg 0x0A
# Define WaterLevelReg 0x0B
# The define ControlReg 0x0C
# The define BitFramingReg 0x0D
# The define CollReg 0x0E
# Define Reserved01 0x0F
/ / Page 1: Command
# Define Reserved10 0x10
# The define ModeReg 0x11
# The define TxModeReg 0x12
# The define RxModeReg 0x13
# The define TxControlReg 0x14
# The define TxAutoReg 0x15
# The define TxSelReg 0x16
# The define RxSelReg 0x17
# The define RxThresholdReg 0x18
# The define DemodReg 0x19
# Define Reserved11 0x1A
# The define Reserved12 0x1B
# The define MifareReg 0x1C
# The define Reserved13 0x1D
# Define Reserved14 0x1E
# The define SerialSpeedReg 0x1F
/ / Page 2: of CFG
# Define Reserved20 0x20
# The define CRCResultRegM 0x21
# The define CRCResultRegL 0x22
# Define Reserved21 0x23
# The define ModWidthReg 0x24
# The define Reserved22 0x25
# The define RFCfgReg 0x26
# The define GsNReg 0x27
# The define CWGsPReg 0x28
# The define ModGsPReg 0x29
# Define TModeReg 0x2A
# Define TPrescalerReg 0x2B
# Define TReloadRegH 0x2C
# The define TReloadRegL 0x2D
# The define TCounterValueRegH 0x2E
# The define TCounterValueRegL 0x2F
/ / Page 3: TestRegister
# Define Reserved30 0x30
# The define TestSel1Reg 0x31
# The define TestSel2Reg 0x32
# The define TestPinEnReg 0x33
# The define TestPinValueReg 0x34
# The define TestBusReg 0x35
# The define AutoTestReg 0x36
# The define VersionReg 0x37
# The define AnalogTestReg 0x38
# The define TestDAC1Reg 0x39
# Define TestDAC2Reg 0x3A
# Define TestADCReg 0x3B
# Define Reserved31 0x3C
# The define Reserved32 0x3D
# The define Reserved33 0x3E
# Define Reserved34 0x3F
/ / -----------------------------------------------


/ / 4-byte card serial number, 5 byte checksum byte
uchar, serNum [5];


uchar writeData [16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100}; / / initialize the 100 yuan
uchar moneyConsume = 18; / / consumption of 18 yuan
uchar moneyAdd = 10; / / recharge 10 yuan
/ / Sector A password, 16 sectors, each sector password 6Byte
 uchar sectorKeyA [16] [16] = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
                             {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
                             / / {0x19, 0x84, 0x07, 0x15, 0x76, 0x14},
                             {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
                            ;}
 uchar sectorNewKeyA [16] [16] = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
                                {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0x07, 0x80, 0x69, 0x19, 0x84, 0x07, 0x15, 0x76, 0x14},
                                 / / You can set another ket, such as "0x19, 0x84, 0x07, 0x15, 0x76, 0x14"
                                 / / {0x19, 0x84, 0x07, 0x15, 0x76, 0x14, 0xff, 0x07, 0x80, 0x69, 0x19, 0x84, 0x07, 0x15, 0x76, 0x14},
                                 / / But when loop, please set the sectorKeyA, the same key, so that RFID module can read the card
                                {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0x07, 0x80, 0x69, 0x19, 0x33, 0x07, 0x15, 0x34, 0x14},
                               ;}


void setup () {
   Serial.begin (9600); / / RFID reader SOUT pin connected to Serial RX pin at 2400bps
 / / Start the the SPI the library:
  SPI.begin ();
  
  pinMode (chipSelectPin, OUTPUT); / / Set digital pin 10 as OUTPUT to connect it to the RFID / ENABLE pin
    digitalWrite (chipSelectPin, LOW); / / Activate the RFID reader
  pinMode (NRSTPD, OUTPUT); / / Set digital pin 10, Not Reset and Power-down
    digitalWrite (NRSTPD, HIGH);


  MFRC522_Init ();
}


void loop ()
{
  uchar, i, tmp;
uchar, the status;
        uchar str [MAX_LEN];
        uchar RC_size;
        uchar blockAddr; / / select the operating block address 0 to 63




/ / Look for the card, return the card type
status = MFRC522_Request (PICC_REQIDL, str);
if (status == MI_OK)
{
                        Serial.println ("Find out a card");
Serial.print (str [0], BIN);
                        Serial.print (",");
Serial.print (str [1], BIN);
                        Serial.println ("");
}


/ / Anti-collision, return the card serial number 4-byte
status = MFRC522_Anticoll (str);
the memcpy (serNum, str, 5);
if (status == MI_OK)
{


                        Serial.println ("The card's number is:");
Serial.print (serNum [0], BIN);
                        Serial.print (",");
Serial.print (serNum [1], BIN);
                        Serial.print (",");
Serial.print (serNum [2], BIN);
                        Serial.print (",");
Serial.print (serNum [3], BIN);
                        Serial.print (",");
Serial.print (serNum [4], BIN);
                        Serial.println ("");
}


/ / Election card, return the card capacity
RC_size = MFRC522_SelectTag (serNum);
if (RC_size! = 0)


{
                        Serial.print ("The size of the card is:");
Serial.print (RC_size, DEC);
                        Serial.println ("K bits");
}
                
/ / Registration card
blockAddr = 7; / / data block 7
status = MFRC522_Auth (PICC_AUTHENT1A, blockAddr, sectorKeyA [blockAddr / 4], serNum); / / authentication
if (status == MI_OK)
{
/ / Write data
status = MFRC522_Write (blockAddr, sectorNewKeyA [blockAddr / 4]);
                        Serial.print ("set the new card password, and can modify the data of the Sector");
                        Serial.print (blockAddr / 4, DEC);
                        Serial.println (":");
for (i = 0; i <6; i + +)
{
              Serial.print (sectorNewKeyA [blockAddr / 4] [i], HEX);
                            Serial.print (",");
}
                        Serial.println ("");
                        blockAddr = blockAddr - 3;
                        status = MFRC522_Write (blockAddr, writeData);
                        if (status == MI_OK)
                        {
                           Serial.println ("You are B2CQSHOP VIP Member, The card has $ 100!");
                        }
}


/ / Card Reader
blockAddr = 7; / / data block 7
status = MFRC522_Auth (PICC_AUTHENT1A, blockAddr, sectorNewKeyA [blockAddr / 4], serNum); / / authentication
if (status == MI_OK)
{
/ / Read data
                        blockAddr = blockAddr - 3;
                        status = MFRC522_Read (blockAddr, str);
if (status == MI_OK)
{
                                Serial.println ("Read from the card, the data is:");
for (i = 0; i <16; i + +)
{
              Serial.print (str [i], DEC);
                                      Serial.print (",");
}
                                Serial.println ("");
}
}


                / / Consumer
blockAddr = 7; / / data block 7
status = MFRC522_Auth (PICC_AUTHENT1A, blockAddr, sectorNewKeyA [blockAddr / 4], serNum); / / authentication
if (status == MI_OK)
{
/ / Read data
                        blockAddr = blockAddr - 3;
status = MFRC522_Read (blockAddr, str);
if (status == MI_OK)
{
                          if (str [15] <moneyConsume)
                          {
                              Serial.println ("The money is not enough!");
                          }
                          else
                          {
                              str [15] = str [15] - moneyConsume;
                              status = MFRC522_Write (blockAddr, str);
                              if (status == MI_OK)
                              {
                                 Serial.print ("You pay $ 18 for items in B2CQSHOP.COM. Now, Your money balance is: $");
              Serial.print (str [15], DEC);
                                 Serial.println ("");
                              }
                          }
}
}


                / / Recharge
blockAddr = 7; / / data block 7
status = MFRC522_Auth (PICC_AUTHENT1A, blockAddr, sectorNewKeyA [blockAddr / 4], serNum); / / authentication
if (status == MI_OK)
{
/ / Read data
                        blockAddr = blockAddr - 3;
status = MFRC522_Read (blockAddr, str);
if (status == MI_OK)
{
                          tmp = (int) (str [15] + moneyAdd);
                          / / Serial.println (tmp, DEC);
                          if (tmp <(char) 254)
                          {
                              Serial.println ("The money of the card can not be more than 255!");
                          }
                          else
                          {
                              str [15] = str [15] + moneyAdd;
                              status = MFRC522_Write (blockAddr, str);
                              if (status == MI_OK)
                              {
                                 Serial.print ("You add $ 10 to your card in B2CQSHOP.COM, Your money balance is: $");
              Serial.print (str [15], DEC);
                                 Serial.println ("");
                              }
                          }
}
}
                Serial.println ("");
MFRC522_Halt (); / / command card into hibernation
          
}


/ *
 * Function: Write_MFRC5200
 * Description: MFRC522 of a register to write a byte of data
 * Input parameters: addr - register address; val - value to be written
 * Return value:
 * /
void Write_MFRC522 (uchar addr, uchar val)
{
digitalWrite (chipSelectPin, LOW);


/ / Address format: 0XXXXXX0,
SPI.transfer ((addr << 1) & 0x7E);
SPI.transfer (val);


digitalWrite (chipSelectPin, HIGH);
}




/ *
 * Function: Read_MFRC522
 * Description: a byte of data read from the MFRC522 of a register
 * Input Parameters: addr - register address
 * Return value: Returns a byte of data read
 * /
uchar Read_MFRC522 (uchar addr)
{
uchar, val;


digitalWrite (chipSelectPin, LOW);


/ / Address format: 1XXXXXX0,
SPI.transfer (((addr << 1) & 0x7E) | 0x80);
val = SPI.transfer (0x00);


digitalWrite (chipSelectPin, HIGH);


return val;
}


/ *
 * Letter of several: SetBitMask
 * Description: set RC522 register bit
 * Input parameters: reg - register address; mask - set value
 * Return value:
 * /
void SetBitMask (uchar reg, uchar mask)
{
    uchar, tmp,;
    tmp = Read_MFRC522 (reg);
    Write_MFRC522 (reg, tmp | mask); / / set bit mask
}




/ *
 * Letter of several: ClearBitMask
 * Description: clear RC522 register bit
 * Input parameters: the address of the reg - register; mask - clear bit value
 * Return value:
 * /
void ClearBitMask (uchar reg, uchar mask)
{
    uchar, tmp,;
    tmp = Read_MFRC522 (reg);
    Write_MFRC522 (reg, tmp & (~ mask)); / / clear bit mask
}




/ *
 * Function: AntennaOn
 * Description: open the antenna each time you start or shut down the natural barrier between the emission should be at least 1ms intervals
 * Input parameters: None
 * Return value:
 * /
void AntennaOn (void)
{
uchar, the temp;


temp = Read_MFRC522 (TxControlReg);
if ((temp & 0x03))
{
SetBitMask (TxControlReg, 0x03);
}
}




/ *
 Function: AntennaOff the
 * Description: close the antenna every time you start or shut down the natural barrier between the emission should be at least 1ms intervals
 * Input parameters: None
 * Return value:
 * /
void AntennaOff (void)
{
ClearBitMask (TxControlReg, 0x03);
}




/ *
 * Function: ResetMFRC522
 * Description: Reset RC522
 * Input parameters: None
 * Return value:
 * /
void MFRC522_Reset (void)
{
    Write_MFRC522 (CommandReg, PCD_RESETPHASE);
}




/ *
 * Function: InitMFRC522
 * Description: initialization RC522
 * Input parameters: None
 * Return value:
 * /
the void MFRC522_Init (void)
{
digitalWrite (NRSTPD, HIGH);


MFRC522_Reset ();


/ / Timer: TPrescaler * TreloadVal/6.78MHz = 24ms
    Write_MFRC522 (TModeReg, 0x8D); / / Tauto = 1; f (Timer) = 6.78MHz/TPreScaler
    Write_MFRC522 (TPrescalerReg, 0x3E); / / TModeReg [3 .. 0] + TPrescalerReg
    Write_MFRC522 (TReloadRegL, 30);
    Write_MFRC522 (TReloadRegH, 0);


Write_MFRC522 (TxAutoReg, 0x40); / / 100% ASK
Write_MFRC522 (ModeReg, 0x3D); / / CRC initial value of 0x6363???


/ / ClearBitMask (Status2Reg, 0x08); / / MFCrypto1On = 0
/ / Write_MFRC522 (RxSelReg, 0x86); / / RxWait = RxSelReg [5 .. 0]
/ / Write_MFRC522 (RFCfgReg, 0x7F); / / RxGain = 48dB


AntennaOn (); / / open the antenna
}




/ *
 * Function: MFRC522_Request
 * Description: look for the card, read the card type
 * Enter parameters: reqMode, - to find the card the way,
 * TagType - return type of card
 * 0x4400 = Mifare_UltraLight
 * 0x0400 = Mifare_One (S50)
 * 0x0200 = Mifare_One (S70)
 * 0x0800 = Mifare_Pro (X)
 * 0x4403 = Mifare_DESFire
 * Return values: successful return MI_OK
 * /
uchar MFRC522_Request (uchar reqMode, uchar * TagType)
{
uchar, the status;
the uint backBits; / / the received data bits


Write_MFRC522 (BitFramingReg, 0x07); / / TxLastBists = BitFramingReg [2 .. 0]???


TagType [0] = reqMode;
status = MFRC522_ToCard (PCD_TRANSCEIVE, TagType, 1, TagType, & backBits);


if ((status! = MI_OK) | | (backBits! = 0x10))
{
status = MI_ERR;
}
   
return status;
}




/ *
 * Letter: MFRC522_ToCard
 * Description: RC522 and ISO14443 card communication
 * Input Parameters: command - MF522 command word,
 * SendData - RC522 sent to the card data
 The * sendLen - Send data length
 * BackData card - received data is returned,
 * BackLen - Returns the length of the data bits
 * Return values: successful return MI_OK
 * /
uchar MFRC522_ToCard (uchar command, uchar * sendData, uchar sendLen, uchar * backData, uint * backLen)
{
    uchar status = MI_ERR;
    uchar irqEn = 0x00;
    uchar waitIRq = 0x00;
    uchar lastBits;
    uchar, n-;
    uint, i;


    the switch (command)
    {
        case PCD_AUTHENT: / / certification card secret
{
irqEn = 0x12;
waitIRq = 0x10;
break;
}
the case PCD_TRANSCEIVE: / / transmit FIFO data
{
irqEn = 0x77;
waitIRq = 0x30;
break;
}
default:
break;
    }
   
    Write_MFRC522 (CommIEnReg, irqEn | 0x80); / / allow the interrupt request
    ClearBitMask (CommIrqReg, 0x80); / / Clear all interrupt request bit
    SetBitMask (FIFOLevelReg, 0x80); / / FlushBuffer 1, the FIFO initialization
    
Write_MFRC522 (CommandReg, PCD_IDLE); / / NO action; to cancel the current command???


/ / Write data to the FIFO
    for (i = 0; i <sendLen; i + +)
    {
Write_MFRC522 (FIFODataReg, sendData [i]);
}


/ / Execute the command
Write_MFRC522 (CommandReg, command);
    if (command == PCD_TRANSCEIVE)
    {
SetBitMask (BitFramingReg, 0x80); / / StartSend = 1, transmission of data starts
}
    
/ / Wait for data is received
i = 2000; / / i according to the clock frequency adjustment, operation M1 card maximum waiting time of 25ms???
    do
    {
/ / CommIrqReg [7 .. 0]
/ / Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
        n = Read_MFRC522 (CommIrqReg);
        i -;
    }
    while ((i! = 0) &&! (n & 0x01) &&! (n & waitIRq));


    ClearBitMask (BitFramingReg, 0x80); / / StartSend = 0


    if (i = 0)
    {
        if (! (Read_MFRC522 (ErrorReg) & 0x1B)) / / BufferOvfl Collerr CRCErr ProtecolErr
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {
status = MI_NOTAGERR; / /??
}


            if (command == PCD_TRANSCEIVE)
            {
               n = Read_MFRC522 (FIFOLevelReg);
              lastBits = Read_MFRC522 (ControlReg) & 0x07;
                if (lastBits)
                {
* BackLen = (n-1) * 8 + lastBits;
}
                else
                {
* BackLen = n * 8;
}


                if (n == 0)
                {
n = 1;
}
                if (n> MAX_LEN)
                {
n = MAX_LEN;
}


/ / Read the received data in the FIFO
                for (i = 0; i <n; i + +)
                {
backData [i] = Read_MFRC522 (FIFODataReg);
}
            }
        }
        else
        {
status = MI_ERR;
}
        
    }


    / / SetBitMask (ControlReg, 0x80); / / timer stops
    / / Write_MFRC522 (CommandReg, PCD_IDLE);


    return status;
}




/ *
 * Function: MFRC522_Anticoll
 * Description: anti-collision detection, and read the card serial number of the selected card
 * Input parameters: serNum - return to the 4-byte card serial number, the first 5 bytes of the checksum byte
 * Return values: successful return MI_OK
 * /
uchar MFRC522_Anticoll (uchar * serNum)
{
    uchar, the status;
    uchar, i;
uchar serNumCheck = 0;
    uint unLen;
    


    / / ClearBitMask (Status2Reg, 0x08); / / TempSensclear
    / / ClearBitMask (CollReg, 0x80); / / ValuesAfterColl
Write_MFRC522 (BitFramingReg, 0x00); / / TxLastBists = BitFramingReg [2 .. 0]
 
    serNum [0] = PICC_ANTICOLL;
    serNum [1] = 0x20;
    status = MFRC522_ToCard (PCD_TRANSCEIVE, serNum, 2, serNum, & unLen);


    if (status == MI_OK)
{
/ / Check card serial number
for (i = 0; i <4; i + +)
{
serNumCheck ^ = serNum [i];
}
if (serNumCheck! = serNum [i])
{
status = MI_ERR;
}
    }


    / / SetBitMask (CollReg, 0x80); / / ValuesAfterColl = 1


    return status;
}




/ *
 * Function: CalulateCRC
 * Function Description: MF522 calculate the CRC
 * Input parameters: pIndata - to be reading a CRC data, len - the length of the data, pOutData - calculated CRC results
 * Return value:
 * /
void CalulateCRC (uchar * pIndata, uchar len, uchar * pOutData)
{
    uchar, i, n;


    ClearBitMask (DivIrqReg, 0x04); / / CRCIrq = 0
    SetBitMask (FIFOLevelReg, 0x80); / / clear FIFO pointer
    / / Write_MFRC522 (CommandReg, PCD_IDLE);


/ / Write data to the FIFO
    for (i = 0; i <len; i + +)
    {
Write_MFRC522 (FIFODataReg, * (pIndata + i));
}
    Write_MFRC522 (CommandReg, PCD_CALCCRC);


/ / Wait for the CRC calculation is done
    i = 0xFF;
    do
    {
        n = Read_MFRC522 (DivIrqReg);
        i -;
    }
    while ((i! = 0) &&! (n & 0x04)); / / CRCIrq = 1


/ / Read the CRC calculation results
    pOutData [0] = Read_MFRC522 (CRCResultRegL);
    pOutData [1] = Read_MFRC522 (CRCResultRegM);
}




/ *
 * Function: MFRC522_SelectTag
 * Description: election card, read the card memory capacity
 * Input parameters: serNum - incoming card serial number
 * Return values: successful return to card capacity
 * /
uchar MFRC522_SelectTag (uchar * serNum)
{
    uchar, i;
uchar, the status;
uchar, size;
    uint recvBits;
    uchar, buffer [9];


/ / ClearBitMask (Status2Reg, 0x08); / / MFCrypto1On = 0


    buffer [0] = PICC_SElECTTAG;
    buffer [1] = 0x70;
    for (i = 0; i <5; i + +)
    {
    buffer [i +2] = * (serNum + i);
    }
CalulateCRC (buffer, 7, & buffer [7]); / /??
    status = MFRC522_ToCard (PCD_TRANSCEIVE, buffer, 9, buffer, & recvBits);
    
    if ((status == MI_OK) && (recvBits == 0x18))
    {
size = buffer [0];
}
    else
    {
size = 0;
}


    return size;
}




/ *
 * Function: MFRC522_Auth
 * Description: Verify that the card password
 * Input parameters: authMode - Password Authentication Mode
                 0x60 = verify A key
                 0x61 = verify the B key
             BlockAddr - block address
             Sectorkey - sectors password
             serNum - Card serial number, 4 bytes
 * Return values: successful return MI_OK
 * /
uchar MFRC522_Auth (uchar authMode, uchar BlockAddr, uchar * Sectorkey, uchar * serNum)
{
    uchar, the status;
    uint recvBits;
    uchar, i;
uchar, buff [12];


/ / Verify instruction block address + sectors password + card serial number
    buff [0] = authMode;
    buff [1] = BlockAddr;
    for (i = 0; i <6; i + +)
    {
buff [i +2] = * (Sectorkey + i);
}
    for (i = 0; i <4; i + +)
    {
buff [i +8] = * (serNum + i);
}
    status = MFRC522_ToCard (PCD_AUTHENT, buff, 12, buff, & recvBits);


    if ((status! = MI_OK) | | (! (Read_MFRC522 (Status2Reg) & 0x08)))
    {
status = MI_ERR;
}
    
    return status;
}




/ *
 * Function: MFRC522_Read
 * Description: Read block data
 * Input parameters: blockAddr - block address; recvData - read a block data
 * Return values: successful return MI_OK
 * /
uchar MFRC522_Read (uchar blockAddr, uchar * recvData)
{
    uchar, the status;
    uint unLen;


    recvData [0] = PICC_READ;
    recvData [1] = blockAddr;
    CalulateCRC (recvData, 2, & recvData [2]);
    status = MFRC522_ToCard (PCD_TRANSCEIVE, recvData, 4, recvData, & unLen);


    if ((status! = MI_OK) | | (unLen! = 0x90))
    {
        status = MI_ERR;
    }
    
    return status;
}




/ *
 * Function: MFRC522_Write
 * Description: Write block data
 * Enter parameters: blockAddr, - block address; writeData to write 16 bytes of data - to block
 * Return values: successful return MI_OK
 * /
uchar MFRC522_Write (uchar blockAddr, uchar * writeData)
{
    uchar, the status;
    uint recvBits;
    uchar, i;
uchar, buff [18];
    
    buff [0] = PICC_WRITE;
    buff [1] = blockAddr;
    CalulateCRC (buff, 2, & buff [2]);
    status = MFRC522_ToCard (PCD_TRANSCEIVE, buff, 4, buff, & recvBits);


    if ((status! = MI_OK) | | (recvBits! = 4) | | ((buff [0] & 0x0F)! = 0x0A))
    {
status = MI_ERR;
}
        
    if (status == MI_OK)
    {
        for (i = 0; i <16; i + +) / / write to the FIFO 16 Byte data
        {
        buff [i] = * (writeData + i);
        }
        CalulateCRC (buff, 16, & buff [16]);
        status = MFRC522_ToCard (PCD_TRANSCEIVE, buff, 18, buff, & recvBits);
        
if ((status! = MI_OK) | | (recvBits! = 4) | | ((buff [0] & 0x0F)! = 0x0A))
        {
status = MI_ERR;
}
    }
    
    return status;
}




/ *
 * Function: MFRC522_Halt
 * Description: command card into hibernation
 * Input parameters: None
 * Return value:
 * /
the void MFRC522_Halt (void)
{
uchar, the status;
    uint unLen;
    uchar, buff [4];


    buff [0] = PICC_HALT;
    buff [1] = 0;
    CalulateCRC (buff, 2, & buff [2]);
 
    status = MFRC522_ToCard (PCD_TRANSCEIVE, buff, 4, buff, & unLen);
}