RFID

Dependents:   RoboticHackathon2 RoboticHackathonFINAL

Rfid.cpp

Committer:
iLyngklip
Date:
2014-04-07
Revision:
0:051708395e3c

File content as of revision 0:051708395e3c:


/******************************************************************************
 * Includes
 ******************************************************************************/
#include "mbed.h"
#include "Rfid.h"

/******************************************************************************
 * User API
 ******************************************************************************/

#define uchar unsigned char
/**
 * Construct RFID
 * int chipSelectPin RFID /ENABLE pin
 */
RFID::RFID() : _rfid(PTD2, PTD3, PTD1), _chipSelectPin(PTD0), _NRSTPD(PTD5) 
{
    
}
/******************************************************************************
 * User API
 ******************************************************************************/

void RFID::check()
    {
        
        uchar status;
        uchar str[MAX_LEN];
        status = MFRC522Request(PICC_REQIDL, str); 
        if (status == MI_OK)
        {
            //Prevent conflict, return the 4 bytes Serial number of the card
            status = anticoll(str);
            memcpy(serNum, str, 5);
            if (status == MI_OK){
            card = (serNum[0]+serNum[1]);
            }
            
        }
        else {card=0;}
    }
        
/******************************************************************************
 * Dr.Leong   ( WWW.B2CQSHOP.COM )
 ******************************************************************************/

void RFID::init()
{
    _NRSTPD =1;

    reset();
        
    //Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
    writeMFRC522(TModeReg, 0x8D);       //Tauto=1; f(Timer) = 6.78MHz/TPreScaler
    writeMFRC522(TPrescalerReg, 0x3E);  //TModeReg[3..0] + TPrescalerReg
    writeMFRC522(TReloadRegL, 30);           
    writeMFRC522(TReloadRegH, 0);
    
    writeMFRC522(TxAutoReg, 0x40);      //100%ASK
    writeMFRC522(ModeReg, 0x3D);        // CRC valor inicial de 0x6363
    writeMFRC522(CommIEnReg, 0x00);     //Enable Rx interupt
    writeMFRC522(DivlEnReg, 0x08);      //IRQ is standar CMOS output
    writeMFRC522(CommIrqReg, 0x20);     //IRQ on end of valid data stream
    writeMFRC522(DivIrqReg, 0x08);
    //ClearBitMask(Status2Reg, 0x08);   //MFCrypto1On=0
    //writeMFRC522(RxSelReg, 0x86);     //RxWait = RxSelReg[5..0]
    //writeMFRC522(RFCfgReg, 0x7F);     //RxGain = 48dB

    antennaOn();        //Abre  la antena
    
    
}
void RFID::reset()
{
    writeMFRC522(CommandReg, PCD_RESETPHASE);
}

void RFID::writeMFRC522(unsigned char addr, unsigned char val)
{
    _chipSelectPin =0;

    //0XXXXXX0 formato de dirección
    _rfid.write((addr<<1)&0x7E);   
    _rfid.write(val);
    
    _chipSelectPin = 1;
}

void RFID::antennaOn(void)
{
    unsigned char temp;

    temp = readMFRC522(TxControlReg);
    if (!(temp & 0x03))
    {
        setBitMask(TxControlReg, 0x03);
    }
}

/*
 *  Read_MFRC522 Nombre de la función: Read_MFRC522
 *  Descripción: Desde el MFRC522 leer un byte de un registro de datos
 *  Los parámetros de entrada: addr - la dirección de registro
 *  Valor de retorno: Devuelve un byte de datos de lectura
 */
unsigned char RFID::readMFRC522(unsigned char addr)
{
    unsigned char val;
    _chipSelectPin =0;
    _rfid.write(((addr<<1)&0x7E) | 0x80);  
    val =_rfid.write(0x00);
    _chipSelectPin =1;
    return val; 
}

void RFID::setBitMask(unsigned char reg, unsigned char mask)  
{ 
    unsigned char tmp;
    tmp = readMFRC522(reg);
    writeMFRC522(reg, tmp | mask);  // set bit mask
}

void RFID::clearBitMask(unsigned char reg, unsigned char mask)  
{
    unsigned char tmp;
    tmp = readMFRC522(reg);
    writeMFRC522(reg, tmp & (~mask));  // clear bit mask
} 

void RFID::calculateCRC(unsigned char *pIndata, unsigned char len, unsigned char *pOutData)
{
    unsigned char i, n;

    clearBitMask(DivIrqReg, 0x04);          //CRCIrq = 0
    setBitMask(FIFOLevelReg, 0x80);         //Claro puntero FIFO
    //Write_MFRC522(CommandReg, PCD_IDLE);

    //Escribir datos en el FIFO 
    for (i=0; i<len; i++)
    {   
        writeMFRC522(FIFODataReg, *(pIndata+i));   
    }
    writeMFRC522(CommandReg, PCD_CALCCRC);

    // Esperar a la finalización de cálculo del CRC
    i = 0xFF;
    do 
    {
        n = readMFRC522(DivIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x04));            //CRCIrq = 1

    //Lea el cálculo de CRC
    pOutData[0] = readMFRC522(CRCResultRegL);
    pOutData[1] = readMFRC522(CRCResultRegM);
}

