/*******************************************************************************
*
*    Copyright(C) 2021 All rights reserved.
*
* 文件：card_5557_driver.c
* 作者：IC WM group
* 版本：V1.00
* 日期：2021-3-12
* 描述：IC卡驱动
* 属性：
* 修改：V1.00, 2021-3-12,创建本文件
*
* 声明：
*******************************************************************************/
//#include "libbase.h"
//#include <string.h>
 #include "sys_config.h"
#if CARD_USED
#include "UWater_card_5557_driver.h"

//CARD_MESSAGE card_message;
typedef struct
{
    u8 buf[28];			//读卡缓冲区

    u8 ix;				//读卡缓冲区字节计数
    u8 le;				//需要读出的字节数
    u8 ct;				//读单字节位计数
    u8 er;				//读数错误记录

    u8 st;				//读数起始控制标识，Sequence Terminator检测控制
    u8 bt;				//读数位中断位置标识，Bit Time检测控制


    u8 in;				//有卡无卡标志
} RF;
RF rf;

uint16_t rf_w;			//PCA捕获时长，码流中电平的宽度
u8 rf_e;				//VC比较的结果，码流中电平的状态
u8 rf_int;				//捕获标志，标识是否发生了捕捉
u32 pca_int_cnt;		//防干扰中断次数计数
static u16 abs_in = 0, abs_out = 0;
void CardSearch125kInit(void);
void CardSearch125kDeInit(void);

///////////////////////////////////////////////////////////
//记录一位数据，MSB方式
static void rf_rb(u8 b)
{
    rf.buf[rf.ix] <<= 1;			//数据左移
    rf.buf[rf.ix] |= (b & 0x01u);	//存入当前位

    rf.ct++;						//已接收位数加1

    if((rf.ct & 0x07) == 0)			//超出7位（8位），数据字节加1
    {
        rf.ix++;
    }
}
//写数据，发送起始Gap
//Gap间隔应该比正常数据位间隔大
static void rf_sg(void)
{
    M0P_TIM1_MODE0->M0CR_f.TOGEN = 0;
    delay_us(280);      // 10-50 fc
    M0P_TIM1_MODE0->M0CR_f.TOGEN = 1;
}
//写数据，发送1位数据
//每位数据由输出载波和间隔（不输出载波）组成
//其中“间隔”都相等，时长比起始Gap短
//输出载波时长有两种，长代表1，短代表0
static void rf_tb(u8 b)
{
    if(b & 0x01)
    {
        delay_us(444);  // 48-63 fc  载波长
    }
    else
    {
        delay_us(188);  // 16-31 fc  载波短
    }

    M0P_TIM1_MODE0->M0CR_f.TOGEN = 0;	//关载波
    delay_us(152);      // 8-30 fc   位间的间隔，比起始Gap短
    M0P_TIM1_MODE0->M0CR_f.TOGEN = 1;	//开载波
}

