📄 pcdutils.c
字号:
#include <string.h>
#include <stdio.h>
#include <PcdUtils.h>
#include <MfRc500.h>
#include <RcComm.h>
#include <MfErrNo.h>
#include "Hardware.h"
#include "PcdShare.h"
#include "MfReg.h"
static MfCmdInfo * MpIsrInfo;
static unsigned char * MpIsrOut;
static unsigned char * MpIsrIn;
//unsigned char RxTxBuffer[MAX_RF_BUF_SIZE];
void PcdSetTmo(unsigned char tmoLength);
void ClearBitMask(unsigned char reg,unsigned char mask);
void SetBitMask(unsigned char reg,unsigned char mask);
void FlushFIFO(void);
char PcdSingleResponseCmd(unsigned char cmd,
unsigned char * send,
unsigned char * rcv,
MfCmdInfo *info);
///////////////////////////////////////////////////////////////////////
// S e t T i m e o u t L E N G T H
///////////////////////////////////////////////////////////////////////
void PcdSetTmo(unsigned char tmoLength)
{
switch(tmoLength)
{ // timer clock frequency 13,56 MHz
case 1: // short timeout (1,0 ms)
WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteRC(RegTimerReload,0x6a);// TReloadVal = 'h6a =106(dec)
break;
case 2: // medium timeout (1,5 ms)
WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteRC(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 3: // long timeout (6 ms)
WriteRC(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteRC(RegTimerReload,0xa0);// TReloadVal = 'ha0 =160(dec)
break;
case 4: // long timeout (9.6 ms)
WriteRC(RegTimerClock,0x09); // TAutoRestart=0,TPrescale=4*128
WriteRC(RegTimerReload,0xff);// TReloadVal = 'ff =255(dec)
break;
case 5:
WriteRC(RegTimerClock,0x0f); // TAutoRestart=0,TPrescale=4*128
WriteRC(RegTimerReload,0xff);// TReloadVal = 'ff =255(dec)
break;
/* case 10: // (309.3 ms) FWI=10
WriteRC(RegTimerClock,0x0F); // TAutoRestart=0,TPrescale=256*128
WriteRC(RegTimerReload,0x81);// TReloadVal = 'h81 =129(dec)
break; */
default: // short timeout (1,0 ms)
WriteRC(RegTimerClock,0x07); // TAutoRestart=0,TPrescale=128
WriteRC(RegTimerReload,tmoLength);// TReloadVal = tmoLength
break;
}
}
//////////////////////////////////////////////////////////////////////
// S E T A B I T M A S K
///////////////////////////////////////////////////////////////////////
void SetBitMask(unsigned char reg,unsigned char mask) //
{
char tmp = 0x0;
tmp = ReadRC(reg);
WriteRC(reg,tmp | mask); // set bit mask
}
//////////////////////////////////////////////////////////////////////
// C L E A R A B I T M A S K
///////////////////////////////////////////////////////////////////////
void ClearBitMask(unsigned char reg,unsigned char mask)
{
char tmp = 0x0;
tmp = ReadRC(reg);
WriteRC(reg,tmp & ~mask); // clear bit mask
}
///////////////////////////////////////////////////////////////////////
// F L U S H F I F O
///////////////////////////////////////////////////////////////////////
void FlushFIFO(void)
{
SetBitMask(RegControl,0x01);
}
//////////////////////////////////////////////////////////////////////
// W R I T E A P C D C O M M A N D
///////////////////////////////////////////////////////////////////////
char PcdSingleResponseCmd(unsigned char cmd,
unsigned char * send,
unsigned char * rcv,
MfCmdInfo *info)
{
char status = MI_OK;
char tmpStatus;
unsigned char lastBits;
unsigned char irqEn = 0x00;
unsigned char waitFor = 0x00;
unsigned char timerCtl = 0x00;
unsigned long TimeOutCount;
WriteRC(RegInterruptEn,0x7F); // disable all interrupts
WriteRC(RegInterruptRq,0x7F); // reset interrupt requests
WriteRC(RegCommand,PCD_IDLE); // terminate probably running command
FlushFIFO(); // flush FIFO buffer
// save info structures to module pointers
MpIsrInfo = info;
MpIsrOut = send;
MpIsrIn = rcv;
// initialising the ISR-Function pointer for mifare
// protocol - do this after initialising the MpXXXX variables
// PcdIsrFct = SingleResponseIsr;
//OpenExternInt0();
info->irqSource = 0x0; // reset interrupt flags
OpenExternInt0();
// READER_INT_ENABLE;
// depending on the command code, appropriate interrupts are enabled (irqEn)
// and the commit interrupt is choosen (waitFor).
switch(cmd)
{
case PCD_IDLE: // nothing else required
irqEn = 0x00;
waitFor = 0x00;
break;
case PCD_WRITEE2: // LoAlert and TxIRq
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_READE2: // HiAlert, LoAlert and IdleIRq
irqEn = 0x07;
waitFor = 0x04;
break;
case PCD_LOADCONFIG: // IdleIRq and LoAlert
case PCD_LOADKEYE2: // IdleIRq and LoAlert
case PCD_AUTHENT1: // IdleIRq and LoAlert
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_CALCCRC: // LoAlert and TxIRq
irqEn = 0x11;
waitFor = 0x10;
break;
case PCD_AUTHENT2: // IdleIRq
irqEn = 0x04;
waitFor = 0x04;
break;
case PCD_RECEIVE: // HiAlert and IdleIRq
info->nBitsReceived = -(ReadRC(RegBitFraming) >> 4);
irqEn = 0x06;
waitFor = 0x04;
break;
case PCD_LOADKEY: // IdleIRq
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSMIT: // LoAlert and IdleIRq
irqEn = 0x05;
waitFor = 0x04;
break;
case PCD_TRANSCEIVE: // TxIrq, RxIrq, IdleIRq and LoAlert
info->nBitsReceived = -(ReadRC(RegBitFraming) >> 4);
irqEn = 0x3d;//0x1d//0x3d//////allen 10.23
waitFor = 0x04;
break;
default:
status = MI_UNKNOWN_COMMAND;
}
if (status == MI_OK)
{
// Initialize uC Timer for global Timeout management
////////////////////////////////////////////////////////////////////
irqEn|=0x20; // always enable timout irq /////allen 10.23
waitFor|=0x20; // always wait for timeout///delete it
WriteRC(RegInterruptEn,irqEn | 0x80); //necessary interrupts are enabled // count up from 1
WriteRC(RegCommand,cmd); //start command
// wait for commmand completion
// a command is completed, if the corresponding interrupt occurs
// or a timeout is signaled
TimeOutCount=14049; //change from 4049
while (!(MpIsrInfo->irqSource & waitFor
|| !TimeOutCount)) // wait for cmd completion or timeout
{
TimeOutCount--;
}
WriteRC(RegInterruptEn,0x7F); // disable all interrupts
WriteRC(RegInterruptRq,0x7F); // clear all interrupt requests
SetBitMask(RegControl,0x04); // stop timer now
WriteRC(RegCommand,PCD_IDLE); // reset command register
//Temp=ReadRC(RegFIFOLength);
//Temp=ReadRC(RegFIFOData);
if (!(MpIsrInfo->irqSource & waitFor)) // reader has not terminated
{ // timer 3 expired
status = MI_ACCESSTIMEOUT;
}
else
status = MpIsrInfo->status; // set status
if (status == MI_OK) // no timeout error occured
{
if ((tmpStatus = (ReadRC(RegErrorFlag) & 0x17))) // error occured
{
if (tmpStatus & 0x01) // collision detected
{
info->collPos = ReadRC(RegCollPos); // read collision position
status = MI_COLLERR;
}
else
{
info->collPos = 0;
if (tmpStatus & 0x02) // parity error
{
status = MI_PARITYERR;
}
}
if (tmpStatus & 0x04) // framing error
{
status = MI_FRAMINGERR;
}
if (tmpStatus & 0x10) // FIFO overflow
{
FlushFIFO();
status = MI_OVFLERR;
}
if (tmpStatus & 0x08) // CRC error
{
status = MI_CRCERR;
}
if (status == MI_OK)
status = MI_NY_IMPLEMENTED;
// key error occures always, because of
// missing crypto 1 keys loaded
}
// if the last command was TRANSCEIVE, the number of
// received bits must be calculated - even if an error occured
if (cmd == PCD_TRANSCEIVE || cmd == PCD_RECEIVE)
{
// number of bits in the last byte
lastBits = ReadRC(RegSecondaryStatus) & 0x07;
if (lastBits)
info->nBitsReceived += (info->nBytesReceived-1) * 8 + lastBits;
else
info->nBitsReceived += info->nBytesReceived * 8;
}
}
else
{
info->collPos = 0x00;
}
}
// READER_INT_DISABLE;
//PcdIsrFct = EmptyPcdIsrFct; // reset the ISR-Function pointer to
// an empty function body
// do this before clearing the Mp XXXX variables
CloseExternInt0();
MpIsrInfo = 0; // reset interface variables for ISR
MpIsrOut = 0;
MpIsrIn = 0;
return status;
}
///////////////////////////////////////////////////////////////////////////////
// Interrupt Handler RIC
///////////////////////////////////////////////////////////////////////////////
void SingleResponseIsr(void)
{
unsigned char irqBits; //static
unsigned char irqMask;
unsigned char oldPageSelect;
unsigned char nbytes;
unsigned char cnt;
if (MpIsrInfo && MpIsrOut && MpIsrIn) // transfer pointers have to be set
// correctly
{
oldPageSelect = ReadRawRC(RegPage); // save old page select
// Attention: ReadRC cannnot be
// used because of the internal
// write sequence to the page
// reg
WriteRawRC(RegPage,0x80); // select page 0 for ISR
while( (ReadRawRC(RegPrimaryStatus) & 0x08)) // loop while IRQ pending
{
irqMask = ReadRawRC(RegInterruptEn); // read enabled interrupts
// read pending interrupts
irqBits = ReadRawRC(RegInterruptRq) & irqMask;
MpIsrInfo->irqSource |= irqBits; // save pending interrupts
//************ LoAlertIRQ ******************
if (irqBits & 0x01) // LoAlert
{
nbytes = MFIFOLength - ReadRawRC(RegFIFOLength);
// less bytes to send, than space in FIFO
if ((MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent) <= nbytes)
{
nbytes = MpIsrInfo->nBytesToSend - MpIsrInfo->nBytesSent;
WriteRawRC(RegInterruptEn,0x01); // disable LoAlert IRQ
}
// write remaining data to the FIFO
for ( cnt = 0;cnt < nbytes;cnt++)
{
WriteRawRC(RegFIFOData,MpIsrOut[MpIsrInfo->nBytesSent]);
MpIsrInfo->nBytesSent++;
}
WriteRawRC(RegInterruptRq,0x01); // reset IRQ bit
}
//************* TxIRQ Handling **************
if (irqBits & 0x10) // TxIRQ
{
WriteRawRC(RegInterruptRq,0x10); // reset IRQ bit
WriteRawRC(RegInterruptEn,0x82); // enable HiAlert Irq for
// response
if (MpIsrInfo->cmd == PICC_ANTICOLL1) // if cmd is anticollision
{ // switch off parity generation
WriteRC(RegChannelRedundancy,0x02); // RxCRC and TxCRC disable, parity disable
WriteRawRC(RegPage,0x00); // reset page address
}
}
//************* HiAlertIRQ or RxIRQ Handling ******************
if (irqBits & 0x0E) // HiAlert, Idle or RxIRQ
{
// read some bytes ( length of FIFO queue)
// into the receive buffer
nbytes = ReadRawRC(RegFIFOLength);
// read date from the FIFO and store them in the receive buffer
for ( cnt = 0; cnt < nbytes; cnt++)
{
MpIsrIn[MpIsrInfo->nBytesReceived] = ReadRawRC(RegFIFOData);
MpIsrInfo->nBytesReceived++;
}
WriteRawRC(RegInterruptRq,0x0A & irqBits);
// reset IRQ bit - idle irq will
// be deleted in a seperate section
}
//************** IdleIRQ Handling ***********
if (irqBits & 0x04) // Idle IRQ
{
WriteRawRC(RegInterruptEn,0x20); // disable Timer IRQ
WriteRawRC(RegInterruptRq,0x20); // disable Timer IRQ request
irqBits &= ~0x20; // clear Timer IRQ in local var
MpIsrInfo->irqSource &= ~0x20; // clear Timer IRQ in info var
// when idle received, then cancel
// timeout
WriteRawRC(RegInterruptRq,0x04); // reset IRQ bit
// status should still be MI_OK
// no error - only used for wake up
}
//************* TimerIRQ Handling ***********
if (irqBits & 0x20) // timer IRQ
{
WriteRawRC(RegInterruptRq,0x20); // reset IRQ bit
MpIsrInfo->status = MI_NOTAGERR; // timeout error
// otherwise ignore the interrupt
}
}
WriteRawRC(RegPage,oldPageSelect | 0x80);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -