#include "XTDriver.h"
#include "hardware/adc_cfg.h"
#include "hardware/timer_cfg.h"
volatile uint32_t XT_SquareCount = 0; 	//发送载波个数
volatile uint16_t XT_FreeBackMaxCur,XT_FreeBackMinCur,XT_FreeBackMaxTime,XT_FreeBackMinTime,XT_CommEndMaxCur;
volatile uint8_t 	XT_EnFreeBack_Test,XT_CommEnd_CurEn;
volatile uint8_t XT_SendSquareFlag = 1;   	//发送方波标志
volatile uint8_t XT_ReadUIDFlag = 1;		//扫描标志




#if XT_Read_AD_Sample_C > FIREBUS_ADC_BUF_LEN
#error "JQDriver.c Firbus AD Sample BUFFER SIZE LIMIT"
#else
volatile uint16_t* XT_ADC_Buf = FireBus_ADC_Buf;//AD采样缓存区
#endif

volatile uint8_t XT_ADCCollectStartFlag = 1;		//ADC采集标志

volatile uint32_t XT_ADC_BaseValue = 0;				//ADC采集最低电压
volatile uint32_t XT_ADC_CollectValue_sum = 0;		//ADC采集电压和
#define  XT_FreeBack_Noise  800

//static uint32_t XT_ADCCollectIncrementValue = XTCollectIncrementValue;
//static uint32_t XT_ADCCollectSumValue = XTCollectSumValue;	
//static uint32_t XT_TIMCollectTimerOverflowUs = XTCollectTimerOverflowUs;   

//static uint32_t XT_ADCSingleCollectAckValue = XTSingleCollectAckValue;

//static CurrentSample_Range_eu XT_CollectResistance = XTCollectResistance;

/*
@brief 通信反码信息初始化
*/
void XT_FreeBack_Prapare(uint8_t enable_flag)
{
	XT_FreeBackMaxCur = 0;
	XT_FreeBackMaxTime = 0;
	XT_FreeBackMinCur = 0xFFFF;
	XT_FreeBackMinTime = 0xFFFF;
	XT_EnFreeBack_Test = enable_flag;
}

static void XT_CommBegin()
{
	CurrentSampleR_Def;
	//WaitDelayEnd(50);//5ms
  //delay_ms(5);
  delay_wait_untill_ms(5);
}
static void XT_CommEnd()
{
	uint16_t us_temp;
	//StartDelayTime();
  TimerCount_Off();
  delay_wait_start();
	if(XT_CommEnd_CurEn > 0)
	{
		delay_os_ms(10);
		us_temp = ADC_Comm1p6mA_EndCur();
		if(us_temp > XT_CommEndMaxCur)
		{
			XT_CommEndMaxCur = us_temp;
		}
	}
	CurrentSampleR_Def;
}

static void XT_SendBit(uint8_t bit)
{
	uint8_t i;
	if( bit == XTBIT0 )
	{
		
		for(i=0;i<5;i++)
		{
			XTBUS_W_0;
			delay_us(XT_DAT_PLUS_T);
			XTBUS_W_1;
			delay_us(XT_DAT_PLUS_T);
		}
		delay_us(XT_BIT_DELAY);      //位结束符
	}
	else if( bit == XTBIT1)
	{
		for(i=0;i<3;i++)
		{
			XTBUS_W_0;
			delay_us(XT_DAT_PLUS_T);
			XTBUS_W_1;
			delay_us(XT_DAT_PLUS_T);
		}
		
		delay_us(XT_BIT_DELAY);      //位结束符
	}
}

static void XT_SendData(uint8_t *DownData, uint8_t DownLength)
{
	uint8_t temp,i,j;
	XT_CommBegin();
	//发送数据
	for(i=0;i<DownLength;i++)
	{
		temp = DownData[i] ;
		for(j=0;j<8;j++)
		{
			XT_SendBit( (temp >> 7) & 0x01 );
			temp <<= 1;
		}
	}
}


volatile uint8_t XT_Trim_Flag = 0;
static void XT_TrimPlusCallback(uint8_t flag)
{
	if(flag == 1)
	{
		XTBUS_W_0;
	}else if(flag > 1){
		XTBUS_W_1;
	}
	XT_Trim_Flag = flag;
}

static void XT_SendTrimSquare(uint16_t cycle,uint16_t duty,  uint32_t count)
{
	delay_us(XTCmdAndSquareUs);
	FireBus_ClkAmend(cycle,duty,count,XT_TrimPlusCallback);
	XT_Trim_Flag = 0;
	while(XT_Trim_Flag != 3)
	{
		delay_ms(20);
	}
	
}