//使用带Sequence terminator的Machester模式
//在数据的起始和结束都有Sequence terminator
//Machester码要求每一个数据位时间内，中必须有电平变化，
//其中上升沿为0，下降沿为1（对应GE Thomas编码，反转曼彻斯特码与之相反）
//Sequence terminator波形为: _-___-__（MSB）, 转为数据则为0X0X(反曼码则为1X1X)，
//其中，起始的“0”（或“1”）与其前的状态或数据相连，这里不用来做判断
//X代表非法的曼彻斯特码，这里为1位时长的低电平
static void rf_rx(uint16_t w, u8 e)		//参数描述：pca捕获计数值，当前vc输出状态
{
    u8 b = !e;							//可以表示当前触发的边沿，e为高，则b为低，上升沿，反之下降沿
    u8 p;


    if((15 < w) && (w < 160))			//半个位宽
    {
        p = 1;
    }
    else if((170 < w) && (w < 290))		//一个位宽，码率约2128bps
    {
        p = 2;
    }
    else if((300 < w) && (w < 800))		//一个半位宽
    {
        p = 3;
    }
    else								//错误数据
    {
        p = 0;
    }

    if(rf.bt == 0)						//前3次进来 manchester编码
    {
        if(rf.st == 0)					//首次进来
        {
            if((p == 3) && (b == 1))	//间隔长，下降沿(X1?)
            {
                rf.st = 1;
            }
        }
        else if(rf.st == 1)				//第二次进来
        {
            if((p == 1) && (b == 0))	//间隔短，上升沿(X1确认)
            {
                rf.st = 2;
            }
            else						//错误，重来
            {
                rf.st = 0;
            }
        }
        else if(rf.st == 2)				//第三次进来
        {
            if((p == 3) && (b == 1))	//间隔长，下降沿(X1,其中1为有效数据，当前在第一个数据位的半位位置)
            {
                rf_rb(b);
                rf.bt = 2;
            }
            else if((p == 2) && (b == 1))	//间隔适中，下降沿(X,无数据，当前在第一个数据位起始，下一个数据位必然为上升沿，即0)
            {
                rf.bt = 1;
            }
            else						//错误，重来
            {
                rf.st = 0;
            }
        }
        else
        {
            ;
        }
    }
    else if(rf.bt == 1)					//非首次，此前处于数据位的起始
    {
        if(p == 1)						//间隔短，半位，当前在数据位中间
        {
            rf_rb(b);					//记录1位数据
            rf.bt = 2;
        }
        else							//错误
        {
            rf.er = 1;
        }
    }
    else if(rf.bt == 2)					//非首次，此前处于数据位的中间
    {
        if(p == 1)						//间隔短，半位，当前在数据位的起始，转到起始对齐处理
        {
            rf.bt = 1;
        }
        else if(p == 2)					//间隔适中，1位，当前在数据位的中间，数据有效
        {
            rf_rb(b);					//记录1位数据
            rf.bt = 2;
        }
        else							//错误
        {
            rf.er = 2;
        }
    }
    else
    {
        ;
    }
}
//读数据
static u8 rf_rd(u8 *buf, u8 c)		//数据缓存，数据字节数
{
    uint16_t i;

    wdt_reset();

    for(i = 0; i < c; i++)		//清缓冲区
    {
        rf.buf[i] = 0;
    }

    rf.le = c;					//初始化读数控制结构体
    rf.ix = 0;
    rf.ct = 0;
    rf.er = 0;
    rf.st = 0;
    rf.bt = 0;

    M0P_PCA->CCON_f.CR = 1;		//启动PCA计数

    i = 0;

    while(rf.ix < rf.le)
    {
        if(rf_int)				//捕获中断已经发生
        {
            rf_int = 0;
            rf_rx(rf_w, rf_e);	//处理捕获的时长、电平，获得有效数据
        }

        if(rf.er)				//如果有错误发生，结束读数
        {
            break;
        }

        if(++i > 1000 * c)		//超时，结束读数，置错误标志为8.每字节给1000个循环
        {
            rf.er = 8;
            break;
        }
    }

    M0P_PCA->CCON_f.CR = 0;		//停止PCA计数

    if(rf.er)					//有错误，返0
    {
        return 0;
    }

    for(i = 0; i < c; i++)		//无错误，复制读数，返1
    {
        buf[i] = rf.buf[i];
    }

    return 1;
}


//块写
static void rf_wk(u8 b, void* buf)	//block编号，数据
{
    u8 i;

    di();

    rf_sg();

    rf_tb(1);
    rf_tb(0);
    rf_tb(0);

    for(i = 0; i < 32; i++)
    {
        rf_tb(((u8 *)buf)[i >> 3] >> ((u8)(~i) & 0x07));
    }

    rf_tb(b >> 2);
    rf_tb(b >> 1);
    rf_tb(b >> 0);

    ei();

    delay_ms(8);
}

//块读
static u8 rf_rk(u8 b, void* buf)	//block编号，缓存
{
    di();

    rf_sg();

    rf_tb(1);
    rf_tb(0);
    rf_tb(0);

    rf_tb(b >> 2);
    rf_tb(b >> 1);
    rf_tb(b >> 0);

    ei();

    if(rf_rd(buf, 4))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
//卡复位
void rf_rt(void)
{
    delay_ms(1);

    di();
    rf_sg();
    rf_tb(0);
    rf_tb(0);
    ei();

    delay_ms(1);
}
//选择第0页
void rf_rr(void)
{
    di();
    rf_sg();
    rf_tb(1);
    rf_tb(0);
    ei();
}
////中断处理
//static uint16_t u16CaptureB;
//u8 togleA =0x01;
//void Tim4_IRQHandler(void)
//{
//    //捕获中断A
//    if(TRUE == Adt_GetIrqFlag(M0P_ADTIM4, AdtCMAIrq))
//    {        
////        Adt_GetCaptureValue(M0P_ADTIM4, AdtCHxA, &u16CaptureA);  //脉冲低电平计数值
//        
//        Adt_ClearIrqFlag(M0P_ADTIM4, AdtCMAIrq);
//    }
//    //捕获中断B
//    if(TRUE == Adt_GetIrqFlag(M0P_ADTIM4, AdtCMBIrq))
//    {
//        togleA = !togleA;
//        Gpio_WriteOutputIO(GpioPortC,GpioPin13,togleA);
//        Adt_GetCaptureValue(M0P_ADTIM4, AdtCHxB, &u16CaptureB);   //脉冲高电平计数值
//        Adt_ClearCount(M0P_ADTIM4);					//清计数
//        Adt_ClearIrqFlag(M0P_ADTIM4, AdtCMBIrq);
//    }
//}
void card_isr(void)
{
    if(M0P_PCA->CCON_f.CCF0 == 1)  //PCA_CH0
    {
        M0P_PCA->ICLR_f.CCF0 = 0;		//清0中断标志
        rf_w = M0P_PCA->CCAP0_f.CCAP0;	//取出PCA计数的捕获值
        rf_e = M0P_VC->IFR_f.VC1_FILTER;//取出当前VC模块比较的电平结果(signal+和signal-)
        rf_int = 1;
        M0P_PCA->CCON_f.CR = 0;			//停止计数
        M0P_PCA->CNT_f.CNT = 0;			//计数器清0
        M0P_PCA->CCON_f.CR = 1;			//重新开始计数

        if(++pca_int_cnt > PCA_INT_MAX)	//防止干扰，频繁中断而超时复位。28字节正常情况中断次数约500左右
        {
            pca_int_cnt = 0;			//中断次数超限，清0中断计数
            rf.er = 9;					//置次数超限错误，防止超时看门狗复位
        }
    }
}

//读卡初始化，配置端口和定时器
void card_init(void)
{
    stc_adt_basecnt_cfg_t    stcAdtBaseCntCfg;
    stc_adt_CHxX_port_cfg_t  stcAdtTIMCfg;
    stc_gpio_cfg_t        stcTIMPort;

    DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
    DDL_ZERO_STRUCT(stcAdtTIMCfg);
    DDL_ZERO_STRUCT(stcTIMPort);

    //PA7 设置为TIM4_CHB
    stcTIMPort.enDir  = GpioDirIn;
    Gpio_Init(CARD_DET_PORT, CARD_DET_PIN, &stcTIMPort);	//Gpio_Init(GpioPortA, GpioPin7, &stcTIMPort);		//det_sh 为输入 吴注 210307 kabiao
    Gpio_SetAfMode(CARD_DET_PORT, CARD_DET_PIN, CARD_DET_PIN_AF);	//Gpio_SetAfMode(GpioPortA, GpioPin7, GpioAf7);		//det_sh 为TIM4_CHB 210307 kabiao
	
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE);   //ADT外设时钟使能

    stcAdtBaseCntCfg.enCntMode = AdtSawtoothMode;				//锯齿波模式 吴注
    stcAdtBaseCntCfg.enCntDir = AdtCntUp;					//递加计数 吴注
    stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0;				//PCLK0 PCLK=HCLK/1 4M 吴注
    Adt_Init(M0P_ADTIM4, &stcAdtBaseCntCfg);                      //ADT载波、计数模式、时钟配置		打开中断，但没有具体处理 吴注

	Adt_SetPeriod(M0P_ADTIM4, 0xFFFF);                             //周期设置

    stcAdtTIMCfg.enCap = AdtCHxCompareInput;                   //CHB设为捕获输入
    Adt_CHxXPortCfg(M0P_ADTIM4, AdtCHxB, &stcAdtTIMCfg);       //端口CHB配置，捕获输入功能
    Adt_CfgHwCaptureB(M0P_ADTIM4, AdtHwTrigCHxBRise);          //硬件捕获B条件配置		上升沿捕获 吴注

//	Adt_CfgHwCaptureB(M0P_ADTIM4, AdtHwTrigCHxBFall);
//	Adt_ClearAllIrqFlag(M0P_ADTIM4);
//	Adt_CfgIrq(M0P_ADTIM4, AdtCMBIrq, TRUE);    //捕获中断B配置
//	EnableNvic(ADTIM4_IRQn, IrqLevel3, TRUE);   //AdvTimer4中断使能
	
    // Adt_StartCount(AdtTIM4);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, FALSE);

    stcTIMPort.enDir = GpioDirOut;
    Gpio_ClrIO(RF125K_PORT, RF125K_PIN );
    Gpio_Init(RF125K_PORT, RF125K_PIN,  &stcTIMPort);	//210307kabiao
    Gpio_ClrIO(SIGNALN_PORT, SIGNALN_PIN);						//signal- 接地，借用TIMPort结构体简单处理，寻卡时再配为模拟
    Gpio_Init(SIGNALN_PORT, SIGNALN_PIN, &stcTIMPort);
    Gpio_ClrIO(SIGNALP_PORT, SIGNALP_PIN);						//signal，借用TIMPort结构体简单处理，寻卡时再配为模拟
    Gpio_Init(SIGNALP_PORT, SIGNALP_PIN, &stcTIMPort);
    CTL_SH_OUT = 0;										//寻卡控制 输出0
    CTL_SH_DIR = 0;
    CardSearch125kInit();				//初始化寻卡驱动
}
/*
void Tim4_IRQHandler(void)
{
    //捕获中断B
    if(TRUE == Adt_GetIrqFlag(M0P_ADTIM4, AdtCMBIrq))
    {        
//        Adt_ClearIrqFlag(M0P_ADTIM4, AdtCMBIrq);
		Adt_ClearAllIrqFlag(M0P_ADTIM4);
    }
}*/

