

#include "TypeA.h"
#include "RC522Config.h"

//============= ISO14443-4协议使用的常量和变量定义 ================================================
const unsigned short   FSC[9] = {16,24,32,40,48,64,96,128,256};  // PICC能接收的帧长度表
unsigned char blocknum;                         // 分组号
unsigned char FSCI;
unsigned long FWI;                              // 帧等待时间因子
 
//=================================================================================================
// ISO14443-3
/**************************************************************************************************
** 函数原型:    char PiccRequest(unsigned char req_code, unsigned char *atq);
** 函数功能:    请求天线感应区内的卡
** 入口参数:    unsigned char req_code          ; 请求类型 REQALL、REQIDLE
** 出口参数:    unsigned char *atq              ; 请求回应
** 返 回 值:    -
** 描　  述:    请求回应的代码
**	     		MF0 IC U1	的类型号:0044H
**	     		MF1 IC S50	的类型号:0004H
**				MF1 IC S70	的类型号:0002H
**				MF3	IC D40	的类型号:0344H
**************************************************************************************************/
char PiccRequest(unsigned char req_code, unsigned char *atq)
{
    char  Status = STATUS_SUCCESS;
    unsigned char SerBuffer[2];	
    
    RcModifyReg(REG_STATUS2, 0, BIT_CRYPTO1ON); // 取消加密通信
    RcSetReg(REG_COLL, BIT_VALUESAFTERCOLL);    // 冲突之后，所接收的值仍然有效
    RcModifyReg(REG_TXMODE, 0, BIT_CRCEN);      // 禁止 TxCRC 和 RxCRC
    RcModifyReg(REG_RXMODE, 0, BIT_CRCEN);
    RcSetReg(REG_BITFRAMING, REQUEST_BITS);     // 仅发送7位
	
//		// terminate command
//	RcSetReg(REG_COMMAND, 0x00);
//	// flush fifo
//	RcSetReg(0x0A, 0x80);
//	// request code
//	RcSetReg(0x09, 0x26);
//	//delay_ms(1);
//	
//	// start tranceive
//	RcSetReg(0x00, 0x0C);
//	
//	// delay_ms(2)
//	
//	SerBuffer[0] = RcGetReg(0x0A);	// fifo length, must = 2
//	SerBuffer[1] = RcGetReg(0x09);	// fifo data = 0xx4
//	SerBuffer[1] = RcGetReg(0x09);	// fifo data ~= 0x00
//	
	
	
	
	
	
	
	
	
	
    
    // 设置发送参数
    ResetInfo();
    SerBuffer[0] = req_code;
    MInfo.nBytesToSend   = 1;
    
    SetTimeOut(25);                              // 设置超时，400us 
	
    Status = PcdCmd(CMD_TRANSCEIVE,SerBuffer);
    if(Status == STATUS_SUCCESS || Status == STATUS_COLLISION_ERROR)
    {
       if(MInfo.nBytesReceived != ATQA_LENGTH || MInfo.nBitsReceived != 0x00)
       {
          Status = STATUS_PROTOCOL_ERROR;
          Status = MI_OK;
          RcSetReg(REG_BITFRAMING, 0);                // 恢复发送整字节
          return Status;
       }
       else
       {
          memcpy(atq,SerBuffer,2);
          Status = MI_OK;
          RcSetReg(REG_BITFRAMING, 0);                // 恢复发送整字节
          return Status;
       }
    }
    RcSetReg(REG_BITFRAMING, 0);                // 恢复发送整字节
    return Status;
}
/**************************************************************************************************
** 函数原型:    char PiccCascAnticoll(unsigned char sel_code,unsigned char bitcount,
**                                    unsigned char *snr);
** 函数功能:    防碰撞
** 入口参数:    unsigned char sel_code          ; 防碰撞的等级
**              unsigned char bitcount          ; 已知UID的位数
**              unsigned char *snr        ; 已知的UID
** 出口参数:    unsigned char *snr        ; UID
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccCascAnticoll(unsigned char sel_code,unsigned char bitcount, volatile unsigned char *snr)
{
    char Status = STATUS_SUCCESS;
	unsigned char SerBuffer[7];	
		int delay;
    unsigned char  i;
    unsigned char  complete = 0;                ///
    unsigned char  rbits    = 0;                // 接收的总位数
    unsigned char  nbits    = 0;                //
    unsigned char  nbytes   = 0;                //
    unsigned char  byteOffset;                  // 

    SerBuffer[2] = 0x00;   
    SerBuffer[3] = 0x00;
    SerBuffer[4] = 0x00;
    SerBuffer[5] = 0x00;
    SerBuffer[6] = 0x00;
    
    RcModifyReg(REG_TXMODE, 0, BIT_CRCEN);      // 禁止接收和发送的CRC
    RcModifyReg(REG_RXMODE, 0, BIT_CRCEN);

    RcSetReg(REG_COLL, 0x0);                      // 冲突位后的数据删除

    // 初始化防冲突循环参量
    while(!complete && (Status == STATUS_SUCCESS))
    {
        // 若RF常存在通信问题，bitcount将大于SINGLE_UID_LENGTH，防冲突循环执行将会存在问题
        if(bitcount > SINGLE_UID_LENGTH)
        {
            Status = STATUS_INVALID_PARAMETER;
            continue;
        }

        // 准备发送的数据
        nbits = (unsigned char)(bitcount % BITS_PER_BYTE);
        nbytes = (unsigned char)(bitcount / BITS_PER_BYTE);
        if(nbits)
            nbytes++;

        SerBuffer[0] = sel_code;
        SerBuffer[1] = (unsigned char)(NVB_MIN_PARAMETER + ((bitcount / BITS_PER_BYTE) << UPPER_NIBBLE_SHIFT) + nbits);
        for(i=0;i<nbytes;i++)
            SerBuffer[2+i] = snr[i];            // 复制相应的数据到数据缓冲区

        // 最后字节需要发送的位
        RcSetReg(REG_BITFRAMING, (unsigned char)((nbits << UPPER_NIBBLE_SHIFT) | nbits));

        ResetInfo();
        MInfo.nBytesToSend   = (unsigned char)(nbytes + 2);

        SetTimeOut(2000);                        // 10ms
				for(delay=0;delay<200;delay++){;}
        Status = PcdCmd(CMD_TRANSCEIVE, SerBuffer);

        if(Status == STATUS_COLLISION_ERROR || Status == STATUS_SUCCESS)
        {
            rbits = (unsigned char)(MInfo.nBitsReceived + (MInfo.nBytesReceived << 3) - nbits);

            if((rbits + bitcount) > COMPLETE_UID_BITS)
            {
                Status = STATUS_BITCOUNT_ERROR;
                continue;
            }

            if(MInfo.nBitsReceived)
                MInfo.nBytesReceived++;

            byteOffset = 0;                     // 复位数据复制的偏移量
            if(nbits)
            {// 上次发送的字节和本次接收的第一字节是同一字节
                snr[nbytes - 1] |= SerBuffer[0];
                byteOffset++;
            }
            for(i=0;i<(4-nbytes);i++)
                snr[nbytes + i] = SerBuffer[i + byteOffset];

            if(Status == STATUS_COLLISION_ERROR)
            {
                bitcount = (unsigned char)(bitcount + rbits);
                Status = STATUS_SUCCESS;
            } else
            {
                if((snr[0] ^ snr[1] ^ snr[2] ^ snr[3]) != SerBuffer[i + byteOffset])
                {
                    Status = STATUS_WRONG_UID_CHECKBYTE;
                    continue;
                }
                complete=1;
            }
        }
    }

    RcSetReg(REG_BITFRAMING, 0);                // 恢复发送整字节

    RcSetReg(REG_COLL, BIT_VALUESAFTERCOLL);    // 冲突位接收的数据任有效
    return Status;
}
/**************************************************************************************************
** 函数原型:    char PiccCascSelect(unsigned char sel_code,unsigned char *snr,
**                                  unsigned char *sak);
** 函数功能:    选择卡
** 入口参数:    unsigned char sel_code      ; 选择的等级
**                                          ; 0x93：第1级；
**                    						; 0x95：第2级；
**                    						; 0x97：第3级。
**              unsigned char *snr    ; UID
** 出口参数:    unsigned char *sak    ; SAK
** 返 回 值:    执行结果
** 描　  述:    
**************************************************************************************************/
char PiccCascSelect(unsigned char sel_code, volatile unsigned char *snr,  unsigned char *sak)
{
    char Status = STATUS_SUCCESS;
//    unsigned char i;
	unsigned char SerBuffer[7];	
    RcModifyReg(REG_TXMODE, 1, BIT_CRCEN);      // 使能发送/接收CRC
    RcModifyReg(REG_RXMODE, 1, BIT_CRCEN);

    // 发送数据
    SerBuffer[0] = sel_code;                    // 选择命令码
    SerBuffer[1] = NVB_MAX_PARAMETER;

    SerBuffer[2] = snr[0];                 
    SerBuffer[3] = snr[1];
    SerBuffer[4] = snr[2];
    SerBuffer[5] = snr[3];
    
    SerBuffer[6] = (unsigned char)(snr[0] ^ snr[1] ^ snr[2] ^ snr[3]);   // BCC

    ResetInfo();
    MInfo.nBytesToSend   = 0x07;
    SetTimeOut(30);
    Status = PcdCmd(CMD_TRANSCEIVE, SerBuffer);

    if(Status == STATUS_SUCCESS)
    {
        if(MInfo.nBytesReceived == SAK_LENGTH && MInfo.nBitsReceived == 0)
            *sak = SerBuffer[0];
        else
            Status = STATUS_BITCOUNT_ERROR;
    }
    return Status;
}
/**************************************************************************************************
** 函数原型:    char PiccHalt(void)
** 函数功能:    将选择的卡挂起(ISO/IEC14443A-3)
** 入口参数:    -
** 出口参数:    -
** 返 回 值:    执行结果
** 描　  述:    该函数是ISO/IEC14443A-3层协议
**************************************************************************************************/
char PiccHalt(void)
{
    char  Status = STATUS_SUCCESS;
	unsigned char SerBuffer[2];
	
    SerBuffer[0] = HALTA_CMD;
    SerBuffer[1] = HALTA_PARAM;

    ResetInfo();
    MInfo.nBytesToSend   = HALTA_CMD_LENGTH;
    SetTimeOut(10);
    Status = PcdCmd(CMD_TRANSCEIVE, SerBuffer);

    if(Status == STATUS_IO_TIMEOUT)
        Status = STATUS_SUCCESS;
    return Status;
}

