kejingfan 4b8460f4ce 重构各页面代码,从h文件改为cpp文件;
添加硬件接口并添加,readerAPI使用硬件接口获取invenory信息和connect;
完成开卡初始页面,获取卡号和学号。
2024-07-29 11:24:26 +08:00

439 lines
9.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//-----------------------------------------
// 关于类说明
// 类 CVCD 用于 描述 VCD
// 应用软件调用类的成员函数可以对VICC进行访问
//
// 派生类CVCD_Sim 用软件仿真VCD通过transponderEnter函数仿真VICC进入了射频场
// class CVCD_Sim : public CVCD
//
// 派生类CVCD_Ours 封装了Ours的reader.
// class CVCD_Ours : public CVCD
//
//
//#pragma once
#ifndef _VCD_H_
#define _VCD_H_
#include "HLog.h"
#include <cstring>
//
// 并部分实现函数的部分功能
// 比如select request寻址模式一定是address mode
//
// 有些命令,可以由用户确定寻址模式
// 00: 所有的卡都应答
// 01: 被选择卡应答
// 02: 特定地址的卡应答
// else: 不支持;
//
//---------------------------------------------------
// 下面定义了reader成员函数的返回结果
//
// 比如一个addressed的命令收到多个应答或者没有应答
// 注意此处没有应答不指VICC没有影带有些场景VICC不应答也是正确的
// 比如stay quiet收不到任何响应其实是正确的。
// 此处没有应答指VICC应该应答而没有应答
//
#define ISO15693_READER_OK 0xA0
#define ISO15693_READER_ER_LESS_ANSWER 0xA1 // 没有应答
#define ISO15693_READER_ER_MORE_ANSWERS 0xA2 // 收到多个应答
#define ISO15693_READER_ER_FRAME 0xA3 // 收到frame格式错可能发生了冲突软件表示frame错误.
// 副载波0: for single subcarrier / 1: for double subcarrier
#define ISO15693_REQ_FLAG_SUB_CARRIER_S 0
#define ISO15693_REQ_FLAG_SUB_CARRIER_D 1
// 速率, 0: for low data rate / 1: for high data rate
#define ISO15693_REQ_FLAG_DATA_RATE_H 0
#define ISO15693_REQ_FLAG_DATA_RATE_H 1
// 编码方式0: for 1/4 / 1 for 1/256;
#define ISO15693_CODING_1_FROM_4 0
#define ISO15693_CODING_1_FROM_256 1
#define ISO15693_RSP_ERR_NO 0
#define MAX_TRANSPONDERS 16
#define MAX_PKT_LEN 1024
// 寻址模式
// 除inventory命令外其他都涉及到寻址模式.
#define ISO15693_INVENTORY_NO_VICC 0x00
#define ISO15693_INVENTORY_ONE_VICC 0x01
#define ISO15693_INVENTORY_MORE_VICCS 0x02
// VCD的射频场最多支持的VICC数
// 定义为16个是因为inventory采用16slots的情况下最多一次可以清晰收到16个VICC的应答。
// 如果发生了碰撞,或者访问清晰收到的,或者继续寻找碰撞的。
#define MAX_NUM_VICCS 16
typedef unsigned char uchar_t;
typedef enum
{
mode_all,
mode_select,
mode_addressed
}ISO15693_MODE_E;
// VICC的部分信息.
typedef struct tag_VICCInfo
{
uchar_t aucUID[8];
uchar_t ucValid; // 0 for unvalid, 1 for valid.
uchar_t ucDSFID;
uchar_t ucAFI;
uchar_t ucBlockNum;
uchar_t ucBlockSize;
uchar_t ucICRef;
}VICCInfo;
class CVCD
{
public:
CVCD(void)
{
m_ucSubCarrier = ISO15693_REQ_FLAG_SUB_CARRIER_D; // 默认双载波
m_ucDataRate = ISO15693_REQ_FLAG_DATA_RATE_H; // 默认高速率
m_ucDataCoding = ISO15693_CODING_1_FROM_4;
m_ucSlots = 16;
m_pLog = NULL;
for( int i = 0; i < MAX_NUM_VICCS; i++ )
{
m_astVICCs[i].ucValid = 0;
}
}
virtual ~CVCD(void)
{
}
public:
// 正式执行inventory前设置这些参数
int set( uchar_t ucSubCarrier, uchar_t ucDataRate, uchar_t ucSlots )
{
m_ucSubCarrier = ucSubCarrier;
m_ucDataRate = ucDataRate;
m_ucSlots = ucSlots;
}
int setSubCarrier( uchar_t ucSubCarrier )
{
m_ucSubCarrier = ucSubCarrier;
}
int setDataRate( uchar_t ucDataRate )
{
m_ucDataRate = ucDataRate;
}
int setSlots( uchar_t ucSlots )
{
m_ucSlots = ucSlots;
}
void setDataCoding_1from4()
{
m_ucDataCoding = ISO15693_CODING_1_FROM_4;
}
void setDataCoding_1from256()
{
m_ucDataCoding = ISO15693_CODING_1_FROM_256;
}
void setLog( CHLog *plog )
{
m_pLog = plog;
}
// 如何设置和VCD/Reader的连接
// 串口.
virtual int connectReader()
{
return 1;
}
virtual int disconnectReader( )
{
return 1;
}
/*
virtual int connectReaderByCOM( int comno )
{
return 1;
}
*/
// 在执行了inventory后用户可以获得芯片的信息。
// 其中获得的blocksize和blocknum在readblocks()和write block()时,有用.
VICCInfo getVICCInfo( uchar_t aucUID[8] )
{
VICCInfo vicc;
memset( (uchar_t *)&vicc, 0x00, sizeof(vicc));
int k = getVICC( aucUID );
if( k != -1 )
{
return m_astVICCs[k];
}
return vicc;
}
public:
// 协议命令
// 返回:>0表示读到的Transponder数量;
//
virtual int inventory(
bool bAFIUsed,
uchar_t ucAFI,
int nViccNum, // 应用层可以接收的UID数量;
uchar_t aucDSFID[],
uchar_t aucUID[][8] )
{
m_bAFIUsed = bAFIUsed;
if( m_bAFIUsed )
{
m_ucAFI = ucAFI;
}
return ISO15693_RSP_ERR_NO;
}
//------------------------------------------
// 状态转换
// stayquiet
// cmd=0x02;
// 寻址方式:只能是地址模式, UID必须;
virtual int stayQuiet( uchar_t *pucUID )
{
return ISO15693_RSP_ERR_NO;
}
// select命令
// cmd=0x25
// 寻址方式一定是地址模式, UID必须;
virtual int select( uchar_t *pucUID )
{
return ISO15693_RSP_ERR_NO;
}
// reset to ready
// cmd=0x26
// 可以使地址模式,也可以是选择模式
virtual int resetToReady( uchar_t *pucUID )
{
return ISO15693_RSP_ERR_NO;
}
//------------------------------------------
// 操作
// 操作类命令寻址模式只能地址或者select
//
// 0x20
virtual int readSingleBlock(
uchar_t *pucUID, // NULL表示select模式
uchar_t optional_flag, // optional bit = 1, 要求返回block的安全状态
uchar_t ucBlkno, // blockno
uchar_t buf[], // 返回读取的数据
uchar_t *pucSecurity // 如果optional_flag = 1, 返回该block的安全状态1表示locked.
)
{
return ISO15693_RSP_ERR_NO;
}
// 0x21
virtual int writeSingleBlock(
uchar_t *pucUID, // NULL表示select模式
uchar_t ucBlkno, //
uchar_t ucBlksize,
uchar_t buf[] )
{
return ISO15693_RSP_ERR_NO;
}
// 0x22
virtual int lockBlock(
uchar_t *pucUID, // NULL表示select模式
int blockno )
{
return ISO15693_RSP_ERR_NO;
}
// 0x23
virtual int readMultipleBlocks(
uchar_t *pucUID, // NULL表示select模式
uchar_t optional_flag, // optional bit = 1, 要求返回block的安全状态
uchar_t ucBlkno, // 开始block no
uchar_t blocknum, // 实际读的block是blocknum+1;
uchar_t buf[], // 返回读取的数据
uchar_t aucSecurity[] // 如果optional_flag = 1, 返回该block的安全状态1表示locked.
)
{
return ISO15693_RSP_ERR_NO;
}
// 0x24
virtual int writeMultipleBlocks(
uchar_t *pucUID, // NULL表示select模式
uchar_t ucBlkno, // 开始block no
uchar_t blocknum, // 实际写的block是blocknum+1;
uchar_t ucBlksize,
uchar_t buf[] )
{
return ISO15693_RSP_ERR_NO;
}
//----------------------------------------------------------
// AFI & DSFID
//
// CMD: 0x27
// optional 不处理.
virtual int writeAFI(
uchar_t *pucUID, // NULL表示select模式
uchar_t ucAFI )
{
return ISO15693_RSP_ERR_NO;
}
//
// CMD: 0x28
// optional 不处理.
virtual int lockAFI(
uchar_t *pucUID // NULL表示select模式
)
{
return ISO15693_RSP_ERR_NO;
}
//
// CMD: 0x29
// optional 不处理.
virtual int writeDSFID(
uchar_t *pucUID, // NULL表示select模式
uchar_t ucDSFID )
{
return ISO15693_RSP_ERR_NO;
}
//
// CMD: 0x2A
// optional 不处理.
virtual int lockDSFID(
uchar_t *pucUID // NULL表示select模式
)
{
return ISO15693_RSP_ERR_NO;
}
// CMD: 0x2B
//
virtual int getSystemInfo(
uchar_t *pucUID,
uchar_t *pinfoFlag,
uchar_t *pDSFID, uchar_t *pAFI, uchar_t *pBlockNum, uchar_t *pBlockSize, uchar_t *pICRef
)
{
return ISO15693_RSP_ERR_NO;
}
protected:
void CRC16( int buflen, uchar_t buf[], uchar_t *pucCRCL, uchar_t *pucCRCH );
bool ISO15693_checkCRC16( int buflen, uchar_t buf[] );
void ISO15693_getCRC16( int buflen, uchar_t buf[], uchar_t *pucCRCL, uchar_t *pucCRCH );
/**
* 在inventory后获取某个VICC的systeminfo
* 生成CVICC.
* 其中blocksize & blocknum 用于以后执行read,write命令用。
* 输入pucUID. 8字节的UID.
*/
virtual bool setVICC( uchar_t aucUID[8] )
{
uchar_t infoFlag;
uchar_t ucDSFID, ucAFI, ucBlockNum, ucBlockSize;
uchar_t ucICRef;
if( getSystemInfo( aucUID, &infoFlag, &ucDSFID, &ucAFI, &ucBlockNum, &ucBlockSize, &ucICRef ) != ISO15693_RSP_ERR_NO )
{
return false;
}
// OK.
for( int i = 0; i < MAX_NUM_VICCS; i++ )
{
if( m_astVICCs[i].ucValid == 0 )
{
m_astVICCs[i].ucValid = 1;
if( infoFlag & (1 << 0) )
{
m_astVICCs[i].ucDSFID = ucDSFID;
}
else if( infoFlag & ( 1 << 1 ))
{
m_astVICCs[i].ucAFI = ucAFI;
}
else if( infoFlag & ( 1 << 2 ) )
{
m_astVICCs[i].ucBlockNum = ucBlockNum;
m_astVICCs[i].ucBlockSize = ucBlockSize;
}
else if( infoFlag & ( 1 << 3 ))
{
m_astVICCs[i].ucICRef = ucICRef;
}
memcpy( m_astVICCs[i].aucUID, aucUID, 8 );
return true;
}
}
return false;
}
int getVICC( uchar_t aucUID[8] )
{
for( int i = 0; i < MAX_NUM_VICCS; i++ )
{
if( memcmp(m_astVICCs[i].aucUID, aucUID, 8 ) == 0 )
{
return i;
}
}
return -1;
}
protected:
void log( char *str )
{
if( m_pLog )
{
m_pLog->logstr( str );
}
}
void logDIM( int len, uchar_t aucDat[] )
{
if( m_pLog )
{
m_pLog->logDIM( len, aucDat );
}
}
protected:
// 全局性配置
// VCD自己的选择
uchar_t m_ucDataCoding; // 编码方式0: for 1/4 / 1 for 1/256;
uchar_t m_ucSlots; // 016 slots or 1 slots;
// VCD对VICC的要求
uchar_t m_ucSubCarrier; // 副载波0: for single subcarrier / 1: for double subcarrier
uchar_t m_ucDataRate; // 速率, 0: for low data rate / 1: for high data rate
// 执行防碰撞循环时可能多次发送inventory request每个都涉及是否使用AFI
// 因此设置为成员变量;
//
uchar_t m_ucAFI;
bool m_bAFIUsed;
// 记录日志.
CHLog* m_pLog;
// 通过inventory命令后发现的viccs.
VICCInfo m_astVICCs[MAX_NUM_VICCS];
};
#endif