void Pca_IRQHandler(void)
{
    card_isr();
}

/*******************************************************************************
Function    : card_enable
Description : 读卡开始
Input       :
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
void card_enable(void)
{
    stc_bt_mode0_cfg_t		stcBtBaseCfg;
    stc_gpio_cfg_t			stcTIMPort;

    stc_vc_channel_cfg_t	stcChannelConfig;
    stc_vc_dac_cfg_t		stcDacConfig;

    stc_pcacfg_t			stcConfig;
//    stc_pca_capmodcfg_t		stcModConfig;

    DDL_ZERO_STRUCT(stcBtBaseCfg);
    DDL_ZERO_STRUCT(stcTIMPort);

    DDL_ZERO_STRUCT(stcDacConfig);
    DDL_ZERO_STRUCT(stcChannelConfig);//变量清0

    DDL_ZERO_STRUCT(stcConfig);
//    DDL_ZERO_STRUCT(stcModConfig);

    //Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //GPIO 外设时钟使能


////////////////////////////////////////////////////////////////////////////////
    // Enable VC
    Sysctrl_SetPeripheralGate(SysctrlPeripheralVcLvd, TRUE);

    #if 0
    stc_gpio_config_t stcGpioCfg;
    DDL_ZERO_STRUCT(stcGpioCfg);
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA, GpioPin12, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin12, GpioAf5);//VC输出
    #endif

    Gpio_SetAnalogMode(SIGNALP_PORT, SIGNALP_PIN);    //模拟输入	//signal 吴注
    Gpio_SetAnalogMode(SIGNALN_PORT, SIGNALN_PIN);    //模拟输入	//signal- 吴注

    stcChannelConfig.enVcChannel = VcChannel1;			//选择通道0
    stcChannelConfig.enVcCmpDly  = VcDelay10mv;			//迟滞10mV
//	stcChannelConfig.enVcBiasCurrent = VcBias300na;		//最小功耗，响应慢
    stcChannelConfig.enVcFilterTime = VcFilter14us;		//输出滤波时间
    stcChannelConfig.enVcInPin_P = VcInPCh5;
    stcChannelConfig.enVcInPin_N = VcInNCh1;//ResDivOut;//AiBg1p2;
	stcChannelConfig.enVcOutCfg = VcOutDisable;			//结果输出除能
	stcChannelConfig.bFlten = TRUE;						//滤波输出使能

    stcDacConfig.bDivEn = FALSE;
    stcDacConfig.u8DivVal = 0;
    stcDacConfig.enDivVref = VcDivVrefAvcc;

    Vc_DacInit(&stcDacConfig);
    Vc_Init(&stcChannelConfig);
	Vc_Cmd(VcChannel1, TRUE);
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
    // Enable PCA, VC1_OUT--->PCA CH0
    Gpio_SfPcaCfg(GpioSfPcaCH0, GpioSf4);  // VC1_OUT--->PCA CH0

    //使能PCA,外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralPca, TRUE);

    //INT ENABLE
    EnableNvic(PCA_IRQn, IrqLevel3, TRUE);
    Pca_ConfModulexIt(PcaModule0,TRUE);			//使能pca0中断

    stcConfig.pca_clksrc  = PcaPclkdiv4;		//PCLK/4,
	stcConfig.pca_cidl = TRUE;					//休眠模式PCA停止工作
//    stcConfig.pca_ecom = PcaEcomDisable;		//比较器功能禁止
	stcConfig.pca_capp = PcaCappEnable;			//上升沿捕获允许
	stcConfig.pca_capn = PcaCapnEnable;			//下降沿捕获允许
//	stcConfig.pca_mat = PcaMatDisable;			//禁止匹配
//	stcConfig.pca_tog = PcaTogDisable;			//禁止翻转
//	stcConfig.pca_pwm = PcaPwm8bitDisable;		//禁止8位PWM功能
//	stcConfig.pca_epwm = PcaEpwmDisable;		//禁止16位PWM功能
	stcConfig.pca_carr = 65535;					//重载值
    Pca_M0Init(&stcConfig);
	M0P_PCA->CCAPM0_f.ECOM = PcaEcomDisable;	//比较器功能禁止
	
//	Pca_Set4Wdte(FALSE);

    Pca_SetCnt(0);
    //Pca_Run();
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
    // 输出125K
//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
    CardSearch125kDeInit();     //TIM1的模式2/3配置会影响到模式0，因此要先恢复一下默认值
    stcTIMPort.enDir  = GpioDirOut;
    Gpio_Init(RF125K_PORT, RF125K_PIN, &stcTIMPort);	//Gpio_Init(GpioPortA, GpioPin5, &stcTIM0Port);//210307kabiao
    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_AF);	//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf4);   // select timer0A//210307kabiao

    stcBtBaseCfg.enWorkMode = BtWorkMode0;                  //定时器模式
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能，计数时钟为内部PCLK
    stcBtBaseCfg.enPRS      = BtPCLKDiv1;                   //PCLK/1
    stcBtBaseCfg.enCntMode  = Bt16bitArrMode;               //自动重载16位计数器/定时器
    stcBtBaseCfg.bEnTog     = TRUE;                         //翻转输出使能
    stcBtBaseCfg.bEnGate    = FALSE;
    stcBtBaseCfg.enGateP    = BtGatePositive;

    Bt_Mode0_Init(TIM1, &stcBtBaseCfg);                     //TIM1 的模式0功能初始化

    // 125kHz@4M
    Bt_M0_ARRSet(TIM1, 65536 - 16);                         //设置重载值

    // 与重载值相同
    Bt_M0_Cnt16Set(TIM1, 65536 - 16);                       //设置计数初值
    Bt_M0_Enable_Output(TIM1, TRUE);                         //TIM1 端口输出使能
////////////////////////////////////////////////////////////////////////////////

    //TIM1 运行
    Bt_M0_Run(TIM1);
    delay_ms(10);
    pca_int_cnt = 0;
}

/*******************************************************************************
Function    : card_disable
Description : 读卡结束
Input       :
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
void card_disable(void)
{
    // stop OPA
//    OPA_DeInit();
//    Sysctrl_SetPeripheralGate(SysctrlPeripheralOpa, FALSE);

    // stop VC
	Vc_Cmd(VcChannel1, FALSE);
	M0P_VC->VC1_CR_f.FLTEN = 0;

    M0P_BGR->CR_f.BGR_EN = 0x0u; //BGR禁止
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, FALSE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralVcLvd, FALSE);


    // stop PCA
    Pca_StartPca(FALSE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralPca, FALSE);


    // stop TIM1
    Bt_M0_EnTOG_Output(TIM1, FALSE);
    Bt_M0_Stop(TIM1);
    //初始化TIM1为寻卡方式
	CardSearch125kInit();   //模式0的配置不会影响模式2/3，因此可以不恢复默认配置

//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, FALSE); //关闭Base Timer外设时钟
//    Gpio_SetAfMode(GpioPortA, GpioPin2, GpioAf0);//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf0);    // select as IO	210307kabiao
//    RF125K_OUT = 0;
//    RF125K_DIR = 0;                   // set IO low
}


/*******************************************************************************
Function    : card_read_all
Description : 读卡, 读取1-7块，28字节
Input       :
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
u8 card_read_all(u8 * buffer)
{
    delay_ms(1);

    rf_rr();		//复位卡片

    if(rf_rd(buffer, 28))	//读卡
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/*******************************************************************************
Function    : card_write_all
Description : 写卡, 写1-7块
Input       :
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
u8 card_write_all(void* buffer)
{
    u8 i, k, m;
    u8 *p = (u8 *)buffer;
    u8 temp[28] = {0};

    for(m = 0; m < 3; m++)		//总计尝试写3次
    {
        p = (u8 *)buffer;

        for(i = 1; i < 8; i++)
        {
            rf_wk(i, p);		//按block编号，逐个写
            p += 4;
        }

        for(k = 0; k < 6; k++)		//总计尝试读6次
        {
            Card5557ClrIntCnt();	//读卡前，清0中断次数，防超时用

            if(card_read_all(temp))	//读出成功，则比较写入与读出，失败则再读，共6次
            {
                if(memcmp(temp, buffer, 28) != 0)	//写入与读出不同，则重试写入，相同则返回
                {
                    break;
                }
                else
                {
                    return 1;
                }
            }

        }
    }


    return 0;

}

/*******************************************************************************
Function    : card_write_block
Description : 写卡,
Input       : block, 1-7
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
u8 card_write_block(u8 block, void* buffer)
{
    if(0 == block)
    {
        return 0;
    }

    delay_ms(1);
    rf_wk(block, buffer);

    return 1;
}

u8 card_read_block(u8 block, void *buffer)
{
    delay_ms(1);

    return rf_rk(block, buffer);
}



/*******************************************************************************
Function    : card_check
Description : 寻卡
Input       :
Output      :
Return      : int, 1-成功, 0-错误
History     :
*******************************************************************************/
u8 card_search(void)
{
    u32  i;
    u8 ret = 0;

    uint16_t gap = 0;
    static u16 last, check;


//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE);//advanced Timer时钟使能
    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_AF);		//Tim1_CHA
    Bt_M23_Cnt16Set(TIM1, 1);					//设初值
    Bt_ClearAllIntFlag(TIM1);					//清中断标志
    Adt_ClearCount(M0P_ADTIM4);					//清计数
    CTL_SH_OUT = 1;
    CTL_SH_DIR = 0;								//输出高
    Adt_StartCount(M0P_ADTIM4);					//启动TIM4计时
    Bt_M23_EnPWM_Output(TIM1, TRUE, FALSE);		//使能TIM1 PWM输出
    Bt_M23_Run(TIM1);							//启动TIM1

    for(i = 0; i < 4 * 160 * 4; i++)
    {
        if(Bt_GetIntFlag(TIM1, BtUevIrq))		//查询TIM1更新事件，输出20个脉冲后置起
        {
            break;
        }
    }

    Bt_ClearAllIntFlag(TIM1);					//清中断标志
    Bt_M23_Stop(TIM1);							//停止TIM1
    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_IO);//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf0);    // select as IO	210307kabiao
    RF125K_OUT = 0;
    RF125K_DIR = 0;                   // set IO low
    Bt_M23_EnPWM_Output(TIM1, FALSE, FALSE);	//去能TIM1 PWM输出
