#include <string.h>
#include "delay.h"
#include "DebugDataDefine.h"
#include "CommandsDefine.h"
#include "AnalogChannelCtrl_Dictionary.h"
#include "ProjectConfig.h"
#include "Probe_MSO7000X_2d5g.h"
#include "AnalogChannelCtrl_2d5g_base.h"
#include "Helper.h"
#include "usart.h"
//////////////////////////////////////////////////////////////////////////////
// 			2203/5/X GHz_ljw 合并版,业务逻辑下沉  模拟通道控制
//////////////////////////////////////////////////////////////////////////////

u8 Get4094CtrlWord(struct Paras595 params, u32* ctrlWord)
{
	u32 _ctrlWord = 0;
	u8 _isHigh = 0;
	 
	// 带宽
	if(params.bandwidth == 0xFFFF)//FULL
	{
		_ctrlWord|=0;
	}
	else if(params.bandwidth == 500) //500MHz
	{
		_ctrlWord|=bwCtrlBit0 | bwCtrlBit2;
	}
	else if(params.bandwidth == 200) //200MHz
	{
		_ctrlWord|=bwCtrlBit0;
	}
	else if(params.bandwidth == 20) //20MHz
	{
		_ctrlWord|=bwCtrlBit0 | bwCtrlBit1;
	}
	else
	{
		return 0; //error
	}
	
	// 阻抗
	if(params.coupling == 0 && params.high_low == 1)//DC50
	{
		_ctrlWord|=coupleCtrl_4094[0];
	}
	else if(params.coupling == 0 && params.high_low == 0)//DC1M
	{
		_ctrlWord|=coupleCtrl_4094[1];
		_isHigh = 1;
	}
	else if(params.coupling == 1 && params.high_low == 0)//AC1M
	{
		_ctrlWord|=coupleCtrl_4094[2];
		_isHigh  = 1;
	}
	else
	{
		return 0; //error
	}
	
	//衰减
	if(_isHigh)
	{
		if(params.att == 0) //直通
		{
			_ctrlWord|= lzDelayBit | hzDelayBit ;
		}
		else if(params.att == 12) //12dB
		{
			_ctrlWord|=lzDelayBit;
		}
		else if(params.att==26)	//26dB
		{
			_ctrlWord|=hzDelayBit;
		}
		else if(params.att==38)	//38dB
		{
			_ctrlWord|=0;
		}
		else
		{
			return 0; //error
		}
	}
	else
	{
		if(params.att==0) //直通
		{
			_ctrlWord|=0;
		}
		else if(params.att==6)//6dB
		{
			_ctrlWord|=lzDelayBit;
		}
		else if(params.att==12)//12dB
		{
			_ctrlWord|=hzDelayBit;
		}
		else if(params.att==20)//20dB
		{
			_ctrlWord|=lzDelayBit|hzDelayBit;
		}
		else
		{
			return 0; //error
		}
	}
	
	
	ctrlWord[0]=_ctrlWord;
	return 1;
}
u8 AnalogChannelSet_Check_Len(u16 dataLen)
{
	if(dataLen<PACKAGE_CHANNELSET_DATA_BYTES+PACKAGE_CHANNELSET_INDEX_BYTES+PACKAGE_CHANNELSET_CHECK_AREA_BYTES+PACKAGE_CHANNELSET_FRAMEID_BYTES)
	{
		return 0;
	}
	if((dataLen-PACKAGE_CHANNELSET_INDEX_BYTES-PACKAGE_CHANNELSET_CHECK_AREA_BYTES-PACKAGE_CHANNELSET_FRAMEID_BYTES)%PACKAGE_CHANNELSET_DATA_BYTES!=0)
	{
		return 0;
	}
	return 1;
}
/*
u32 GetDACConfigWord(struct ParasDAC params,u8* dac_index)
{
	u32 ConfigWord;
	u8 high = offset_hz;
	u8 low = offset_lz;
	if(params.isBias==1)
	{
		 high = move_hz;
	   low = move_lz;
	}
	ConfigWord = 0x10300000;
	u8 dataType = params.high_low == 0 ? high : low;
	dac_index[0] = dacPortInfoTable[params.channelId-1][dataType][0] - 5;
	u8 dac_indexEx = dacPortInfoTable[params.channelId-1][dataType][2];
	u8 port = dacPortInfoTable[params.channelId-1][dataType][1];
	ConfigWord |= dac_indexEx << 24;
	ConfigWord |= port << 16;
	ConfigWord |= params.data;
	if(dac_index[0]==1){
		dac_index=dac_index; //test point
	}
	
	return ConfigWord;
}*/
void AnalogChannel_GetAll4094Word(u8 *pData,u8 channelId){
	//控制HC595/CD4094
	struct Paras595 params595;
	params595.gain = pData[OFFSET_IN_DATA_GAIN_START] ; 	//放大
	params595.att =  pData[OFFSET_IN_DATA_ATT_START] ;		//衰减
	params595.coupling = pData[OFFSET_IN_DATA_COUPLING_START];
	params595.high_low = pData[OFFSET_IN_DATA_HIGH_LOW_START];
	params595.bandwidth = pData[OFFSET_IN_DATA_BANDWIDTH_START] + (pData[OFFSET_IN_DATA_BANDWIDTH_START + 1]<<8);

	u32 ctrlWord595 = 0;
	u8 result = Get4094CtrlWord(params595, &ctrlWord595);
	if(result==0){ //参数错误
		return;
	}

	Low32HC595 |= (ctrlWord595 << 8*(channelId-1));
}

void AnalogChannel_SetAll4094(u8 *pData){
	u8 channelId = pData[1];
	Low32HC595 = Low32HC595 & ((u32)1<<31);
	u8 gotChData = 0;

	for(int i=0; i<MAX_CHANNEL_NUM; i++)
	{
		if(((channelId>>i) & 0x01) == 1){
			AnalogChannel_GetAll4094Word(pData + PACKAGE_CHANNELSET_INDEX_BYTES + gotChData * PACKAGE_CHANNELSET_DATA_BYTES, i+1);
			gotChData++;
		}
	}		
	CD_4094(Low32HC595, 4);
	delay_ms(2);
}

/// @brief 通过595给DSA2配置spi使能
/// @param pData 
/// @param channelId 
/// @param csEnable 
void AnalogChannel_GetAll4094Word_DSA2_CS(u8 *pData,u8 channelId, u8 csEnable){
	//控制HC595/CD4094
	struct Paras595 params595;
	params595.gain = pData[OFFSET_IN_DATA_GAIN_START] ; 	//放大
	params595.att =  pData[OFFSET_IN_DATA_ATT_START] ;		//衰减
	params595.coupling = pData[OFFSET_IN_DATA_COUPLING_START];
	params595.high_low = pData[OFFSET_IN_DATA_HIGH_LOW_START];
	params595.bandwidth = pData[OFFSET_IN_DATA_BANDWIDTH_START] + (pData[OFFSET_IN_DATA_BANDWIDTH_START + 1]<<8);

	u32 ctrlWord595 = 0;
	u8 result = Get4094CtrlWord(params595, &ctrlWord595);
	if(result==0){ //参数错误
		return;
	}
	ctrlWord595 |= (csEnable << 7);
	Low32HC595 |= (ctrlWord595 << 8*(channelId-1));
}

/// @brief  通过595给DSA2配置spi使能
/// @param pData 
/// @param CHx_DSA_CSn 
void AnalogChannel_SetAll4094_DSA2_CS(u8 *pData, u8 CHx_DSA_CSn){
	u8 channelId = pData[1];
	Low32HC595 = Low32HC595 & ((u32)1<<31);
	u8 gotChData = 0;

	for(int i=0; i<MAX_CHANNEL_NUM; i++)
	{
		if(((channelId>>i) & 0x01) == 1){
			u8 csEnable = (CHx_DSA_CSn == i + 1) ? 1 : 0;
			AnalogChannel_GetAll4094Word_DSA2_CS(pData + PACKAGE_CHANNELSET_INDEX_BYTES + gotChData * PACKAGE_CHANNELSET_DATA_BYTES, i+1, csEnable);
			gotChData++;
		}
	}		
	CD_4094(Low32HC595, 4);
	delay_us(2);
}

/// @brief 开关通道
/// @param channelId 
/// @param openFlag 
void PowerAnaChnl(u8 channelId, u8 openFlag)
{
	GPIOPin powerGpioPin;  //控制管脚
    switch(channelId){
        case CH1_DSA_CS:
        {			
            powerGpioPin.gpioType = GPIOD;			 
            powerGpioPin.pinIndex = GPIO_Pin_10;
            break;
        }
        case CH2_DSA_CS:
        {		
            powerGpioPin.gpioType = GPIOE;			 
            powerGpioPin.pinIndex = GPIO_Pin_10;	
            break;
        }
        case CH3_DSA_CS:
        {				 
            powerGpioPin.gpioType = GPIOC;			 
            powerGpioPin.pinIndex = GPIO_Pin_1;	
            break; 
        }
		case CH4_DSA_CS:
        {				 
            powerGpioPin.gpioType = GPIOE;			 
            powerGpioPin.pinIndex = GPIO_Pin_3;	
            break; 
        }
        default:
            return;
    }
	if(openFlag == 1){
		GPIO_ResetBits(powerGpioPin.gpioType, powerGpioPin.pinIndex);
	}
	else{
		GPIO_SetBits(powerGpioPin.gpioType, powerGpioPin.pinIndex);
	}
}

/// @brief 设置通道是否过FG
/// @param channelId 
/// @param openFlag 0-不过FG，1-过FG
void SetAnaChnlFG(u8 channelId, u8 openFlag)
{
	GPIOPin switchGpioPin;  //控制管脚
    switch(channelId){
        case CH1_DSA_CS:
        {			
			switchGpioPin.gpioType = GPIOE;			 
            switchGpioPin.pinIndex = GPIO_Pin_1;				 
            break;
        }
        case CH2_DSA_CS:
        {		
			switchGpioPin.gpioType = GPIOE;			 
            switchGpioPin.pinIndex = GPIO_Pin_0;	 
            break;
        }
        case CH3_DSA_CS:
        {				 
			switchGpioPin.gpioType = GPIOB;			 
            switchGpioPin.pinIndex = GPIO_Pin_9;
            break; 
        }
		case CH4_DSA_CS:
        {				 
			switchGpioPin.gpioType = GPIOB;			 
            switchGpioPin.pinIndex = GPIO_Pin_8;
            break; 
        }
        default:
            return;
    }
	if(openFlag == 1){
		GPIO_SetBits(switchGpioPin.gpioType, switchGpioPin.pinIndex);
	}
	else{
		GPIO_ResetBits(switchGpioPin.gpioType, switchGpioPin.pinIndex);
	}
}

void AnalogChannelSet(u8 *pData,u8 channelId, u8* pData595)
{
	u8 fgFlag = pData[OFFSET_IN_DATA_FG_START];
	u8 gain1 = pData[OFFSET_IN_DATA_GAIN_START] ; 
	u8 gain2 = pData[OFFSET_IN_DATA_GAIN_START + 1] ; 
	u8 high_low = pData[OFFSET_IN_DATA_HIGH_LOW_START];
	u16 bias = pData[OFFSET_IN_DATA_BIAS_START] + (pData[OFFSET_IN_DATA_BIAS_START + 1]<<8); 	//hardware offset, software bias
	u16 move = pData[OFFSET_IN_DATA_MOVE_START] + (pData[OFFSET_IN_DATA_MOVE_START + 1]<<8);	//hardware move, software offset

	u32 ConfigWord;
	u8 dac_index;

	//FG控制
	SetAnaChnlFG(channelId, fgFlag);

	//控制字
	struct ParasDAC paramsDAC;
	paramsDAC.high_low = high_low;
	paramsDAC.channelId = channelId;

	//bias
	paramsDAC.data = bias;
	paramsDAC.isBias = 1; //bias
	ConfigWord = GetDACConfigWord(paramsDAC,&dac_index);
	DAC_AD5675(ConfigWord,dac_index);

	//move
	paramsDAC.data = move;
	paramsDAC.isBias = 0; //move
	ConfigWord = GetDACConfigWord(paramsDAC,&dac_index);
	DAC_AD5675(ConfigWord,dac_index);

	//ref
	paramsDAC.data = 32000;
	paramsDAC.isBias = 2; //ref
	ConfigWord = GetDACConfigWord(paramsDAC,&dac_index);
	DAC_AD5675(ConfigWord,dac_index);

	//dsa1 -> gain1 
	DSA_PE43711(LMH43711_ADDR_GAIN, gain1, channelId); //LMH6401_ADDR_GAIN

	/*dsa2 -> gain2 */
	//片选开始,拉低
	AnalogChannel_SetAll4094_DSA2_CS(pData595, 0);//默认片选拉低
	//发送数据和时钟
	DSA2_PE43711(LMH43711_ADDR_GAIN, gain2);
	//片选结束,拉高低
	AnalogChannel_SetAll4094_DSA2_CS(pData595, channelId);
	AnalogChannel_SetAll4094_DSA2_CS(pData595, 0);
}

void CMD0x22_Request_AnalogChannelSet_process(u8 *pData,u16 dataLen,u8 bIsContentBitInverted_Recv,u8 bIsContentBitInverted_SendBack)
{
	if(IsChannelSetting!=0)
	{
		return;
	}
	IsChannelSetting = 1;
#ifdef RUNNING_WHERE_AT_BOOT	
	Command_SendbackErrorMessage(Error0x02_CannotRunAtBoot,1);
#else
	memcpy(G_DebugData_AnalogChannel_LastRecvData,pData,dataLen);
	if(AnalogChannelSet_Check_Len(dataLen)==0)
	{ 
		IsChannelSetting=0;
		Command_SendbackErrorMessage(Error0x05_CMD_ParaLentghError,1);
		return;
	}
	//Calc
	u8 CRCStartIndex = dataLen - PACKAGE_CHANNELSET_FRAMEID_BYTES - PACKAGE_CHANNELSET_CHECK_AREA_BYTES;
	u8 SUMStartIndex = CRCStartIndex + PACKAGE_CHANNELSET_CRC32_BYTES;
	//u8 frameId[PACKAGE_CHANNELSET_FRAMEID_BYTES] ;
	u32 getCRC32 = pData[CRCStartIndex] + (pData[CRCStartIndex+1]<<8) + (pData[CRCStartIndex+2]<<16)+ (pData[CRCStartIndex+3]<<24);
	u16 getSUM16 =  pData[SUMStartIndex] + (pData[SUMStartIndex+1]<<8) ;
	
	u32 calcCRC32 = Helper_CRC_CalcBlockCRC8(pData,CRCStartIndex);
	u16 calcSUM16 = Helper_Sum16(pData,CRCStartIndex);
	
	if(getCRC32!=calcCRC32 || getSUM16!=calcSUM16)
	{
		IsChannelSetting=0;		
		Command_SendbackErrorMessage(Error0xFF_General,1);
		return;
	}
	//Calc End

	u8 gotChData = 0;
	//pData[0]:表示晶振开关；
	u8 isOpenCrystal = pData[0] & 0x01;
	//pData[1]，bit0-bit3:表示通道读热码；
	u8 channelIds = pData[1] & 0x0f;

	AnalogChannel_SetAll4094(pData);
	for(int i=0; i<MAX_CHANNEL_NUM; i++)
	{
		u8 openFlag = (channelIds>>i) & 0x01;
		PowerAnaChnl(i + 1, openFlag);
		if(openFlag == 1)
		{
			AnalogChannelSet(pData + PACKAGE_CHANNELSET_INDEX_BYTES + gotChData * PACKAGE_CHANNELSET_DATA_BYTES,i+1, pData);
			gotChData++;
		}
	}	

	if(isOpenCrystal == 0){
		//高阻信号
		GPIO_SetBits(GPIOD, GPIO_Pin_11);
	}
	else{
		//晶振信号
		GPIO_ResetBits(GPIOD, GPIO_Pin_11);
	}
	
	//Call back
	u8 dataBytes=PACKAGE_CHANNELSET_FRAMEID_BYTES;

	for(u8 i=0;i<PACKAGE_CHANNELSET_FRAMEID_BYTES;i++)
	{
		USART_WR_BUF[i] =  pData[dataLen-PACKAGE_CHANNELSET_FRAMEID_BYTES+i];
	}
	 
	USART6_Send(CMD0x22_Request_AnalogChannelSet,dataBytes,bIsContentBitInverted_SendBack);	
	//end
	IsChannelSetting = 0;
#endif	
}