unsigned char RFID::MFRC522ToCard(unsigned char command, unsigned char *sendData, unsigned char sendLen, unsigned char *backData, unsigned int *backLen)
{
    unsigned char status = MI_ERR;
    unsigned char irqEn = 0x00;
    unsigned char waitIRq = 0x00;
    unsigned char lastBits;
    unsigned char n;
    unsigned int i;

    switch (command)
    {
        case PCD_AUTHENT:       // Tarjetas de certificación cerca
        {
            irqEn = 0x12;
            waitIRq = 0x10;
            break;
        }
        case PCD_TRANSCEIVE:    //La transmisión de datos FIFO
        {
            irqEn = 0x77;
            waitIRq = 0x30;
            break;
        }
        default:
            break;
    }
   
    writeMFRC522(CommIEnReg, irqEn|0x80);   //De solicitud de interrupción
    clearBitMask(CommIrqReg, 0x80);         // Borrar todos los bits de petición de interrupción
    setBitMask(FIFOLevelReg, 0x80);         //FlushBuffer=1, FIFO de inicialización
    
    writeMFRC522(CommandReg, PCD_IDLE); //NO action;Y cancelar el comando

    //Escribir datos en el FIFO
    for (i=0; i<sendLen; i++)
    {   
        writeMFRC522(FIFODataReg, sendData[i]);    
    }

    //???? ejecutar el comando
    writeMFRC522(CommandReg, command);
    if (command == PCD_TRANSCEIVE)
    {    
        setBitMask(BitFramingReg, 0x80);        //StartSend=1,transmission of data starts  
    }   
    
    // A la espera de recibir datos para completar
    i = 2000;   //i????????,??M1???????25ms ??? i De acuerdo con el ajuste de frecuencia de reloj, el tiempo máximo de espera operación M1 25ms tarjeta??
    do 
    {
        //CommIrqReg[7..0]
        //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
        n = readMFRC522(CommIrqReg);
        i--;
    }
    while ((i!=0) && !(n&0x01) && !(n&waitIRq));

    clearBitMask(BitFramingReg, 0x80);          //StartSend=0
    
    if (i != 0)
    {    
        if(!(readMFRC522(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
        {
            status = MI_OK;
            if (n & irqEn & 0x01)
            {   
                status = MI_NOTAGERR;           //??   
            }

            if (command == PCD_TRANSCEIVE)
            {
                n = readMFRC522(FIFOLevelReg);
                lastBits = readMFRC522(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;   
                }
                
                //??FIFO??????? Lea los datos recibidos en el FIFO
                for (i=0; i<n; i++)
                {   
                    backData[i] = readMFRC522(FIFODataReg);    
                }
            }
        }
        else
        {   
            status = MI_ERR;  
        }
        
    }
    
    //SetBitMask(ControlReg,0x80);           //timer stops
    //Write_MFRC522(CommandReg, PCD_IDLE); 

    return status;
}


/*
 *  Nombre de la función: MFRC522_Request
 *  Descripción: Buscar las cartas, leer el número de tipo de tarjeta
 *  Los parámetros de entrada: reqMode - encontrar el modo de tarjeta,
 *             Tagtype - Devuelve el tipo de tarjeta
 *              0x4400 = Mifare_UltraLight
 *              0x0400 = Mifare_One(S50)
 *              0x0200 = Mifare_One(S70)
 *              0x0800 = Mifare_Pro(X)
 *              0x4403 = Mifare_DESFire
 *  Valor de retorno: el retorno exitoso MI_OK
 */
unsigned char  RFID::MFRC522Request(unsigned char reqMode, unsigned char *TagType)
{
    unsigned char status;  
    unsigned int backBits;          //   Recibió bits de datos

    writeMFRC522(BitFramingReg, 0x07);      //TxLastBists = BitFramingReg[2..0] ???
    
    TagType[0] = reqMode;
    status = MFRC522ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);

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

/**
 *  MFRC522Anticoll -> anticoll
 *  Anti-detección de colisiones, la lectura del número de serie de la tarjeta de tarjeta
 *  @param serNum - devuelve el número de tarjeta 4 bytes de serie, los primeros 5 bytes de bytes de paridad
 *  @return retorno exitoso MI_OK
 */
unsigned char RFID::anticoll(unsigned char *serNum)
{
    unsigned char status;
    unsigned char i;
    unsigned char serNumCheck=0;
    unsigned int unLen;
    

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

    if (status == MI_OK)
    {
        //?????? Compruebe el número de serie de la tarjeta
        for (i=0; i<4; i++)
        {   
            serNumCheck ^= serNum[i];
        }
        if (serNumCheck != serNum[i])
        {   
            status = MI_ERR;    
        }
    }

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

    return status;
}