//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, FALSE); //关闭Base Timer外设时钟

    delay_us(300);  // adjust	延时等待检测信号放电

    if(M0P_ADTIM4->STFLR_f.CMBF)						//查询法查捕获状态
    {
        M0P_ADTIM4->STFLR_f.CMBF = 0;
        Adt_GetCaptureValue(M0P_ADTIM4, AdtCHxB, &gap);	//取回捕获时长
    }
	Adt_ClearAllIrqFlag(M0P_ADTIM4);
    Adt_StopCount(M0P_ADTIM4);			//停止TIM4计数
	
    CTL_SH_OUT = 0;
    CTL_SH_DIR = 0;                  //关ctl_sh，停止检测 
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, FALSE); //关时钟
	
    if(4 * 160 * 4 <= i)			//超时，重新初始化寻卡驱动，防止意外
    {
        card_init();
    }

//    card_message.test = gap;

    if(gap > 2000)			//时间异常
    {
        return 0;
    }
	if(gap == 0)
	{
		card_init();
		return 0;
	}

    if(0 == rf.in)		//无卡状态
    {
        if(last - gap > CARDIN_DELTA)//40) // card in 时间差满足贴卡
        {
            check = gap;		//记录刷卡距离
            rf.in = 1;			//置有卡状态
            ret = 1;			//返回刷卡

            if(0 == abs_in)		//复位后第1次刷卡
            {
                abs_in = gap;	//记录刷卡绝对值
                abs_out = last;	//记录去卡绝对值，卡贴近和移开扰动大，去卡的时候设置易出现刷卡距离大于去卡情况
            }
            else if(abs_in + 4 < gap)	//刷卡距离变远
            {
                abs_in++;
            }
            else if(abs_in > gap + 3)	//刷卡距离变近
            {
                abs_in--;
            }
        }
        else if(0 != abs_in && gap < abs_in + 2)	//卡距离足够近，超过记录的距离，也认为刷卡
        {
            check = gap;
            rf.in = 1;
            ret = 1;
        }
    }
    else if(1 == rf.in)		//有卡状态
    {
        if(gap > CARDOUT_DELTA + last)//27) // card out  时间差满足去卡
        {
            rf.in = 0;				//置无卡状态

            if(0 == abs_out)		//复位首次去卡，前面刷卡时已经设置，这里其实无效
            {
                abs_out = gap;
            }
            else if(abs_out + 3 < gap)		//card out 的值大于存储的值，增大，即去卡距离变大
            {
                abs_out++;
            }
            else if(abs_out > gap + 4)		//card out 的值远小于存储的值，减小，即去卡距离变小
            {
                abs_out--;
            }

            if(abs_out < abs_in + THRESHHOLD_DIFF)	//锁定去卡距离必须大于刷卡距离一定值，实际总是出现去卡小于刷卡情况
            {
                abs_out = abs_in + THRESHHOLD_DIFF;
            }
        }
        else if(gap > CARDOUT_DELTA + check)//35			//通过check值，即本次刷卡距离，去卡，不调整绝对去卡值
        {
            rf.in = 0;
        }
        else if(0 != abs_out && gap + 2 > abs_out)	//卡距离足够远，超过记录的距离，认为去卡
        {
            rf.in = 0;
        }
    }
    else		//异常情况
    {
        rf.in = 0;
        abs_in = 0;
        abs_out = 0;
    }

    last = gap;		//记下本次检卡得到的参数（时长，等效为距离）

    return ret;
}

/*******************************************************************************
Function    : CardSearch125kInit
Description : tim1输出125k 20脉冲初始化
Input       :
Output      :
Return      : 
History     :不同于读卡概率较小，寻卡时需要经常使用，因此加入初始化，寻卡时仅启停即可
*******************************************************************************/
void CardSearch125kInit(void)		//210312kabiao
{
    stc_bt_mode23_cfg_t	stcBtBaseCfg;
    stc_gpio_cfg_t		stcTIMPort;
    stc_bt_m23_compare_cfg_t stcBtExtendCfg;

    DDL_ZERO_STRUCT(stcBtBaseCfg);
    DDL_ZERO_STRUCT(stcTIMPort);
    DDL_ZERO_STRUCT(stcBtExtendCfg);

//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
	stcTIMPort.enDir  = GpioDirOut;
	stcTIMPort.enCtrlMode = GpioAHB;
    Gpio_Init(RF125K_PORT, RF125K_PIN, &stcTIMPort);	//Gpio_Init(GpioPortA, GpioPin5, &stcTIM0Port);//210307kabiao
    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_AF);	//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf4);   // select timer0A//210307kabiao

    stcBtBaseCfg.enWorkMode	= BtWorkMode2;                  //锯齿波模式
    stcBtBaseCfg.enCntDir	= BtCntUp;						//向上计数
    stcBtBaseCfg.enPRS      = BtPCLKDiv1;                   //PCLK 4M
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能，计数时钟为内部PCLK
    stcBtBaseCfg.enPWMTypeSel = BtIndependentPWM;			//独立PWM输出
    stcBtBaseCfg.enPWM2sSel	= BtSinglePointCmp;				//单点比较使能，使用CCRA比较控制OCREFA输出
    stcBtBaseCfg.bOneShot	= TRUE;							//单次触发模式使能
    stcBtBaseCfg.bURSSel	= TRUE;							//仅选择上、下溢出时更新
	//不使用中断，发生更新时，轮询处理

    stcBtExtendCfg.enCh0ACmpCap	= BtCHxCmpMode;				//比较输出
    stcBtExtendCfg.enCH0ACmpCtrl = BtPWMMode2;				//PWM模式2，低于CCR时OCREF输出低
    stcBtExtendCfg.enCH0APolarity = BtPortOpposite;			//负极性，输出与OCREF相反
    stcBtExtendCfg.bCh0ACmpBufEn = FALSE;					//禁用比较A缓存功能
    stcBtExtendCfg.enCh0ACmpIntSel = BtCmpIntNone;			//无比较匹配中断
	//不使用B通道

    Bt_Mode23_Init(TIM1, &stcBtBaseCfg);					//TIM1 的模式23功能初始化
    Bt_M23_PortOutput_Cfg(TIM1, &stcBtExtendCfg);			//模式23配置

    // 125kHz@4M
    Bt_M23_ARRSet(TIM1, 31, FALSE);							//设置重载值，立即更新

    Bt_M23_CCR_Set(TIM1, BtCCR0A, 15);						//设CCR
    Bt_M23_SetValidPeriod(TIM1, 19);						//重复周期20
    Bt_M23_Cnt16Set(TIM1, 1);								//设初值
    Bt_ClearAllIntFlag(TIM1);

    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_IO); // select as IO	210307kabiao
    RF125K_OUT = 0;
    RF125K_DIR = 0;                   // set IO low
