📄 mfrc500uc.c
字号:
///////////////////////////////////////////////////////////////////////////////
// Copyright (c), Philips Semiconductors Gratkorn
//
// (C)PHILIPS Electronics N.V.2000
// All rights are reserved.
// Philips reserves the right to make changes without notice at any time.
// Philips makes no warranty, expressed, implied or statutory, including but
// not limited to any implied warranty of merchantibility or fitness for any
//particular purpose, or that the use will not infringe any third party patent,
// copyright or trademark. Philips must not be liable for any loss or damage
// arising from its use.
///////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include "RICReg.H"
#include "MfRc500.h"
#include "PICCCmdConst.h"
#include "MfErrNo.h"
/*
* Projekt: MF EV X00 Firmware
*
* $Workfile:: MfRc500uC.c $
* $Modtime:: 24.06.02 15:41 $
* $Author:: Hb $
* $Revision:: 8 $
*
*
* This library modul is written for a C166 microcontroller derivative.
* The source can be ported to other platforms very easily.
* In our case the reader module is
* connected via memory mapped io at base address 0x100000.
* The interrupt pin of the reader IC is assumed to be connected to
* the fast external interrupt pin INT0# (active low) and the reset
* pin of the reader IC should be connected to a dedicated port pin
* (Port: P1 Pin: 9).
* In this configuration, a reset of the reader module is independend
* from the reset of the microcontroller.
* All protocoll
* relevant timing constraints are generated
* by the internal timer of the reader module.
*
* Some explanations to the programming method of this library.
* There are three kind of functions coded in this module.
*
* ---- internal functions, which have no prototypes in a header
* file. This kind of functions are not intended to be used
* outside of this file
* ---- commands, which are intended for the reader module itself
* ---- commands, which are intended for any tag in the rf field.
* These commands are send to the reader and the reader module
* transmitts the data to the rf interface.
*
* Commands for the reader and for the tag have the appropriate
* prefix (PCD for Proximity Coupled Device or reader module
* PICC for Proximity Integrated Circuit Card or tag)
* and their protypes are defined in the header file.
* Certainly, each command for a PICC consists of an instruction to the PCD.
* Therefore
* the function PcdSingleResponseCmd is very important for the understanding
* of the communication.
*
* The basic functionality is provided by the interrupt service
* routine (SingleResponseCmd), which closely works together with the function
* PcdSingleResponseCmd. All kinds of interrupts are serviced by the
* same ISR.
*/
///////////////////////////////////////////////////////////////////////////////
// M O D U L V A R I A B L E S
///////////////////////////////////////////////////////////////////////////////
// interrupt vector number for interrupt of the RIC
// select the appropriate value corresponding to the microcontroller in use
#define READER_INT // e. g. 0x18
// disable reader interrupt
// select the appropriate value corresponding to the microcontroller in use
#define READER_INT_DISABLE // e. g. EXICON &= ~0x0002
// enable reader interrupt
// select the appropriate value corresponding to the microcontroller in use
#define READER_INT_ENABLE // e. g. EXICON |= 0x0002
// initialize reset pin and change port direction
// select the appropriate value corresponding to the microcontroller in use
#define READER_INIT_RESET // e. g. P6 |= 0x20; DP6 |= 0x20
// set reset pin
// select the appropriate value corresponding to the microcontroller in use
#define READER_RESET // e. g. P6 |= 0x20
// clear reset pin
// select the appropriate value corresponding to the microcontroller in use
#define READER_CLEAR_RESET // e. g. P6 &= ~0x20
// memory base address corresponding to the previous set address select register
// select the appropriate value corresponding to the microcontroller in use
#define MEMORY_BASE_ADDRESS 0x100000
// the RIC has only 3 address lines - page select is necessary
#define GetRegPage(addr) (0x80 | (addr>>3))
/* ISO14443 Support Properties
* Some of the protokoll functions of ISO14443 needs information about
* the capability of the reader device, which are provided by this
* constants.
*/
//{
#define TCLFSDSNDMAX 8 ///< max. frame size send
#define TCLFSDRECMAX 8 ///< max. frame size rcv
#define TCLDSMAX 3 ///< max. baudrate divider PICC --> PCD
#define TCLDRMAX 3 ///< max. baudrate divider PCD --> PICC
#define TCLDSDFLT 0 ///< default baudrate divider PICC --> PCD
#define TCLDRDFLT 0 ///< default baudrate divider PCD --> PICC
//}
/* ISR communication structures
* All parameters are passed to the ISR via this structure.
*/
//{
// struct definition for a communication channel between function and ISR
typedef struct
{
unsigned char cmd; //!< command code
char status; //!< communication status
unsigned short nBytesSent; //!< how many bytes already sent
unsigned short nBytesToSend; //!< how many bytes to send
unsigned short nBytesReceived;//!< how many bytes received
unsigned long nBitsReceived; //!< how many bits received
unsigned char irqSource; //!< which interrupts have occured
unsigned char collPos; /*!< at which position occured a
collision*/
unsigned char errFlags; //!< error flags
unsigned char saveErrorState;//!< accumulated error flags for
//!< multiple responses
unsigned char RxAlignWA; //!< workaround for RxAlign = 7
unsigned char DisableDF; //!< disable disturbance filter
} MfCmdInfo;
// Convinience function for initialising the communication structure.
#define ResetInfo(info) \
info.cmd = 0; \
info.status = MI_OK;\
info.irqSource = 0; \
info.nBytesSent = 0; \
info.nBytesToSend = 0; \
info.nBytesReceived = 0; \
info.nBitsReceived = 0; \
info.collPos = 0; \
info.errFlags = 0; \
info.saveErrorState = 0; \
info.RxAlignWA = 0; \
info.DisableDF = 0;
// In order to exchange some values between the ISR and the calling function,
// a struct is provided.
volatile MfCmdInfo MInfo;
// communication info stucture
static volatile MfCmdInfo *MpIsrInfo = 0;
// ISR send buffer
static volatile unsigned char *MpIsrOut = 0;
// ISR receive buffer
static volatile unsigned char *MpIsrIn = 0;
//}
// storage of the last selected serial number including check byte.
// For multi level serial numbers, only the first 4 bytes are stored.
unsigned char MLastSelectedSnr[5];
// storage buffer for receive and transmit routines
//{
#define MEMORY_BUFFER_SIZE 300
volatile unsigned char MemPool[MEMORY_BUFFER_SIZE];
volatile unsigned char *MSndBuffer = MemPool; // pointer to the transmit buffer
volatile unsigned char *MRcvBuffer = MemPool; // pointer to the receive buffer
//}
/* Higher Baudrate Control
* attention: RegDecoderControl is modified in CascAnticoll
* Because of standard baudrate usage during anticollision, the
* register can be written. For general purpose usage, only some bits
* should be set.
*
* Please pay attention, that the location of the configuration array is
* in ROM space, that means that on 16 bit microcontroller the access
* should be word aligned.
*/
//{
typedef struct
{
unsigned short SubCarrierPulses; ///< RegRxControl1
unsigned short RxCoding; ///< RegDecoderControl
unsigned short RxThreshold; ///< RegRxThreshold
unsigned short BPSKDemControl; ///< RegBPSKDemControl
} t_DSCfg;
typedef struct
{
unsigned short CoderRate; ///< RegCoderControl
unsigned short ModWidth; ///< RegModWidth
} t_DRCfg;
const t_DSCfg MDSCfg[4] = {{0x73,0x08,0x88,0x00} // Manchaster 106 kBaud
,{0x53,0x09,0x50,0x0C} // BPSK 212 kBaud
,{0x33,0x09,0x50,0x0C} // BPSK 424 kBaud
,{0x13,0x09,0x50,0x0C}}; // BPSK 848 kBaud
const t_DRCfg MDRCfg[4] = {{0x19,0x13} // Miller 106 kBaud
,{0x11,0x07} // Miller 212 kBaud
,{0x09,0x03} // Miller 424 kBaud
,{0x01,0x01}}; // Miller 848 kBaud
// data send baudrate divider PICC --> PCD
static unsigned char MDSI = TCLDSDFLT;
// data send baudrate divider PCD --> PICC
static unsigned char MDRI = TCLDRDFLT;
//}
// Write one byte to the reader IC address space
/*!
* -o address (IN) reader ic register address
* -o value (IN) 8 bit value
* return: none
*
* Function for writting one char to the reader module
*
* The reader module is connected to a 16 bit demultiplexed bus,
* therefore the address pin of the reader module is mapped as
* follows: \n
* uC Reader \n
* A1 A0 \n
* A2 A1 \n
* A3 A2 \n
*
* In order to get the correct address, the original address need to
* be multiplied by 2.
*/
#define WriteRawRC(addr,value) *(gpcRCBaseAddress + addr) = value;
//! Read one byte from the reader IC address space
/*!
* -o address (IN) reader ic register address
* -o value (IN) 8 bit value
* return: none
*
* Function for reading one char from the reader module
*
* The reader module is connected to a 16 bit demultiplexed bus,
* therefore the address pin of the reader module is mapped as
* follows: \n
* uC Reader \n
* A1 A0 \n
* A2 A1 \n
* A3 A2 \n
*
* In order to get the correct address, the original address need to
* be multiplied by 2.
*/
#define ReadRawRC(addr) (*(gpcRCBaseAddress + addr))
//! Open Reader IC Connection
/*!
* -o none
* return: MI_OK
* other error opening reader ic channel
*
* Open and initialize communication channel to the reader module
*/
char OpenRC(void);
//! Write one byte to the reader IC address space
/*!
* -o address (IN) reader ic register address
* -o value (IN) 8 bit value
* return: none
*
* This function determines the necessary page address of the
* reader module and writes the page number to the page
* register and the value to the specified address.
*/
void WriteRC(unsigned char Address, unsigned char value);
//! Write one byte to the reader IC address space
/*
* -o address (IN) reader IC register address
* return: value 8 bit data, read from the reader ic address space
*
* This function determines the necessary page address of the
* reader module and writes the page number to the page
* register and reads the value from the specified address.
*/
unsigned char ReadRC(unsigned char Address);
//! Close reader IC communication channel
/*!
* -o none
* return: none
*
* Closing the communication channel to the reader module
*/
void CloseRC(void);
// In case of a parallel connection, the address space of the reader module
// needs to be mapped to the address space of the microcontroller. Therefore
// a base address is reserved.
unsigned char * const gpcRCBaseAddress = (unsigned char * const)(MEMORY_BASE_ADDRESS);
///////////////////////////////////////////////////////////////////////////////
// Open Reader Communication
///////////////////////////////////////////////////////////////////////////////
char OpenRC(void)
{
signed char status = MI_OK;
READER_INIT_RESET;
return status;
}
///////////////////////////////////////////////////////////////////////////////
// Close Reader Communication
///////////////////////////////////////////////////////////////////////////////
void CloseRC(void)
{
}
///////////////////////////////////////////////////////////////////////////////
// G E N E R I C W R I T E
///////////////////////////////////////////////////////////////////////////////
void WriteRC(unsigned char Address, unsigned char value)
{
WriteRawRC(0x00,GetRegPage(Address)); // select appropriate page
WriteRawRC(Address,value); // write value at the specified
// address
}
///////////////////////////////////////////////////////////////////////////////
// G E N E R I C R E A D
///////////////////////////////////////////////////////////////////////////////
unsigned char ReadRC(unsigned char Address)
{
WriteRawRC(0x00,GetRegPage(Address)); // select appropriate page
return ReadRawRC(Address); // read value at the specified
}
///////////////////////////////////////////////////////////////////////////////
// Prototypes for local functions
///////////////////////////////////////////////////////////////////////////////
/// Internal Authentication State Switch
/*!
* -o auth_mode (IN)
* enum: selects master key A or master key B
* - PICC_AUTHENT1A
* - PICC_AUTHENT1B
*
* -o *snr (IN)
* 4 byte serial number of the card, which should be
* authenticated
* -o sector (IN) Range [0..15]
* specifies the key RAM address
* from which the keys should be taken
* return: enum:
* - MI_OK
* - CCE
* - MI_BITCOUNTERR wrong number of bits received
* - MI_AUTHERR wrong keys for selected card
* - MI_KEYERR error while loading keys
*
*
* Internal authentication state function.
*/
char Mf500PiccAuthState(unsigned char auth_mode,// PICC_AUTHENT1A, PICC_AUTHENT1B
unsigned char *snr, // 4 byte serial number
unsigned char sector); // 0 <= sector <= 15
// sector address for authentication
/// Write Baudrate Divider
/*!
* -o none
* return: MI_OK
*
* Write function for baudrate divider and PCD properties
*/
char Mf500PcdWriteAttrib(void);
/* ISR Communication Structure
* Data, which have to be passed between ISR and other functions are
* colleted within one structure.
*/
//{
// ISR for Single Response Commands
/*
* -o none
* return: none
*
* This function is a central routine in the communication chain between
* PCD and PICC.
*/
//interrupt (READER_INT)
void SingleResponseIsr(void);
// Command issuer for Single Response Commands
/*
* -o cmd (IN)
* Command type
* enum:
* - PCD_IDLE
* - PCD_WRITEE2
* - PCD_READE2
* - PCD_LOADCONFIG
* - PCD_LOADKEYE2
* - PCD_AUTHENT1
* - PCD_CALCCRC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -