

	
	
	//*********************************************************************************
	link bit CS_DIR = CS.D0_DIR;	//即SDA
	link bit CS_OUT = CS.D0_OUT;	//即SDA
	SPI.SCK_DIR = SCK.D0_DIR;
	SPI.SCK_OUT = SCK.D0_OUT;
	SPI.MOSI_DIR = MOSI.D0_DIR;
	SPI.MOSI_OUT = MOSI.D0_OUT;
	SPI.MISO_DIR = MISO.D0_DIR;
	SPI.MISO_IN = MISO.D0_IN;
	
	bit IRQ_DIR;
	bit IRQ_OUT;
	bit RST_DIR;
	bit RST_OUT;
	
	bool last_is_ok;
	
	bool busy;
	
	//卡序列号
	const uint8 MAX_LEN = 30;
	[uint8*MAX_LEN] CardQueue;
	
	[uint8*6] KEY;
	
	void RunInit()
	{
		CS_DIR = 1;
		CS_OUT = 1;
		
		IRQ_DIR = 0;
		IRQ_OUT = 1;
		
		SPI.init();
		
		//触发复位
		RST_DIR = 1;
		RST_OUT = 1;
		loop( 200 ) {}
		//RST_OUT = 0;
		loop( 200 ) {}
		RST_OUT = 1;
		loop( 200 ) {}
		
		//复位
		write_reg(CommandReg, PCD_RESETPHASE);
		loop( 200 ) {}
		
		//Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
		write_reg(TModeReg, 0x8D); //Tauto=1; f(Timer) = 6.78MHz/TPreScaler
		write_reg(TPrescalerReg, 0x3E); //TModeReg[3..0] + TPrescalerReg
		write_reg(TReloadRegL, 30);
		write_reg(TReloadRegH, 0);
    		
		write_reg(TxAutoReg, 0x40); //100%ASK
		write_reg(ModeReg, 0x3D); //CRC initilizate value 0x6363 ???
		
		
		///////////////////////////////////////////////////////////////////////////////////
		//write_reg(RxSelReg,0x86);
		//ClearBitMask(Status2Reg,0x08);
		///////////////////////////////////////////////////////////////////////////////////
		
		
		//ClearBitMask(Status2Reg, 0x08); //MFCrypto1On=0
		//write_reg(RxSelReg, 0x86); //RxWait = RxSelReg[5..0]
		//write_reg(RFCfgReg, 0x7F); //RxGain = 48dB
		AntennaOn(); //turn on antenna
		
		KEY[0] = 0xFF;
		KEY[1] = 0xFF;
		KEY[2] = 0xFF;
		KEY[3] = 0xFF;
		KEY[4] = 0xFF;
		KEY[5] = 0xFF;
		
		last_is_ok = false;
		busy = false;
	}
	
	uint8 ddd;
	
	int32 test()
	{
		return (int)ddd;
	}
	
	//=================================================================================
	public void OS_run()
	{
		if( busy ) {
			return;
		}
		
		//注意!!! 这个数组不能定义成局部变量
		//[uint8*MAX_LEN] str;
		
		// Search card, return card types
		uint8 status = Request( PICC_REQIDL, CardQueue );
		
		if (status != MI_OK) {
			if( last_is_ok ) {
				last_is_ok = false;
				OS_EventFlag.1(bit) = 1;
				isNear = false;
			}
			return;
		}
		if( !last_is_ok ) {
			last_is_ok = true;
			
			OS_EventFlag.0(bit) = 1;
			isNear = true;
			
			
//			if(str[0]==0x04 && str[1]==0x00) MFOne-S50
//			else if(str[0]==0x02 && str[1]==0x00) MFOne-S70
//			else if(str[0]==0x44 && str[1]==0x00) MF-UltraLight
//			else if(str[0]==0x08 && str[1]==0x00) MF-Pro
//			else if(str[0]==0x44 && str[1]==0x03) MF Desire
			
			
			//4 bytes Serial number of card, the 5 bytes is verfiy bytes
			//[uint8*5] serNum;
			
			//Prevent conflict, return the 4 bytes Serial number of the card
			status = MFRC522_Anticoll( CardQueue );
			
			// str[0..3]: serial number of the card
			// str[4]: XOR checksum of the SN.
			
			//读取ID
			if (status == MI_OK) {
				IDlist[0] = get_hex(CardQueue[0]>>4);
				IDlist[1] = get_hex(CardQueue[0]&0x0f);
				IDlist[2] = get_hex(CardQueue[1]>>4);
				IDlist[3] = get_hex(CardQueue[1]&0x0f);
				IDlist[4] = get_hex(CardQueue[2]>>4);
				IDlist[5] = get_hex(CardQueue[2]&0x0f);
				IDlist[6] = get_hex(CardQueue[3]>>4);
				IDlist[7] = get_hex(CardQueue[3]&0x0f);
				
				uint32 dd;
				dd.0(uint8) = CardQueue[3];
				dd.8(uint8) = CardQueue[2];
				dd.16(uint8) = CardQueue[1];
				dd.24(uint8) = CardQueue[0];
				IDnumber = (int)dd;
				
				//加上之后导致系统运行异常, 无法正常触发事件
				
				//status = PcdSelect( CardQueue );
				//if(status == MI_OK) {
				//	status = PcdAuthState(0x60,0x04, KEY, CardQueue);
				//	if(status == MI_OK) {
						
						
						
				//		ddd = 34;
				//	}
				//	else {
				//		ddd = 56;
				//	}
				//}
			}
			else {
				//#.I.串口.发送常量字符串_?_("Read card's number ERROR!\n");
			}
		}
		//command the card into sleep mode
		halt();
	}
	//---------------------------------------------------
	//获取给定数字对应的字符, 十六进制 0-15 -> 0-F
	uint8 get_hex( uint8 d )
	{
		if( d <= 9 ) return '0' + d;
		return 'A' + (d - 10);
	}
	//=================================================================================
	//功    能：选定卡片
	//参数说明: pSnr[IN]:卡片序列号，4字节
	//返    回: 成功返回MI_OK
	[uint8*30] str1;
	public uint8 PcdSelect( [uint8*?] TagType )
	{
		str1[0] = PICC_ANTICOLL;
		str1[1] = 0x70;
		str1[6] = 0;
		for(uint8 i=0; i<5; i+1 ) {
			str1[i+2] = TagType[i];
		}
		calulate_CRC( str1, 7, str1[7] );
		
		ClearBitMask( Status2Reg, 0x08 );
		
		uint8 unLen;
		uint8 status = to_card( PCD_TRANSCEIVE, str1, 9, str1, unLen );
		
		if( (status == MI_OK) && (unLen == 0x18) ) {
			status = MI_OK;
		}
		else {
			status = MI_ERR;
		}
		return status;
	}
	//=================================================================================
	
	uint8 PcdAuthState(uint8 auth_mode, uint8 addr, [uint8*?] Key, [uint8*?] TagType )
	{
		str1[0] = auth_mode;
		str1[1] = addr;
		
		for( uint8 i=0; i<6; i+1 ) {
			str1[i+2] = Key[i];
		}
		for( uint8 i=0; i<4; i+1 ) {
			str1[i+8] = TagType[i];
		}
		uint8 unLen;
		uint8 status = to_card(PCD_AUTHENT,str1,12,str1,&unLen);
		if( status != MI_OK || read_reg(Status2Reg) & 0x08 == 0 ) {
			status = MI_ERR;
		}
		return status;
	}
	
	//---------------------------------------------------
	//* Function：MFRC522_Halt
	//* Description：Command the cards into sleep mode
	//* Input parameters：null
	//* return：null
	void halt()
	{
		uint8 status;
		uint32 unLen;
		[uint8*4] buff;
		
		buff[0] = PICC_HALT;
		buff[1] = 0;
		calulate_CRC(buff, 2, buff[2]);
		status = to_card( PCD_TRANSCEIVE, buff, 4, buff,unLen );
	}
	//---------------------------------------------------
	//查询卡
	//* Function：MFRC522_Request
	//* Description：Searching card, read card type
	//* Input parameter：reqMode--search methods，
	//* TagType--return card types
	//* 0x4400 = Mifare_UltraLight
	//* 0x0400 = Mifare_One(S50)
	//* 0x0200 = Mifare_One(S70)
	//* 0x0800 = Mifare_Pro(X)
	//* 0x4403 = Mifare_DESFire
	//* return：return MI_OK if successed
	uint8 Request( uint8 reqMode, [uint8*?] TagType )
	{
		///////////////////////////////////////////////////////////////////////////////////
		//ClearBitMask(Status2Reg,0x08);
		///////////////////////////////////////////////////////////////////////////////////
		
		
		write_reg( BitFramingReg, 0x07 ); //TxLastBists = BitFramingReg[2..0] ???
		TagType[0] = reqMode;
		
		uint32 backBits; //the data bits that received
		uint8 status = to_card( PCD_TRANSCEIVE, TagType, 1, TagType, backBits );
		
		if ((status != MI_OK) || (backBits != 0x10)) {
			status = MI_ERR;
		}
		return status;
	}
	//---------------------------------------------------
	//* Function：MFRC522_Write
	//* Description：write block data
	//* Input parameters：blockAddr--block address;writeData--Write 16 bytes data into block
	//* return：return MI_OK if successed
	uint8 Write( uint8 blockAddr, [uint8*?] writeData )
	{
		uint8 status;
		uint32 recvBits;
		uint8 i;
		[uint8*18] buff;
		
		buff[0] = PICC_WRITE;
		buff[1] = blockAddr;
		calulate_CRC( buff, 2, buff[2] );
		status = to_card( PCD_TRANSCEIVE, buff, 4, buff, recvBits );
		
		if( status!=MI_OK || recvBits!=4 || buff[0]&0x0F!=0x0A ) { 
			status = MI_ERR;
		}
		if( status == MI_OK ) {
			//Write 16 bytes data into FIFO
			for( i = 0; i < 16; i + 1 ) { 
				buff[i] = writeData[i]; 
			}
			calulate_CRC( buff, 16, buff[16] );
			status = to_card( PCD_TRANSCEIVE, buff, 18, buff, recvBits );
			
			if ( status!=MI_OK || recvBits!=4 || buff[0]&0x0F!=0x0A ) { 
				status = MI_ERR;
			}
		}
		return status;
	}
	//---------------------------------------------------
	//* Function：MFRC522_Anticoll
	//* Description：Prevent conflict, read the card serial number 
	//* Input parameter：serNum--return the 4 bytes card serial number, the 5th byte is recheck byte
	//* return：return MI_OK if successed
	//防碰撞处理
	uint8 MFRC522_Anticoll( [uint8*?] serNum )
	{
		uint8 status;
		uint8 i;
		uint8 serNumCheck = 0;
		uint32 unLen;
		
		//ClearBitMask(Status2Reg, 0x08); //strSensclear
		//ClearBitMask(CollReg,0x80); //ValuesAfterColl
		write_reg( BitFramingReg, 0x00 ); //TxLastBists = BitFramingReg[2..0]
		
		serNum[0] = PICC_ANTICOLL;
		serNum[1] = 0x20;
		status = to_card( PCD_TRANSCEIVE, serNum, 2, serNum, unLen );
		
		if( status == MI_OK ) {
			//Verify card serial number
			for( i = 0; i < 4; i + 1 ) { 
				serNumCheck ^ serNum[i];
			}
			if( serNumCheck != serNum[i] ) { 
				status = MI_ERR;
			}
		}
		//SetBitMask(CollReg, 0x80); //ValuesAfterColl=1
		return status;
	}
	//---------------------------------------------------
	//* Function：CalulateCRC
	//* Description：Use MF522 to caculate CRC
	//* Input parameter：pIndata--the CRC data need to be read，len--data length，pOutData-- the caculated result of CRC
	//* return：Null
	void calulate_CRC( [uint8*?] pIndata, uint8 len, [uint8*?] pOutData)
	{
		uint8 i;
		uint8 n;
		
		ClearBitMask( DivIrqReg, 0x04 ); //CRCIrq = 0
		SetBitMask( FIFOLevelReg, 0x80 ); //Clear FIFO pointer
		//write_reg( CommandReg, PCD_IDLE );
		
		//Write data into FIFO 
		for( i = 0; i < len; i + 1 ) { 
			write_reg( FIFODataReg, pIndata[i] ); 
		}
		write_reg( CommandReg, PCD_CALCCRC );
		
		//waite CRC caculation to finish
		i = 0xFF;
		do {
			n = read_reg( DivIrqReg );
			i - 1;
		}
		while( i!=0 && n&0x04==0 ); //CRCIrq = 1
		
		//read CRC caculation result
		pOutData[0] = read_reg( CRCResultRegL );
		pOutData[1] = read_reg( CRCResultRegM );
	}
	//---------------------------------------------------
	//* Function：MFRC522_ToCard
	//* Description：communicate between RC522 and ISO14443
	//* Input parameter：command--MF522 command bits
	//* sendData--send data to card via rc522
	//* sendLen--send data length
	//* backData--the return data from card
	//* backLen--the length of return data
	//* return：return MI_OK if successed
	uint8 to_card(uint8 command, [uint8*?] sendData, uint8 sendLen, [uint8*?] backData, #.base uint32 backLen )
	{
		uint8 status = MI_ERR;
		uint8 irqEn = 0x00;
		uint8 waitIRq = 0x00;
		
		switch( command ) {
			== PCD_AUTHENT: //verify card password
				irqEn = 0x12;
				waitIRq = 0x10;
				break;
			== PCD_TRANSCEIVE: //send data in the FIFO
				irqEn = 0x77;
				waitIRq = 0x30;
				break;
			default:
				break;
		}
		write_reg( CommIEnReg, irqEn | 0x80 ); //Allow interruption
		ClearBitMask( CommIrqReg, 0x80 ); //Clear all the interrupt bits
		SetBitMask( FIFOLevelReg, 0x80 ); //FlushBuffer=1, FIFO initilizate
		write_reg( CommandReg, PCD_IDLE ); //NO action;cancel current command ???
		
		//write data into FIFO
		for( uint8 i = 0; i < sendLen; i + 1 ) {
			write_reg( FIFODataReg, sendData[i] );
		}
		//procceed it
		write_reg( CommandReg, command );
		if( command == PCD_TRANSCEIVE ) { 
			SetBitMask( BitFramingReg, 0x80 ); //StartSend=1,transmission of data starts 
		}
		//waite receive data is finished
		uint16 time = 2000; //i should adjust according the clock, the maxium the waiting time should be 25 ms???
		uint8 flag;
		do {
			//CommIrqReg[7..0]
			//Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
			flag = read_reg( CommIrqReg );
			time - 1;
		}
		while( time != 0 && flag&0x01 == 0 && flag & waitIRq == 0 );
		
		ClearBitMask( BitFramingReg, 0x80 ); //StartSend=0
		
		if( time != 0 ) {
			//BufferOvfl Collerr CRCErr ProtecolErr
			if( read_reg(ErrorReg) & 0x1B == 0 ) {
				status = MI_OK;
				if( (flag&irqEn&0x01) != 0 ) status = MI_NOTAGERR;
				if( command == PCD_TRANSCEIVE ) {
					uint32 n = read_reg( FIFOLevelReg );
					uint8 lastBits = read_reg( ControlReg ) & 0x07;
					if( lastBits != 0 ) {
						backLen = ( n - 1 ) * 8 + lastBits;
					}
					else {
						backLen = n * 8;
					}
					if( n == 0 ) n = 1;
					if( n > MAX_LEN ) n = MAX_LEN;
					
					//read the data from FIFO
					for( uint8 i = 0; i < n; i + 1 ) { 
						backData[i] = read_reg( FIFODataReg );
					}
				}
			}
			else {
				status = MI_ERR;
			}
		}
		//SetBitMask(ControlReg,0x80); //timer stops
		//Write_MFRC522(CommandReg, PCD_IDLE); 
		return status;
	}
	//---------------------------------------------------
	//* Function：AntennaOn
	//* Description：Turn on antenna, every time turn on or shut down antenna need at least 1ms delay
	//* Input parameter：null
	//* Return：null
	void AntennaOn()
	{
		uint8 temp = read_reg( TxControlReg );
    		if( temp & 0x03 == 0x00 ) {
			SetBitMask( TxControlReg, 0x03 );
		}
	}
	//---------------------------------------------------
	//* Function：AntennaOff
	//* Description：Turn off antenna, every time turn on or shut down antenna need at least 1ms delay
	//* Input parameter：null
	//* Return：null
	void AntennaOff()
	{
		ClearBitMask( TxControlReg, 0x03 );
	}
	//---------------------------------------------------
	//* Function：SetBitMask
	//* Description：set RC522 register bit
	//* Input parameter：reg--register address;mask--value
	//* Return：null
	void SetBitMask( uint8 reg, uint8 mask ) 
	{
		uint8 tmp = read_reg( reg );
		write_reg( reg, tmp | mask ); // set bit mask
	}
	//---------------------------------------------------
	//* Function：ClearBitMask
	//* Description：clear RC522 register bit
	//* Input parameter：reg--register address;mask--value
	//* Return：null
	void ClearBitMask( uint8 reg, uint8 mask ) 
	{
		uint8 tmp = read_reg( reg );
		write_reg( reg, tmp & ~mask ); // clear bit mask
	}
	//---------------------------------------------------
	//向指定地址写入数据
	//* Function：Write_MFRC5200
	//* Description：write a byte data into one register of MR RC522
 	//* Input parameter：addr--register address；val--the value that need to write in
	//* Return：Null
	void write_reg( uint8 addr, uint8 val )
	{
		CS_OUT = 0;
		//address format：0XXXXXX0
		SPI.write_byte( (addr<<1) & 0x7E ); 
		SPI.write_byte( val );
		CS_OUT = 1;
	}
	//---------------------------------------------------
	//从指定地址读取数据
	//* Function：Read_MFRC522
	//* Description：read a byte data into one register of MR RC522
	//* Input parameter：addr--register address
	//* Return：return the read value
	public uint8 read_reg( uint8 addr )
	{
		CS_OUT = 0;
		//address format：1XXXXXX0
		SPI.write_byte ( ((addr<<1)&0x7E) | 0x80 );
		uint8 val =SPI.read_byte();
		CS_OUT = 1;
		return val;
	}
	//=================================================================================
	unit SPI
	{
		public link bit SCK_DIR;
		public link bit SCK_OUT;
		
		public link bit MOSI_DIR;
		public link bit MOSI_OUT;
		
		public link bit MISO_DIR;
		public link bit MISO_IN;
		
		//---------------------------------------------------
		//初始化
		public void init()
		{
			SCK_DIR = 1;
			SCK_OUT = 0;
			
			MOSI_DIR = 1;
			MOSI_OUT = 0;
			
			MISO_DIR = 0;
			MOSI_OUT = 0;
		}
		//---------------------------------------------------
		//写一个字节
		public void write_byte( uint8 data )
		{
			loop( 8 ) {
				MOSI_OUT = data.7(bit);
				//#asm "nop"
				SCK_OUT = 1;
				//#asm "nop"
				SCK_OUT = 0;
				data << 1;
			}
		}
		//---------------------------------------------------
		//读一个字节
		public uint8 read_byte()
		{
			MOSI_OUT = 0;
			uint8 data;
			loop( 8 ) {
				data << 1;
				SCK_OUT = 1;
				//#asm "nop"
				data.0(bit) = MISO_IN;
				//#asm "nop"
				SCK_OUT = 0;
			}
			return data;
		}
	}
	
	//=================================================================================
	//THe mistake code that return when communicate with MF522
	const uint8 MI_OK		= 0x00;
	const uint8 MI_NOTAGERR	= 0x01;
	const uint8 MI_ERR	= 0x02;
	
	//MF522 command bits
	const uint8 PCD_IDLE		= 0x00; //NO action; cancel current commands
	const uint8 PCD_AUTHENT		= 0x0E; //verify password key
	const uint8 PCD_RECEIVE		= 0x08; //receive data
	const uint8 PCD_TRANSMIT	= 0x04; //send data
	const uint8 PCD_TRANSCEIVE	= 0x0C; //send and receive data
	const uint8 PCD_RESETPHASE	= 0x0F; //reset
	const uint8 PCD_CALCCRC		= 0x03; //CRC check and caculation

	//Mifare_One card command bits
	const uint8 PICC_REQIDL		= 0x26; //Search the cards that not into sleep mode in the antenna area 
	const uint8 PICC_REQALL		= 0x52; //Search all the cards in the antenna area
	const uint8 PICC_ANTICOLL	= 0x93; //prevent conflict
	const uint8 PICC_SElECTTAG	= 0x93; //select card
	const uint8 PICC_AUTHENT1A	= 0x60; //verify A password key
	const uint8 PICC_AUTHENT1B	= 0x61; //verify B password key
	const uint8 PICC_READ		= 0x30; //read 
	const uint8 PICC_WRITE		= 0xA0; //write
	const uint8 PICC_DECREMENT	= 0xC0; //deduct value
	const uint8 PICC_INCREMENT	= 0xC1; //charge up value
	const uint8 PICC_RESTORE	= 0xC2; //Restore data into buffer
	const uint8 PICC_TRANSFER	= 0xB0; //Save data into buffer
	const uint8 PICC_HALT		= 0x50; //sleep mode
	
	//------------------MFRC522 register ---------------
	//Page 0:Command and Status
	const uint8 Reserved00 = 0x00;
	const uint8 CommandReg = 0x01;
	const uint8 CommIEnReg = 0x02;
	const uint8 DivlEnReg = 0x03;
	const uint8 CommIrqReg = 0x04;
	const uint8 DivIrqReg = 0x05;
	const uint8 ErrorReg = 0x06;
	const uint8 Status1Reg = 0x07;
	const uint8 Status2Reg = 0x08;
	const uint8 FIFODataReg = 0x09;
	const uint8 FIFOLevelReg = 0x0A;
	const uint8 WaterLevelReg = 0x0B;
	const uint8 ControlReg = 0x0C;
	const uint8 BitFramingReg = 0x0D;
	const uint8 CollReg = 0x0E;
	const uint8 Reserved01 = 0x0F;
	//Page 1:Command
	const uint8 Reserved10 = 0x10;
	const uint8 ModeReg = 0x11;
	const uint8 TxModeReg = 0x12;
	const uint8 RxModeReg = 0x13;
	const uint8 TxControlReg = 0x14;
	const uint8 TxAutoReg = 0x15;
	const uint8 TxSelReg = 0x16;
	const uint8 RxSelReg = 0x17;
	const uint8 RxThresholdReg = 0x18;
	const uint8 DemodReg = 0x19;
	const uint8 Reserved11 = 0x1A;
	const uint8 Reserved12 = 0x1B;
	const uint8 MifareReg = 0x1C;
	const uint8 Reserved13 = 0x1D;
	const uint8 Reserved14 = 0x1E;
	const uint8 SerialSpeedReg = 0x1F;
	//Page 2:CFG
	const uint8 Reserved20 = 0x20;
	const uint8 CRCResultRegM = 0x21;
	const uint8 CRCResultRegL = 0x22;
	const uint8 Reserved21 = 0x23;
	const uint8 ModWidthReg = 0x24;
	const uint8 Reserved22 = 0x25;
	const uint8 RFCfgReg = 0x26;
	const uint8 GsNReg = 0x27;
	const uint8 CWGsPReg = 0x28;
	const uint8 ModGsPReg = 0x29;
	const uint8 TModeReg = 0x2A;
	const uint8 TPrescalerReg = 0x2B;
	const uint8 TReloadRegH = 0x2C;
	const uint8 TReloadRegL = 0x2D;
	const uint8 TCounterValueRegH = 0x2E;
	const uint8 TCounterValueRegL = 0x2F;
	//Page 3:TestRegister
	const uint8 Reserved30 = 0x30;
	const uint8 TestSel1Reg = 0x31;
	const uint8 TestSel2Reg = 0x32;
	const uint8 TestPinEnReg = 0x33;
	const uint8 TestPinValueReg = 0x34;
	const uint8 TestBusReg = 0x35;
	const uint8 AutoTestReg = 0x36;
	const uint8 VersionReg = 0x37;
	const uint8 AnalogTestReg = 0x38;
	const uint8 TestDAC1Reg = 0x39;
	const uint8 TestDAC2Reg = 0x3A;
	const uint8 TestADCReg = 0x3B;
	const uint8 Reserved31 = 0x3C;
	const uint8 Reserved32 = 0x3D;
	const uint8 Reserved33 = 0x3E;
	const uint8 Reserved34 = 0x3F;
	
	
	
	

