

#include "RC522Config.h"
#include "mfrc522.h"

//MfCmdInfo MInfo;
MfCmdInfo MInfo;

unsigned int	MIFARE_tmoutcnt; 

/**************************************************************************************************
** Reset data buffer
***************************************************************************************************/
void ResetInfo(void)
{
  unsigned char i;
  unsigned char *BfrPtr = (unsigned char *)(&MInfo);

  for(i=0 ; i<sizeof(MfCmdInfo); i++)
    BfrPtr[i] = 0;
}

/**************************************************************************************************
** IN:						_100us			number of us
** Set Transceive timeout
**************************************************************************************************/
void SetTimeOut(unsigned int _100us) // wenxue 设置超时时间
{
    RcSetReg(REG_TRELOADLO, ((unsigned char)(_100us&0xff)));
    RcSetReg(REG_TRELOADHI, ((unsigned char)((_100us>>8)&0xff)));
}


/**************************************************************************************************
** Set chip to operate at ISO14443A @106kbps
**************************************************************************************************/
char PcdConfig(void)
{
  unsigned char RegVal;
	unsigned char i;

	for(i=3;i>0;i--)
		for(RegVal=200;RegVal>0;RegVal--);	    // change according crystal startup
	

	RcSetReg(REG_COMMAND, 0x0f);                // soft reset RC52x

	
	RcSetReg(0x15, 0x40);						// 100% ASK
	 
	
	RcSetReg(0x0C, 0x10);						// set as initiator
		
	RcSetReg(0x12, 0x00);	  				// TypeA 106kbps

	RcSetReg(0x19, 0x0D);						// I/Q chnannel, select stronger one
	RcSetReg(0x27, 0xF1);						// N channel max
	RcSetReg(0x28, 0x3F);						// P channel max

  RcSetReg(0x18, 0x62);						// Rx threshhold and collision threshold
	RcSetReg(0x26, 0x78);						// reciver gain
	RcSetReg(0x36, 0x00);						// switch off AmpRcv
	
	RcSetReg(0x27, 0xF0 | 0x04);		// CWGsN = 0xF; ModGsN = 0x4
	RegVal = RcGetReg(REG_GSN);
	if(RegVal != 0xF4)				      // check interface
		return STATUS_INIT_ERROR;

	RcSetReg(REG_TPRESCALER, 0xA6-1);	        // 100us clock
	RcSetReg(REG_TMODE, 0x82);		            // Timer starts after last bit and stops after first bit
	
	SetTimeOut(100);					            // set 10ms delay but not started  // wenxue

	// Activate RF field
	RcModifyReg(REG_TXCONTROL, 1, BIT_TX2RFEN | BIT_TX1RFEN); 

  RcModifyReg(REG_CONTROL, 1, BIT_TSTARTNOW); // Start timer

	do 
	{
			RegVal = RcGetReg(REG_COMMIRQ);
	}
	while(!(RegVal & BIT_TIMERI));              // wait for RF setup finished

  RcSetReg(REG_COMMIRQ, BIT_TIMERI);          // clear interrupt

	RcSetReg(REG_COMMAND, CMD_IDLE);

	RcSetReg(REG_ANALOGTEST, 0xcd);

	return STATUS_SUCCESS;
}

 unsigned char getRegVal_test;

/**************************************************************************************************
** IN:					unsigned char cmd								command code
** 							unsigned char *ExchangeBuf      data in-out buffer
** Func:				implement chip command
**************************************************************************************************/
char  PcdCmd(unsigned char cmd,unsigned char *ExchangeBuf)
{
    char    status = STATUS_SUCCESS;
    unsigned char commIrqEn   = 0;
    unsigned char divIrqEn    = 0;
    unsigned char waitForComm = BIT_ERRI | BIT_TXI;
    unsigned char waitForDiv  = 0;
    unsigned char doReceive   = 0;
    unsigned char getRegVal,setRegVal;
    unsigned char  nbytes, nbits;
    nbytes = nbytes;
    nbits = nbits;
		// clear all interrupts
    RcSetReg(REG_COMMIRQ, 0x7f);                
    RcSetReg(REG_DIVIRQ, 0x7f);
    RcSetReg(REG_FIFOLEVEL, BIT_FLUSHBUFFER);

		// clear current command
    getRegVal = RcGetReg(REG_COMMAND);           
    if(cmd == CMD_TRANSCEIVE)
    {
        setRegVal = (getRegVal & ~MASK_COMMAND) | CMD_TRANSCEIVE;
        RcSetReg(REG_COMMAND, setRegVal);
    }
    else
    {
        setRegVal = (getRegVal & ~MASK_COMMAND);
        RcSetReg(REG_COMMAND, setRegVal);
    }
    switch(cmd)
    {
       case CMD_IDLE:
            waitForComm = 0;
            waitForDiv  = 0;
            break;
        case CMD_CALCCRC:
            waitForComm = 0;
            waitForDiv  = 0;
            break;
        case CMD_TRANSMIT:
            commIrqEn = BIT_TXI | BIT_TIMERI;
            waitForComm = BIT_TXI;
            break;
        case CMD_RECEIVE:
            commIrqEn = BIT_RXI | BIT_TIMERI;
            waitForComm = BIT_RXI | BIT_TIMERI;
            doReceive = 1;
            break;
        case CMD_TRANSCEIVE:
            commIrqEn = BIT_RXI | BIT_TIMERI;
            waitForComm = BIT_RXI | BIT_TIMERI;
            doReceive = 1;
            break;
        case CMD_AUTHENT:
            commIrqEn = BIT_IDLEI | BIT_TIMERI;
            waitForComm = BIT_IDLEI | BIT_TIMERI;
            break;
        case CMD_SOFTRESET:
            waitForComm = 0;
            waitForDiv  = 0;
            break;
        default:
            status = STATUS_UNSUPPORTED_COMMAND;
    }
    if(status == STATUS_SUCCESS)
    {
        // enable required interrupt
        getRegVal = RcGetReg(REG_COMMIEN);
        RcSetReg(REG_COMMIEN, getRegVal | commIrqEn);
        getRegVal = RcGetReg(REG_DIVIEN);
        RcSetReg(REG_DIVIEN, getRegVal | divIrqEn);
				
				// write data into FIFO
				WriteFIFO(ExchangeBuf,MInfo.nBytesToSend); 

        if(cmd == CMD_TRANSCEIVE)               // 
        {// start transmission
            RcModifyReg(REG_BITFRAMING, 1, BIT_STARTSEND);
        }
        else
        {
            getRegVal = RcGetReg(REG_COMMAND);
            RcSetReg(REG_COMMAND, (getRegVal & ~MASK_COMMAND) | cmd);
        }

        // check expected interrupt
        getRegVal = 0;
        setRegVal = 0;
        // set timeout	
				MIFARE_tmoutcnt = 500;  // wenxue 
				// 注意这个值I2C_MAX_TIMEOUT  I2C里已经有了timeout  I2C的timerout不能太大

				while(!(waitForComm&setRegVal))
        {
          MIFARE_tmoutcnt --;
					setRegVal = RcGetReg(REG_COMMIRQ);
					//getRegVal_test=setRegVal;
					//getRegVal = RcGetReg(REG_DIVIRQ);
					if(MIFARE_tmoutcnt == 0)
							break;                          // timeout
        }
			if(MIFARE_tmoutcnt == 0)
			{
				status = STATUS_ACCESS_TIMEOUT;
			}
			else
			{
						// save interrupt
						waitForComm = (unsigned char)(waitForComm & setRegVal);
						waitForDiv  = (unsigned char)(waitForDiv & getRegVal);
		
						// if timer interrupt -> timeout
						if (setRegVal & BIT_TIMERI)
						{
								status = STATUS_IO_TIMEOUT;  // wenxue
						}
			}
    }

    // disable interrupt
    RcModifyReg(REG_COMMIEN, 0, commIrqEn);

    RcModifyReg(REG_DIVIEN, 0, divIrqEn);

    if(doReceive && (status == STATUS_SUCCESS))
    {
        // read bytes and bits
        MInfo.nBytesReceived = RcGetReg(REG_FIFOLEVEL);
        nbytes = MInfo.nBytesReceived;
        getRegVal = RcGetReg(REG_CONTROL);
        MInfo.nBitsReceived = (unsigned char)(getRegVal & 0x07);
        nbits = MInfo.nBitsReceived;

        getRegVal = RcGetReg(REG_ERROR);
        // error info
        if(getRegVal)
        {
            if(getRegVal & BIT_COLLERR)
                status = STATUS_COLLISION_ERROR;// collision error
            else if(getRegVal & BIT_PARITYERR)
                status = STATUS_PARITY_ERROR;   // parity error

            if(getRegVal & BIT_PROTERR)
                status = STATUS_PROTOCOL_ERROR; // protocol error
            else if(getRegVal & BIT_BUFFEROVFL)
                status = STATUS_BUFFER_OVERFLOW;// FIFO overflow error
            else if(getRegVal & BIT_CRCERR)
            {// CRC error
                if(MInfo.nBytesReceived == 0x01 &&
                    (MInfo.nBitsReceived == 0x04 ||
                     MInfo.nBitsReceived == 0x00))
                {   // CRC error AND only 1 byte received -> consider Mifare (N)ACK
                    ExchangeBuf[0] = RcGetReg(REG_FIFODATA);
                    MInfo.nBytesReceived = 1;
                    status = STATUS_ACK_SUPPOSED;   // (N)ACK
                }
                else
                    status = STATUS_CRC_ERROR;      // CRC error
            }
            else if(getRegVal & BIT_TEMPERR)
                status = STATUS_TEMP_ERROR;   // temperature error
            if(getRegVal & BIT_WRERR)
                status = STATUS_FIFO_WRITE_ERROR;   // write FIFO error
            if(status == STATUS_SUCCESS)
                status = STATUS_ERROR_NY_IMPLEMENTED;    // RFU error

            // in case of error, clear it before IRQ 
            RcSetReg(REG_ERROR, 0);
        }

        // read FIFO and set parameters
        if(status != STATUS_ACK_SUPPOSED)
        {
					ReadFIFO(ExchangeBuf,MInfo.nBytesReceived);
					// last byte incomplete
					if(MInfo.nBitsReceived && MInfo.nBytesReceived)
						MInfo.nBytesReceived --;
        }
    }
    RcSetReg(REG_COMMIRQ, waitForComm);
    RcSetReg(REG_DIVIRQ, waitForDiv);
    RcSetReg(REG_FIFOLEVEL, BIT_FLUSHBUFFER);
    RcSetReg(REG_COMMIRQ, BIT_TIMERI);
    RcSetReg(REG_BITFRAMING, 0);
    return status;
}
//=================================================================================================