/*
@brief 直接反馈模式
@param timeoutcnt 回读超时时间 单位0.1ms
@param ConfirmAckCount ADC 采样确认个数
@param *executiontime 
*/
static uint8_t XT_Get_Ack(uint32_t timeoutcnt, uint8_t ConfirmAckCount,uint32_t *executiontime)
{
	uint32_t  FeekValue=0,count=0;
	uint32_t ul_readtime = 0,ul_runtime = 0;
	uint8_t rtv = 1;
	LED1_Out_On;
	TimerCount_Init();
	Get100usCount();	
	Power_SetSampleRange_Seep(XTDriver_Sample_R,ADC_SPEED_HFAST);
	//延时700us
	delay_us(XTCmdAndSquareUs);	
//	XT_ADC_BaseValue = 0;
//	while(us_temp < 64)
//	{
//		XT_ADC_BaseValue += ADC_GetCurADCFast();
//	}
//	XT_ADC_BaseValue = (XT_ADC_BaseValue>>6) +  XT_FreeBack_Noise;
	XT_ADC_BaseValue = XT_FreeBack_Noise;
	while(1)             
	{
		FeekValue = ADC_GetCurADCFast();
		if(FeekValue >= XT_ADC_BaseValue)
		{
			count++;
		}
		else
		{
			count=0;
		}
		if(count>=ConfirmAckCount)
		{
			*executiontime = ul_readtime + GetCountTimerCnt();
			rtv = 0;
			break;
		}
		ul_runtime = GetCountTimerCnt();
		if(ul_runtime > 60000)
		{
			ul_readtime += Get100usCount();
			ul_runtime = 0;
		}
		ul_runtime = ul_readtime+ul_runtime;
		if(ul_runtime >= timeoutcnt){
      // time out
			rtv = 2;
			break;
    }
	}
	LED1_Out_Off;
	XTBUS_IDLE;
	Power_SetSampleCurrentRange(Current_Max);
	XT_CommEnd();
  if(rtv){
    rtv=!0;
  }
	return rtv;
}





static void XT_ReceiveData(uint8_t *UpData, uint32_t ReceiveBitLength)
{	
	uint8_t uc_data;
	uint32_t ul_readcount,ul_adv_sum;
	uint16_t us_adccount ,us_index,us_ack_count;
	XTBUS_RWIDLE;
	delay_us(XTCmdAndSquareUs);	
	
	Power_SetSampleRange_Seep(XTDriver_Sample_R,ADC_SPEED_HIGH);
	
	UpData[0] = 0;
	XTBUS_WR_0;
	delay_us(500);
	ul_readcount = 0;
	while( ul_readcount <  ReceiveBitLength)
	{
		if((ul_readcount & 0x07) == 0)
		{
			uc_data = 0;
		}
		XTBUS_WR_1;
		delay_us(120);
		for(us_adccount = 0; us_adccount < XT_Read_AD_Sample_C; us_adccount++)
		{
			XT_ADC_Buf[us_adccount] = ADC_GetCurADCFast();
		}
		XTBUS_WR_0;
		
		for(us_index = 3; us_index < us_adccount; us_index ++)
		{
			if((XT_ADC_Buf[us_index] < XT_FreeBack_Noise) && (XT_ADC_Buf[us_index-1] < XT_FreeBack_Noise))
			{
				break;
			}
			if((XT_ADC_Buf[us_index] < XT_ADC_Buf[us_index-2] ) && (XT_ADC_Buf[us_index-1] < XT_ADC_Buf[us_index-3]))
			{
				break;
			}
		}
		if(us_index >= us_adccount)
		{
			delay_us(450);
			continue;
		}
		us_ack_count = 0;
		ul_adv_sum = 0;
		while(us_index < us_adccount)
		{
			if(XT_ADC_Buf[us_index] > XT_FreeBack_Noise)
			{
				ul_adv_sum += XT_ADC_Buf[us_index];
				us_ack_count++;
			}else if(us_ack_count < 2)//连续两个大于2启动检测
			{
				ul_adv_sum = 0;
				us_ack_count = 0;
			}
			us_index++;
		}
		
		if(us_ack_count > 10)
		{
			
			 ul_adv_sum = ul_adv_sum / us_ack_count;
			if( XT_EnFreeBack_Test > 0 )
			{
				if(XT_FreeBackMaxCur == 0)
				{
					XT_FreeBackMaxCur = XT_FreeBackMinCur = ul_adv_sum;
				}else if(ul_adv_sum > XT_FreeBackMaxCur){
					XT_FreeBackMaxCur = ul_adv_sum;
				}else if(ul_adv_sum < XT_FreeBackMinCur){
					XT_FreeBackMinCur = ul_adv_sum;
					
				}
				if(XT_FreeBackMaxTime == 0)
				{
					XT_FreeBackMaxTime = XT_FreeBackMinTime = us_ack_count;
				}else if(us_ack_count > XT_FreeBackMaxTime)
				{
					XT_FreeBackMaxTime = us_ack_count;
				}else if(us_ack_count < XT_FreeBackMinTime){
					XT_FreeBackMinTime = us_ack_count;
				}
				
			}
			uc_data |= (0x80 >>  (ul_readcount & 0x07));
		}
		UpData[ul_readcount>>3] = uc_data;
		ul_readcount++;
		delay_us(300);
		
	}
	XTBUS_RWIDLE
	XT_CommEnd();
}


static void XT_ScanUID(uint8_t *UpData, uint32_t ReceiveBitLength)
{
	uint8_t uc_data;
	uint32_t ul_readcount;
	
	uint16_t us_adccount,us_index2,us_index3;
	uint16_t us_ack_count;
	uint16_t us_sum1,us_sum2,us_minSum = 0xFFFF;
	XTBUS_RWIDLE;
	delay_us(XTCmdAndSquareUs);	

	Power_SetSampleRange_Seep(XTDriver_Sample_R,ADC_SPEED_HFAST);
	
	UpData[0] = 0;
	XTBUS_WR_0;
	delay_us(500);
	ul_readcount = 0;
	while( ul_readcount <  ReceiveBitLength)
	{
		if((ul_readcount & 0x07) == 0)
		{
			uc_data = 0;
		}
		XTBUS_WR_1;
		delay_us(120);
		us_sum1 = 0;
		us_sum2 = 0;
		for(us_adccount = 0; us_adccount < 8; us_adccount++)
		{
			XT_ADC_Buf[us_adccount] = ADC_GetCurADCFast();
			if(us_adccount < 4)
			{
				us_sum1 += XT_ADC_Buf[us_adccount];
				us_index2 = us_adccount;
			}else{
				us_sum2  += XT_ADC_Buf[us_adccount];
				us_index3 = us_adccount;
			}
		}
		
		us_ack_count = 0;
		
		while(us_adccount < 160 && us_ack_count < 5)
		{
			if(us_sum1 < us_minSum)
			{
				us_minSum = us_sum1;
			}
			if(us_sum2 > (us_minSum + (XT_FreeBack_Noise << 2)))
			{
				us_ack_count++;
			}else{
				us_ack_count = 0;
			}
			us_sum1 -= XT_ADC_Buf[(us_index2-3)&0x07];
			us_sum2 -= XT_ADC_Buf[(us_index3-3)&0x07];
			us_adccount++;
			XT_ADC_Buf[us_adccount & 0x07] = ADC_GetCurADCFast();
			us_index2++;
			us_index3++;
			us_sum1 += XT_ADC_Buf[us_index2&0x07];
			us_sum2 += XT_ADC_Buf[us_index3&0x07];
			
		}
		if(us_ack_count < 5)
		{
			delay_us(600);
			XTBUS_WR_0;
			delay_us(300);
		}else{
			XTBUS_WR_0;
			delay_us(800);
			uc_data |= (0x80 >> (ul_readcount & 0x07));
		}
		UpData[ul_readcount>>3] = uc_data;
		ul_readcount++;
	}
	XTBUS_RWIDLE
	XT_CommEnd();
}

static uint8_t XT_CalCRC(uint8_t data[], uint8_t length)
{
	uint8_t c=0,temp,crc[8] = {0},nextcrc[8] = {0};
	uint8_t i,j,k;
	for(i=0;i<length;i++)
	{
		for(j=0;j<8;j++)
		{
			temp = (data[i] >> (7-j)) & 0x1;
			nextcrc[0] = temp ^ crc[7];
			nextcrc[1] = temp ^ crc[0] ^ crc[7];
			nextcrc[2] = temp ^ crc[1] ^ crc[7];
			nextcrc[3] = crc[2];
			nextcrc[4] = crc[3];
			nextcrc[5] = crc[4];
			nextcrc[6] = crc[5];
			nextcrc[7] = crc[6];
			for(k=0;k<8;k++)
			{
				crc[k] = nextcrc[k];
			}
		}
	}
	for(i=0;i<8;i++)
	{
		c += crc[i]<<i;
	}
	return c;
}


uint8_t XT_Power_Init()
{
	uint8_t errorcode=0;
	
	if(PowerCalibration_set(XTREGISTERVOLTAGE, XTCOMMMEDIUMVOLTAGE))
	{
		errorcode |= 0x1;
	}
	
	if(PowerCalibration_set(XTCOMMHIGHVOLTAGE, XTCOMMMEDIUMVOLTAGE))
	{
		errorcode |= 0x2;
	}
	
	if(PowerCalibration_set(XTCHARGEINSTRUCTIONVOLTAGE, XTCOMMMEDIUMVOLTAGE))
	{
		errorcode |= 0x4;
	}
	
	if(PowerCalibration_set(XTCHARGEVOLTAGE, XTCOMMMEDIUMVOLTAGE))
	{
		errorcode |= 0x8;
	}
	
	Power_SetSampleCurrentRange(Current_Max);
	
	return errorcode;
}

void XT_BUS_CTRL( uint8_t NewState )
{
	PowerCalibration_set(XTCOMMHIGHVOLTAGE, XTCOMMMEDIUMVOLTAGE);
	if(NewState){
		XTBUS_ON;
	}else{
		XTBUS_OFF;
	}
}