//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, FALSE); //关闭Base Timer外设时钟
}

/*******************************************************************************
Function    : CardSearch125kDeInit
Description : tim1输出125k 20去初始化
Input       :
Output      :
Return      : 
History     : 防止对读卡造成干扰
*******************************************************************************/
void CardSearch125kDeInit(void)		//
{
    stc_bt_mode23_cfg_t	stcBtBaseCfg;
    stc_gpio_cfg_t		stcTIMPort;
    stc_bt_m23_compare_cfg_t stcBtExtendCfg;

    DDL_ZERO_STRUCT(stcBtBaseCfg);
    DDL_ZERO_STRUCT(stcTIMPort);
    DDL_ZERO_STRUCT(stcBtExtendCfg);

//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
	stcTIMPort.enDir  = GpioDirOut;
	stcTIMPort.enCtrlMode = GpioAHB;
    Gpio_Init(RF125K_PORT, RF125K_PIN, &stcTIMPort);	//Gpio_Init(GpioPortA, GpioPin5, &stcTIM0Port);//210307kabiao
    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_AF);	//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf4);   // select timer0A//210307kabiao

    stcBtBaseCfg.enWorkMode	= BtWorkMode2;                  //锯齿波模式
    stcBtBaseCfg.enCntDir	= BtCntUp;						//向上计数
    stcBtBaseCfg.enPRS      = BtPCLKDiv1;                   //PCLK 4M
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能，计数时钟为内部PCLK
    stcBtBaseCfg.enPWMTypeSel = BtIndependentPWM;			//独立PWM输出
    stcBtBaseCfg.enPWM2sSel	= BtSinglePointCmp;				//单点比较使能，使用CCRA比较控制OCREFA输出
    stcBtBaseCfg.bOneShot	= FALSE;							//单次触发模式除能
    stcBtBaseCfg.bURSSel	= FALSE;							//选择上、下溢出、软件更新UG、从模式复位时更新
	//不使用中断，发生更新时，轮询处理

    stcBtExtendCfg.enCh0ACmpCap	= BtCHxCmpMode;				//比较输出
    stcBtExtendCfg.enCH0ACmpCtrl = BtPWMMode2;				//PWM模式2，低于CCR时OCREF输出低
    stcBtExtendCfg.enCH0APolarity = BtPortOpposite;			//负极性，输出与OCREF相反
    stcBtExtendCfg.bCh0ACmpBufEn = FALSE;					//禁用比较A缓存功能
    stcBtExtendCfg.enCh0ACmpIntSel = BtCmpIntNone;			//无比较匹配中断
	//不使用B通道

    Bt_Mode23_Init(TIM1, &stcBtBaseCfg);					//TIM1 的模式23功能初始化
    Bt_M23_PortOutput_Cfg(TIM1, &stcBtExtendCfg);			//模式23配置

    Bt_M23_CCR_Set(TIM1, BtCCR0A, 0);						//设CCR
    Bt_M23_SetValidPeriod(TIM1, 0);						//重复周期0
    Bt_ClearAllIntFlag(TIM1);

    Gpio_SetAfMode(RF125K_PORT, RF125K_PIN, RF125K_PIN_IO);//Gpio_SetAfMode(GpioPortA, GpioPin5, GpioAf0);    // select as IO	210307kabiao
    RF125K_OUT = 0;
    RF125K_DIR = 0;                   // set IO low
//    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, FALSE); //关闭Base Timer外设时钟
}
void ClearCardSta(void)
{
    abs_in = 0;
    abs_out = 0;
}

void Card5557ClrIntCnt(void)
{
    pca_int_cnt = 0;
}

void  Card5557PreSleep(void)
{

}
void  Card5557WakeSleep(void)
{

}

#endif

