#include "adc_func.h"
#include "adc_drv.h"
#include "adc_reg.h"
#include "sys.h"

#define _reg_write(reg, val)    					((reg) = (val))
#define _reg_read(reg)          					((reg))
#define _bit_set(value, bit)    					((value) |=  (bit))
#define _bit_clr(value, bit)    					((value) &= ~(bit))

#define _reg_modify(reg, clearmask, setmask)  _reg_write((reg), (((_reg_read(reg)) & (clearmask)) | (setmask)))

static void ADC_SetStructure(ADC_InitTypeDef *adc)
{
	adc->align       = ADC_RIGHT_ALIGN;
	adc->clk_div     = ADC_CLK_DIV_4;
	adc->conv        = ADC_CONTINUOUS_CONV_MODE;
	adc->overrun     = ADC_OVERRUN_MODE_LAST;
	adc->resolution  = ADC_RESOLUTION_12BIT;
	adc->smp_time    = 0x20;
	adc->stab_time   = 0x20;
	adc->vref        = ADC_INTERNAL_VREF;
	adc->int_kind    = 0;
}


/*******************************************************************************
* Function Name  : ADC_Init
* Description    : ADC initialize
* Input          :  - cfgr1  : ADC configuration register 1
*                   - cfgr2  : ADC configuration register 2
*                   - chselr1: ADC channel selection register 1
*                   - chselr2: ADC channel selection register 2
*                   - smpr   : ADC sampling time register
*
* Output         : None
* Return         : None
******************************************************************************/
void ADC_Init(ADC_InitTypeDef *adc,u16 channel)
{
	ADC_SetStructure(adc);
	
	_reg_modify(ADC->CFGR2,0xFFFFF0FF,((adc->clk_div)&0x0F)<<8);
	
	_reg_modify(ADC->CFGR2,0xFFFFFF00,((adc->stab_time))&0xFF);
	
	_reg_modify(ADC->SMPR,0xFFFFFF00,(adc->smp_time)&0xFF);
	
	_reg_modify(ADC->CFGR1,0xFFFFFCFF,((adc->resolution)&0x3)<<8);
	
	//ADC转换队列设置
	_reg_modify(ADC->CFGR1,0xF8FFFFFF,((0)&0x7)<<24);
	
	_reg_modify(ADC->CHSELR1,0xFFFFFFE0,(channel)&0x1F);
	
	if(adc->vref == ADC_EXTERNAL_VREF)
		_bit_set(ADC->CFGR1,ADC_EXTERNAL_VREF_MASK);
	else
		_bit_clr(ADC->CFGR1,ADC_EXTERNAL_VREF_MASK);
	
	if(adc->conv == ADC_CONTINUOUS_CONV_MODE)
		_bit_set(ADC->CFGR1,ADC_CONTINUOUS_CONVERSION_MASK);
	else
		_bit_clr(ADC->CFGR1,ADC_CONTINUOUS_CONVERSION_MASK);
	
	if(adc->overrun == ADC_OVERRUN_MODE_LAST)
		_bit_set(ADC->CFGR1,ADC_OVERRUN_MODE_MASK);
	else
		_bit_clr(ADC->CFGR1,ADC_OVERRUN_MODE_MASK);
	
	if(adc->align == ADC_RIGHT_ALIGN)
		_bit_clr(ADC->CFGR1,ADC_LEFT_ALIGNMENT_MASK);
	else
		_bit_set(ADC->CFGR1,ADC_LEFT_ALIGNMENT_MASK);
	
	// Select channel
	_reg_write(ADC->CHSELR3,(channel)&0x0000FFFF);
	
	if(adc->int_kind != 0)
	{
		NVIC_Init(3, 3, QADC_IRQn, 2);
		_reg_modify(ADC->IER,0xFFFFFF60,(adc->int_kind)&0x9F);
	}
	
	//adc_module_en();
	ADC_Cmd(1);
}
/*******************************************************************************
* Function Name  : ADC_GetConversionValue
* Description    : ADC 采样处理函数
* Input          :  - ADC_CHx：ADC采用通道  对应芯片引脚 ADC_INx (其中x取值0~7)
*
* Output         : None
* Return         : 对应引脚AD采集的值
******************************************************************************/

UINT16 ADC_GetConversionValue(UINT16 channel)
{
	UINT32 adcisr = 0,i;

	_reg_write(ADC->CHSELR3,(channel)&0x0000FFFF);
	_reg_modify(ADC->CHSELR1,0xFFFFFFE0,(channel)&0x1F);

	for (i = 0; i < 9; i++)
	{
		ADC_StartConv();
		while (EOSEQ !=(ADC->ISR & EOSEQ));
		ADC->ISR |= EOSEQ;
		ADC_StopConv();

		if(i == 0)
		{// Discard the 1'st char
			adcisr = (ADC->uFIFO_DAT.FIFO)&0xFFFF;
			adcisr = 0;
			continue;
		}
		adcisr += (ADC->uFIFO_DAT.FIFO)&0xFFFF;
	}

	return ((adcisr>>3)&0x0fff);
}

/*******************************************************************************
* Function Name  : ADC_Get_Battery
* Description    : 采集锂电池电量
* Input          : - ADC_CHx：ADC采用通道  对应芯片引脚 ADC_INx (其中x取值0~7)
*
* Output         : None
* Return         : None
******************************************************************************/

/*
unsigned int ADC_Get_Battery(unsigned char ADC_CHx)
{
	unsigned int resVC = 0;
	unsigned int res_battery = 0;
	unsigned int res_standard = 0;
	unsigned int reg_tmp;
	int i;

	for(i = 0; i < 10; i ++)
	{
		res_battery += ADC_GetConversionValue(ADC_CHx);
	}
	
	//input core test key
	CPM_Write_CoreTestKey();
	CPM->CPM_VCCCTMR |= (1<<21);
	

	reg_tmp = CPM->CPM_VCCVTRIMR;
	//CPM->CPM_VCCCTMR |= (1<<21);//OVERWR_VCC_TRIM位置上
	CPM->CPM_VCCVTRIMR |=  (1<<8);//关v_store reg
	CPM->CPM_VCCVTRIMR |=  (1<<10);//开trim en reg
	CPM->CPM_VCCVTRIMR |=  (1<<9);
	CPM->CPM_VCCCTMR &= ~(1<<21);
	
//	ADC_GetConversionValue(ADCCH_9);
//	for(i = 0; i < 10; i ++)
	{
		res_standard += ADC_GetConversionValue(ADCCH_9);
	}
	

	CPM->CPM_VCCVTRIMR &=  ~(1<<8);
	CPM->CPM_VCCVTRIMR &=  ~(1<<10);
	
	CPM->CPM_VCCCTMR |= (1<<21);
	CPM->CPM_VCCVTRIMR = reg_tmp;
	CPM->CPM_VCCCTMR &= ~(1<<21);

	resVC = 9*res_battery/res_standard;

	return resVC;
}
*/