//函数名称：写现场值
//函数参数：
//函数功能：UID正确且CRC校验通过时，将编号值、延期值、孔位值写入EEPROM。载波反馈1表示收到指令。编号值长度为2字节，延期值长度为3字节，孔位值长度为2字节。
//函数返回：雷管是否接收成功 0接收失败 / 1接收成功
uint8_t XT_Write_Field(uint8_t *uid, uint8_t uidlen, uint8_t *field)
{
	uint8_t SData[22],RData[1];
	
	SData[0] = XT_CMDA_WRITE_FIELD;
	memcpy(SData+1,uid,uidlen);
	memcpy(SData+1+uidlen,field,7);
	SData[uidlen+8] = XT_CalCRC(SData,uidlen+8);
	XT_SendData(SData,9+uidlen);
	XT_ReceiveData(RData,1);
	
	if(*RData & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：读现场值
//函数参数：
//函数功能：UID正确且CRC校验通过时，读出编号值、延期值、孔位值、状态字节。编号值长度为2字节，延期值长度为3字节，孔位值长度为2字节，状态字节为1字节。反馈完成后会继续反馈一位1作为结束符。
//函数返回：field存储编号值、延期值、孔位值、状态字节  0接收失败 / 1接收成功
uint8_t XT_Read_Field(uint8_t *uid, uint8_t uidlen, uint8_t *field)
{
	uint8_t SData[15];
	
	SData[0] = XT_CMDA_READ_FIELD;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = XT_CalCRC(SData,uidlen+1);
	XT_SendData(SData,uidlen+2);
	XT_ReceiveData(field,66);
	if(*(field+8) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：读管壳码
//函数参数：
//函数功能：UID正确且CRC校验通过时，读出管壳码。管壳码长度为13字节。反馈完成后会继续反馈一位1作为结束符。
//函数返回：管壳码  0接收失败 / 1接收成功
uint8_t XT_Read_Shell(uint8_t *uid, uint8_t uidlen, uint8_t *shell)
{
	uint8_t SData[15];
	
	SData[0] = XT_CMDA_READ_SHELL;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = XT_CalCRC(SData,uidlen+1);
	XT_SendData(SData,uidlen+2);
	//XT_ReceiveInit(106,1);
	
	XT_ReceiveData(shell,106);
	if(*(shell+13) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：读测量参数值
//函数参数：
//函数功能：UID正确且CRC校验通过时，读出CCSC、AMP、R1、Rdson。这4个字段的长度均为1字节。反馈完成后会继续反馈一位1作为结束符。
//函数返回：CCSC、AMP、R1、Rdson   0接收失败 / 1接收成功
uint8_t XT_Read_Param(uint8_t *uid, uint8_t uidlen, uint8_t *param)
{
	uint8_t SData[15];
	
	SData[0] = XT_CMDA_READ_PARAM;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = XT_CalCRC(SData,uidlen+1);
	XT_SendData(SData,uidlen+2);
	//XT_ReceiveInit(34,1);
	XT_ReceiveData(param,34);
	if(*(param+4) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：测量药头电阻
//函数参数：
//函数功能：UID正确且CRC校验通过时，打开药头电阻测量电路开关。
//          等待40个载波后，发出ADC复位信号，再经过1个载波后，
//          发出开始ADC采样信号，随后的8个载波中反馈ADC采样的值。
//           然后再发出ADC复位信号，如上重复三次
//函数返回：ADC采样值
uint8_t XT_Measure_Res(uint8_t *uid, uint8_t uidlen, uint8_t *adcvalue)
{
	uint8_t SData[15],RData[9];
	
	SData[0] = XT_CMDA_MEASURE_RES;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = XT_CalCRC(SData,uidlen+1);
	XT_SendData(SData,uidlen+2);
	
	//XT_ReceiveInit(70,1);
	
	XT_ReceiveData(RData,70);
	
	*adcvalue = (RData[5]<<2) + (RData[6]>>6);
	*(adcvalue+1) = (RData[6]<<4) + (RData[7]>>4);
	*(adcvalue+2) = (RData[7]<<6) + (RData[8]>>2);
	
	return 0;
}


//函数名称：测量储能电容
//函数参数：
//函数功能：UID正确且CRC校验通过时，将电容电压比较器档位设定为LEVEL指定的档位，
//          并打开恒流源开关，关闭放电开关进行充电。充电完成时发出反馈，并关闭恒流源开关，打开放电开关。
//函数返回：充电时间
uint8_t XT_Measure_Cap(uint8_t *uid, uint8_t uidlen, uint8_t level, uint32_t *chargetime)
{
	uint8_t SData[16];
	
	SData[0] = XT_CMDA_MEASURE_CAP;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = level;
	SData[uidlen+2] = XT_CalCRC(SData,uidlen+2);
	XT_SendData(SData,uidlen+3);
	
	return XT_Get_Ack(*chargetime, XTConfirmAckCount, chargetime);
}


//函数名称：单发充电
//函数参数：
//函数功能：UID正确且CRC校验通过时，将电容电压比较器档位设定为LEVEL指定的档位，
//         将当前充满电标志位复位，并打开充电开关，关闭放电开关进行充电。充电完成时发出反馈，并将曾充满电标志位、当前充满电标志位置位。
//		    LEVEL：0x11-1V、0x22-4V、0x33-6V、0x44-10V、0x55-12V、0x66-14V、0x77-18V、0x88-22V、0x99-26V
//函数返回：是否充满
uint8_t XT_Charge_One(uint8_t *uid,uint8_t uidlen, uint8_t level,uint16_t busvoltage, uint8_t isgetack)
{
	uint8_t SData[16];
	uint32_t chargetime=0;
	uint8_t chargeresult =1;
	
	SData[0] = XT_CMDA_CHARGE;
	memcpy(SData+1,uid,uidlen);
	SData[uidlen+1] = level;
	SData[uidlen+2] = XT_CalCRC(SData,uidlen+2);
	XT_SendData(SData,uidlen+3);
	
	PowerCalibration_set(busvoltage,XTCOMMMEDIUMVOLTAGE);	//修改总线电压
	
	if(!isgetack || level == 0x00)
	{
		return 0;
	}
	
	//XT_GetAckInit();

	chargeresult = XT_Get_Ack(XTSingleCollectAckTimerOverflowCnt, XTConfirmAckCount, &chargetime);
	
	return chargeresult;
}


/******************************************
*
* B类指令（广播指令）
*
*******************************************/


//函数名称：清除已读状态
//函数参数：
//函数功能：UID已读标志位复位。
//函数返回：
void XT_Clear_Read(void)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_CLEAR_READH;
	SData[1] = XT_CMDB_CLEAR_READL;
	XT_SendData(SData,2);
}


//函数名称：起爆
//函数参数：
//函数功能：若起爆密码验证通过标志位、延期标定完成标志位、曾充满电标志位均为1，
//			则设置电容电压比较器档位为最低档位，并进入延期状态。延期倒计时归零时，进行起爆前反馈，然后逐位翻转起爆控制信号。之后进行起爆后反馈。若上述标志位不均为1，则对芯片进行复位，效果同软件复位指令相同
//函数返回：
void XT_Fire()
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_FIREH;
	SData[1] = XT_CMDB_FIREL;
	XT_SendData(SData,2);
}


uint8_t XT_FireandCheck(uint8_t *delay)			//delay 3字节  最大的延期时间
{
	uint8_t SData[2];
	uint8_t fireresult = 1;
	uint32_t timeout=0;
	uint32_t delay_max=0;
	
	delay_max = (*delay<<16) + (*(delay+1)<<8) + (*(delay+2));
	
	timeout = delay_max*10+5000;
	
	SData[0] = XT_CMDB_FIREH;
	SData[1] = XT_CMDB_FIREL;
	XT_SendData(SData,2);
	
	fireresult = XT_Get_Ack(timeout, 2, &delay_max);
	return fireresult;
}

uint8_t XT_MeasureFire(uint32_t *delay)	
{
	uint8_t SData[2];
	uint8_t fireresult = 1;
	uint32_t timeout=0;
	uint32_t delay_max=0;
	
	delay_max = *delay+2;
	
	timeout = delay_max*10+5000;
	
	SData[0] = XT_CMDB_FIREH;
	SData[1] = XT_CMDB_FIREL;
	XT_SendData(SData,2);
	
	fireresult = XT_Get_Ack(timeout, 2, delay);
	return fireresult;
}

//函数名称：初始化
//函数参数：
//函数功能：初始化寄存器。
//函数返回：
void XT_Init(uint8_t regdata)
{
	uint8_t SData[3];
	
	SData[0] = XT_CMDB_INITH;
	SData[1] = XT_CMDB_INITL;
	SData[2] = regdata;
	XT_SendData(SData,3);
}


//函数名称：软件复位
//函数参数：
//函数功能：对芯片进行复位，2,000时钟周期后可以继续接收指令。
//函数返回：
void XT_Reset()
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_RESETH;
	SData[1] = XT_CMDB_RESETL;
	XT_SendData(SData,2);
}


//函数名称：扫描
//函数参数：
//函数功能：读出UID、编号值、延期值、孔位值、状态字节。使用防冲突机制，当重复发送该指令时，所有在线的雷管会按照UID顺序从大到小依次反馈。
//			指令码长度为2字节，UID长度为7~13字节，编号值长度为2字节，延期值长度为3字节，孔位值长度为2字节，状态字节长度为1字节
//函数返回：UID、编号值、延期值、孔位值、状态字节
uint8_t XT_Read_Uid(uint8_t *uid, uint8_t uidlen)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_READ_UIDH;
	SData[1] = XT_CMDB_READ_UIDL;
	XT_SendData(SData,2);
	//XT_ReceiveData(uid,((uint32_t)uidlen<<3)+66);
	XT_ScanUID(uid,((uint32_t)uidlen<<3)+66);
	
	if(*(uid+uidlen+8) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：快速延期标定
//函数参数：
//函数功能：翻转信号接收模块的识别极性，起爆器会以正常通信相反的极性发送该指令，以控制极性识别错误的雷管恢复正确极性。
//函数返回：
void XT_Trim_Fast(void)
{
	XT_Trim_Faset_Cycle(1000,500);
}
void XT_Trim_Faset_Cycle(uint16_t cycle,uint16_t duty)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_TRIM_FASTH;
	SData[1] = XT_CMDB_TRIM_FASTL;
	XT_SendData(SData,2);
	
	XT_SendTrimSquare(cycle,duty,1026);
}

//函数名称：完整延期标定
//函数参数：
//函数功能：标定第1个方波下降沿至第(DELAY+1)个方波下降沿所对应的时钟周期数，并写入TIMER模块的计数器中。标定完成标志位置位。
//函数返回：
void XT_Trim_Complete(uint32_t delay_max)
{
	XT_Trim_Complete_Cycle(1000,500,delay_max);
}
void XT_Trim_Complete_Cycle(uint16_t cycle,uint16_t duty, uint32_t delay_max)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_TRIM_COMPLETEH;
	SData[1] = XT_CMDB_TRIM_COMPLETEL;
	XT_SendData(SData,2);
	
	XT_SendTrimSquare(cycle,duty,delay_max);
}


//函数名称：在线检测
//函数参数：
//函数功能：指令后发送数量等于最大编号值的方波，每发雷管对方波进行计数，在计数到自己的编号值所对应的方波时，反馈1
//函数返回：
uint8_t XT_Check_Online(uint16_t index_max, uint8_t *online)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_CHECK_ONLINEH;
	SData[1] = XT_CMDB_CHECK_ONLINEL;
	XT_SendData(SData,2);
	XT_ReceiveData(online, index_max+8);
	
	return 0;
}


//函数名称：验证起爆密码
//函数参数：
//函数功能：验证起爆密码。验证正确时反馈并将起爆密码验证通过标志位置位，否则不反馈
//函数返回：
uint8_t XT_Check_Bmid(uint8_t *bmid, uint8_t bmidlen)
{
	uint8_t SData[10],RData[1]={0};
	
	SData[0] = XT_CMDB_CHECK_BMIDH;
	SData[1] = XT_CMDB_CHECK_BMIDL;
	
	memcpy(SData+2,bmid,bmidlen);
	XT_SendData(SData,2+bmidlen);
	
	XT_ReceiveData(RData, 1);
	
	if(*RData & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：获取全部验证状态
//函数参数：
//函数功能：若曾充满电标志位、延期标定完成标志位、起爆密码验证通过标志位均为1则不反馈，否则反馈
//函数返回：
uint8_t XT_Check_Fire_All(void)
{
	uint8_t SData[2],RData[1]={0};
	
	SData[0] = XT_CMDB_CHECK_FIRE_ALLH;
	SData[1] = XT_CMDB_CHECK_FIRE_ALLL;
	XT_SendData(SData,2);
	
	XT_ReceiveData(RData, 1);
	
	if(*RData & 0x80)
		return 1;
	else
		return 0;
}


//函数名称：逐发获取验证状态
//函数参数：
//函数功能：指令后发送数量等于最大编号值的方波。
//          每发雷管对方波进行计数，在计数到自己的编号值所对应的方波时，
//          若当前充满电标志位、延期标定完成标志位、起爆密码验证通过标志位均为1则反馈，否则不反馈
//函数返回：
uint8_t XT_Check_Fire_Each(uint32_t index_max, uint8_t *check)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDB_CHECK_FIRE_EACHH;
	SData[1] = XT_CMDB_CHECK_FIRE_EACHL;
	XT_SendData(SData,2);	
	XT_ReceiveData(check, index_max);
	
	return 0;
}


//函数名称：设置反馈电流大小
//函数参数：
//函数功能：CRC校验通过时，将SETTING常驻寄存器的[3:2]位改为LEVEL所指定的档位。不改变EEPROM。若要改变EEPROM，应使用写配置区指令。
//函数返回：
void XT_Set_Current(uint8_t level)
{
	uint8_t SData[3];
	
	SData[0] = XT_CMDB_SET_CURRENTH;
	SData[1] = level;
	SData[2] = XT_CalCRC(SData,2);
	XT_SendData(SData,3);
}


//函数名称：广播充电
//函数参数：
//函数功能：CRC校验通过时，将电容电压比较器档位设定为LEVEL指定的档位，将当前充满电标志位复位，
//          并打开充电开关，关闭放电开关进行充电。充电完成时将曾充满电标志位、当前充满电标志位置位。
//			LEVEL：0x11-1V、0x22-4V、0x33-6V、0x44-10V、0x55-12V、0x66-14V、0x77-18V、0x88-22V、0x99-26V
//函数返回：
void XT_Charge_All(uint8_t level)
{
	uint8_t SData[3];
	
	SData[0] = XT_CMDB_CHARGE;
	SData[1] = level;
	SData[2] = XT_CalCRC(SData,2);
	XT_SendData(SData,3);
}

//函数名称：检查配置区
//函数参数：
//函数功能：CRC校验通过时，若配置区中的UID/起爆密码长度及版本号两个字段同指令中的值相同则不反馈，否则反馈
//函数返回：
uint8_t XT_Check_Config(uint8_t *config)
{
	uint8_t SData[4],RData[1]={0};
	
	SData[0] = XT_CMDB_CHECK_CONFIG;
	SData[1] = *(config);
	SData[2] = *(config+1);
	SData[3] = XT_CalCRC(SData,3);
	XT_SendData(SData,4);
	
	XT_ReceiveData(RData, 1);
	
	if(*RData & 0x80)
		return 1;
	else
		return 0;
}


/******************************************
*
* C类指令（测试指令）
*
*******************************************/

//函数名称：写UID
//函数参数：
//函数功能：将UID写入EEPROM。写入完成后有反馈
//函数返回：
uint8_t XT_Write_Uid(uint8_t *uid, uint8_t uidlen)
{
	uint8_t SData[14];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_UID;
	memcpy(SData+1,uid,uidlen);
	XT_SendData(SData,uidlen+1);
		
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：写起爆密码
//函数参数：
//函数功能：将起爆密码写入EEPROM。写入完成后有反馈
//函数返回：
uint8_t XT_Write_Bmid(uint8_t *bmid, uint8_t bmidlen)
{
	uint8_t SData[9];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_BMID;
	memcpy(SData+1,bmid,bmidlen);
	XT_SendData(SData,bmidlen+1);
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：写管壳码
//函数参数：
//函数功能：将管壳码写入EEPROM。写入完成后有反馈
//函数返回：
uint8_t XT_Write_Shell(uint8_t *shell)
{
	uint8_t SData[14];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_SHELL;
	memcpy(SData+1,shell,13);
	
	XT_SendData(SData,14);
	
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：写现场值_C
//函数参数：
//函数功能：将编号值、延期值、孔位值写入EEPROM。写入完成后有反馈。编号值长度为2字节，延期值长度为3字节，孔位值长度为2字节
//函数返回：
uint8_t XT_Write_Field_All(uint8_t *field)
{
	uint8_t SData[8];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_FIELD;

	memcpy(SData+1,field,13);
	
	XT_SendData(SData,8);
	
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：写配置区
//函数参数：
//函数功能：将LEN、SETTING、REV写入EEPROM及相应的常驻寄存器。写入完成后有反馈
//函数返回：
uint8_t XT_Write_Config(uint8_t *config)
{
	uint8_t SData[4];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_CONFIG;
	memcpy(SData+1,config,3);
	XT_SendData(SData,4);
	
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：写测量参数值
//函数参数：
//函数功能：将CCSC、AMP、R1、Rdson写入EEPROM。写入完成后有反馈
//函数返回：
uint8_t XT_Write_Param(uint8_t *param)
{
	uint8_t i,SData[5];
	uint32_t writetime=0;
	
	SData[0] = XT_CMDC_WRITE_PARAM;
	
	for(i=0;i<4;i++)
	{
		SData[i+1] = *(param+i);
	}
	memcpy(SData+1,param,4);
	
	XT_SendData(SData,5);	
	
	return XT_Get_Ack(XTWriteBitTimerOverflowCnt, XTConfirmAckCount, &writetime);
}


//函数名称：测量储能电容C
//函数参数：
//函数功能：UID正确且CRC校验通过时，将电容电压比较器档位设定为LEVEL指定的档位，并打开恒流源开关，关闭放电开关进行充电。充电完成时发出反馈，并关闭恒流源开关，打开放电开关。
//函数返回：充电时间
uint8_t XT_Measure_Cap_All(uint8_t level, uint32_t *chargetime)
{
	uint8_t SData[2];
	
	SData[0] = XT_CMDC_MEASURE_CAP;
	SData[1] = level;
	XT_SendData(SData,2);
	return XT_Get_Ack(*chargetime, XTConfirmAckCount, chargetime);
}


//函数名称：锁定
//函数参数：
//函数功能：向EEPROM中LOCK字段写入0x8B，锁定标志位置位。写入完成后有反馈。锁定后C类指令不再识别，仅可写入现场值
//函数返回：
void XT_Lock(void)
{
	uint8_t SData[1];
	
	SData[0] = XT_CMDC_LOCK;
	XT_SendData(SData,1);
	delay_us(700);
	XTBUS_W_0;
	delay_us(500);
	XTBUS_W_1;
	delay_os_ms(50);
}


//函数名称：读测量参数值_C
//函数参数：
//函数功能：读出CCSC、AMP、R1、Rdson
//函数返回：
uint8_t XT_Read_Param_All(uint8_t *param)
{
	uint8_t SData[1];
	
	SData[0] = XT_CMDC_READ_PARAM;
	XT_SendData(SData,1);
	XT_ReceiveData(param, 34);
	
	if(*(param+4) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：读配置区
//函数参数：
//函数功能：读出CKCFG、LEN、SETTING、REV
//函数返回：
uint8_t XT_Read_Config(uint8_t *config)
{
	uint8_t SData[1];
	
	SData[0] = XT_CMDC_READ_CONFIG;
	XT_SendData(SData,1);
	XT_ReceiveData(config, 34);
	
	if(*(config+4) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：读管壳码_C
//函数参数：
//函数功能：读出管壳码。管壳码长度为13字节。反馈完成后会继续反馈一位1作为结束符
//函数返回：
uint8_t XT_Read_Shell_All(uint8_t *shell)
{
	uint8_t SData[1];
	
	SData[0] = XT_CMDC_READ_SHELL;
	XT_SendData(SData,1);
	XT_ReceiveData(shell, 106);
	
	if(*(shell+13) & 0x80)
		return 0;
	else
		return 1;
}


//函数名称：测量药头电阻_C
//函数参数：
//函数功能：收到指令时打开药头电阻测量电路开关。等待40个载波后，发出ADC复位信号，再经过1个载波后，发出开始ADC采样信号，随后的8个载波中反馈ADC采样的值。然后再发出ADC复位信号，如上重复三次
//函数返回：
uint8_t XT_Measure_Res_All(uint8_t *adcvalue)
{
	uint8_t SData[1],RData[9]={0};
	
	SData[0] = XT_CMDC_MEASURE_RES;
	XT_SendData(SData,1);
	XT_ReceiveData(RData, 70);
	
	*adcvalue = (RData[5]<<2) + (RData[6]>>6);
	*(adcvalue+1) = (RData[6]<<4) + (RData[7]>>4);
	*(adcvalue+2) = (RData[7]<<6) + (RData[8]>>2);
	
	return 0;
}


uint8_t XT_Get_UID_R(uint8_t *uid, uint8_t uidlen)                    			//算桥丝电阻
{
	uint8_t adcvalue[3];
	uint16_t qsadc=0,count=1;
	
	XT_Measure_Res(uid,uidlen,adcvalue);
	
	qsadc = adcvalue[1];
	if(adcvalue[0]>0x00 && adcvalue[0]<0xF0)
	{
		qsadc += adcvalue[0];
		count++;
	}
	if(adcvalue[2]>0x00 && adcvalue[2]<0xF0)
	{
		qsadc += adcvalue[2];
		count++;
	}
	qsadc = qsadc / count;
	return (qsadc & 0xFF);
//	if(qsadc < 0xF0)
//		return 0;
//	else
//		return 1;
}


uint8_t XT_Get_R()                    			//算桥丝电阻
{
	uint8_t adcvalue[3];
	uint16_t qsadc=0,count=1;
	
	XT_Measure_Res_All(adcvalue);
	
	qsadc = adcvalue[1];
	if(adcvalue[0]>0x00 && adcvalue[0]<0xF0)
	{
		qsadc += adcvalue[0];
		count++;
	}
	if(adcvalue[2]>0x00 && adcvalue[2]<0xF0)
	{
		qsadc += adcvalue[2];
		count++;
	}
	qsadc = qsadc / count;
	return (qsadc & 0xFF);
//	if(qsadc < 0xF0)
//		return 0;
//	else
//		return 1;
}

uint8_t XT_Get_UID_C(uint8_t *uid, uint8_t uidlen, uint8_t level, uint32_t time_out,float *CapacitanceValue)               //算储能电容
{
	uint8_t exeresult=1;
	uint32_t chargetime=time_out;
	uint8_t param[5]={0};
	float CSCC=0;
	
	exeresult = XT_Measure_Cap(uid, uidlen, level, &chargetime);
	if(exeresult)
	{
		return 1;
	}
	
	__disable_irq();
	delay_ms(10);
	__enable_irq();
	
	exeresult = XT_Read_Param(uid,uidlen, param);
	if(exeresult)
	{
		return 1;
	}
	
	CSCC = 0.390625f * param[0] + 120;
	
	if(level == 0x11)
	{
		*CapacitanceValue = CSCC * chargetime  /10000.0f;
	}
	else if(level == 0x22)
	{
		*CapacitanceValue = CSCC * chargetime / 40000.0f;
	}
	else if(level == 0x33)
	{
		*CapacitanceValue = CSCC * chargetime / 100000.0f;
	}
	
	return 0;
}

uint8_t XT_Get_C(uint8_t level,uint32_t time_out ,float *CapacitanceValue)               //算储能电容
{
	uint8_t exeresult=1;
	uint32_t chargetime=time_out;
	uint8_t param[5]={0};
	float CSCC=0;
	
	exeresult = XT_Measure_Cap_All(level, &chargetime);
	if(exeresult)
	{
		return 1;
	}
	
	delay_os_ms(20);
	
	exeresult = XT_Read_Param_All(param);
	if(exeresult)
	{
		return 1;
	}
	
	CSCC = 0.390625f * param[0] + 120;
	
	if(level == 0x11)
	{
		*CapacitanceValue = CSCC * chargetime  /10000.0f;
	}
	else if(level == 0x22)
	{
		*CapacitanceValue = CSCC * chargetime / 40000.0f;
	}
	else if(level == 0x33)
	{
		*CapacitanceValue = CSCC * chargetime / 100000.0f;
	}
	
	return 0;
}