/**************************************************************************************************
** IN:						unsigned char *atq			ATQA buffer
** 								unsigned char *buf			UID buffer
**								unsigned char *sak			SAK address
** FUNC:					Active one single card
**************************************************************************************************/
char PiccActiveCard(unsigned char *atq, unsigned char *buf, unsigned char *sak)
{
	char status=MI_OK;
	unsigned char delay;
	const unsigned char delay_t=10;
				
	status = PiccRequest( REQIDLE, atq );
 	if(status == MI_OK)
	{
		for(delay=0; delay<delay_t; delay++)	{;}
		status = PiccCascAnticoll( 0x93, 0, buf);
	  if ( status == MI_OK ) 
		{
			for(delay=0; delay<delay_t; delay++)	{;}
			status = PiccCascSelect( 0x93, buf, sak );
			if ( status == MI_OK )  
			{
				if(*sak & 0x04)	
				{// bit3 of SAK - UID not complete
					//bSnrLen = 1;	// updata UID length
					*buf=*(buf+1);
					*(buf+1)=*(buf+2);
					*(buf+2)=*(buf+3);

					for(delay=0; delay<delay_t; delay++)	{;}
					status = PiccCascAnticoll(0x95,0,buf+3); // level 2
					if(status == MI_OK) 
					{
						for(delay=0; delay<delay_t; delay++)	{;}
						status = PiccCascSelect(0x95, buf+3, sak);	// level 2
					} 
				} 
			} 
    } 			
	}
	return status;
}

