/*********************************************************************
 * INCLUDES
 */
#include "bsp_adc.h"
#include "system.h"
#include "exception.h"
/*********************************************************************
 * DEFINITIONS
 */
#define PIN_NOT_USED						0xFF
#define CHANNEL_NOT_USED				0xFF
/*********************************************************************
 * STRUCTION
 */
typedef struct {
	uint32_t pin;
	uint32_t channel;
}adc_config_t;
/*********************************************************************
 * LOCAL VARIABLES
 */
static adc_config_t									m_adc_config[CHANNEL_MAX] 						= {{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED},{PIN_NOT_USED,CHANNEL_NOT_USED}};
static nrf_saadc_channel_config_t 	channelConfig[CHANNEL_MAX];
static nrf_saadc_value_t 						s_bufferPool[CHANNEL_MAX] 						= {0};
//定义SAADC采样数据缓存
//定义SAADC采样缓存数组大小
//只有采样结果存满该缓存之后,才会产生SAADC采样完成事件
static uint32_t 										sample_in_buffer 											= 0;

static bsp_adc_sample_notify_cb 		m_cb  																= NULL;
/*********************************************************************
 * LOCAL FUNCTIONS
 */
/**
 @brief ADC中断处理回调函数
 @param 无
 @return 无
*/
static void adcCallbackFunc(nrf_drv_saadc_evt_t const *pEvent)
{
	ret_code_t 			err_code;
	static int16_t 	adc_value[CHANNEL_MAX] = {0,0,0,0,0,0,0,0};
	uint8_t  				adc_sort[CHANNEL_MAX] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	uint8_t  				sort_index = 0;
	int  		 				i;	
	
	
	if(pEvent->type == NRF_DRV_SAADC_EVT_DONE)	// 采样完成，采集时填充顺序为，通道编号小的先填充。
	{
		//设置好缓存，为下一次采样做准备
		err_code=nrf_drv_saadc_buffer_convert(pEvent->data.done.p_buffer,sample_in_buffer);
		if(err_code == NRF_SUCCESS)
		{
			//预先排序，采集时填充顺序为，通道编号小的先填充。
			for(i=0;i<CHANNEL_MAX;i++)
			{
				if(channelConfig[i].pin_p != NRF_SAADC_INPUT_DISABLED){
					adc_sort[sort_index] = i;
//					DEBUG_LOG("adc_sort[%d] = %d\r\n",sort_index,i);
					sort_index++;
				}
			}
			//获取数据
			for(i=0;i<sample_in_buffer;i++)
			{
				adc_value[adc_sort[i]] = s_bufferPool[i];
			}

			if(m_cb != NULL)m_cb(adc_value);
		}
	}
}

static void bsp_adc_init_process(void)
{
	if(Except_TxError(EXCEPT_ADC_INIT,"bsp_adc_init_error\r\n") == 0)
	{
		Process_Stop(bsp_adc_init_process);
	}
}

/**
	@brief	初始化ADC
	@param	无
	@return 无
*/
static void ADC_Init(void)
{
	int 				ret = 0;
	ret_code_t 	errCode;
	
	nrf_drv_saadc_config_t p_config = NRFX_SAADC_DEFAULT_CONFIG;
	p_config.interrupt_priority = ADC_IRQ_PRIORITY;
	
	
	// ADC初始化
	errCode = nrf_drv_saadc_init(&p_config, adcCallbackFunc);//优先级设置为3，比定时器中断要高，不然回调会在定时器中断结束后触发。
	if(errCode != NRF_SUCCESS)ret = -1;

	// ADC通道配置
	for(int i=0;i<CHANNEL_MAX;i++)
	{
		if(m_adc_config[i].pin != PIN_NOT_USED && m_adc_config[i].channel != CHANNEL_NOT_USED)
		{
			// ADC通道初始化
			errCode = nrf_drv_saadc_channel_init(m_adc_config[i].channel, &channelConfig[m_adc_config[i].channel]);
			if(errCode != NRF_SUCCESS)ret = -1;
		}
	}
	
	if(sample_in_buffer > 0)
	{
		// 缓冲配置
		errCode = nrf_drv_saadc_buffer_convert(s_bufferPool, sample_in_buffer);
		if(errCode != NRF_SUCCESS)ret = -1;
	}
	
	
	if(ret == -1)
	{
		Process_Start(0,"bsp_adc_init_process",bsp_adc_init_process);
	}
}

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
/**
	@brief	初始化ADC引脚和通道
	@param	pin -[in]	需要初始化的adc引脚
	@param	channel -[in]	需要初始化的adc通道
	@return 错误代码
*/
uint32_t ADC_SetPinChannel(uint32_t pin, uint32_t channel,nrf_gpio_pin_pull_t pin_pull)
{
	ret_code_t 	errCode;
	
	//清除已存在的引脚和通道
	ADC_RemovePinChannel(pin, channel);
	
	for(int i=0;i<CHANNEL_MAX;i++)
	{
		if(m_adc_config[i].pin == PIN_NOT_USED && m_adc_config[i].channel == CHANNEL_NOT_USED && PIN_NOT_USED != pin)	
		{
			//不关闭总开关是不能关闭通道的
			ADC_Disable();
			
			m_adc_config[i].pin = pin;
			m_adc_config[i].channel = channel;
			
			//保留之前的引脚配置,一旦就失败复原
			nrf_gpio_pin_dir_t dir = nrf_gpio_pin_dir_get(m_adc_config[i].pin);
			
			//设置ADC引脚为浮空
			nrf_gpio_cfg_input(m_adc_config[i].pin,pin_pull);
			// 单端输入
			channelConfig[m_adc_config[i].channel].resistor_p = NRF_SAADC_RESISTOR_DISABLED;
			channelConfig[m_adc_config[i].channel].resistor_n = NRF_SAADC_RESISTOR_DISABLED;
			channelConfig[m_adc_config[i].channel].gain       = NRF_SAADC_GAIN1_6;
			channelConfig[m_adc_config[i].channel].reference  = NRF_SAADC_REFERENCE_INTERNAL;
			channelConfig[m_adc_config[i].channel].acq_time   = NRF_SAADC_ACQTIME_10US;
			channelConfig[m_adc_config[i].channel].mode       = NRF_SAADC_MODE_SINGLE_ENDED;
			channelConfig[m_adc_config[i].channel].burst      = NRF_SAADC_BURST_DISABLED;
			channelConfig[m_adc_config[i].channel].pin_p      = (nrf_saadc_input_t)(m_adc_config[i].channel + 1);
			channelConfig[m_adc_config[i].channel].pin_n      = NRF_SAADC_INPUT_DISABLED;
			// ADC通道初始化
			errCode = nrf_drv_saadc_channel_init(m_adc_config[i].channel, &channelConfig[m_adc_config[i].channel]);
			if(errCode != NRF_SUCCESS)
			{
				channelConfig[m_adc_config[i].channel].pin_p = NRF_SAADC_INPUT_DISABLED;
				m_adc_config[i].pin = PIN_NOT_USED;
				m_adc_config[i].channel = CHANNEL_NOT_USED;
				nrf_gpio_pin_dir_set(m_adc_config[i].pin, dir);
				
				ADC_Enable();
				
				return ADC_ERR_INIT_CONGESTION;
			}
			
			sample_in_buffer++;
			
			ADC_Enable();
			
			return ADC_OP_SUCCESS;
		}
	}
	return ADC_ERR_INIT_CONGESTION;
}
/**
	@brief	移除已初始化ADC引脚和通道
	@param	pin -[in]	需要移除的adc引脚
	@param	channel -[in]	需要移除的adc通道
	@return 错误代码
*/
uint32_t ADC_RemovePinChannel(uint32_t pin, uint32_t channel)
{
	for(int i=0;i<CHANNEL_MAX;i++)
	{
		if(m_adc_config[i].pin == pin && m_adc_config[i].channel == channel)
		{
			nrf_drv_saadc_channel_uninit(m_adc_config[i].channel);
			channelConfig[m_adc_config[i].channel].pin_p = NRF_SAADC_INPUT_DISABLED;
			m_adc_config[i].pin = PIN_NOT_USED;
			m_adc_config[i].channel = CHANNEL_NOT_USED;
			if(sample_in_buffer != 0)sample_in_buffer--;
			return ADC_OP_SUCCESS;
		}
	}
	return ADC_ERR_REMOVE_PIN_CHANNEL;
}

/**
	@brief ADC触发采样
	@param cb -[in]通知回调
	@return 错误代码
*/
uint32_t ADC_Sample(bsp_adc_sample_notify_cb cb)
{
	uint32_t errCode;

	if(cb != NULL)
	{
		//没有配置通道返回失败
		if(sample_in_buffer == 0)return ADC_ERR_READ_NO_CHANNEL;
		ADC_Disable();
		ADC_Enable();
		errCode = nrf_drv_saadc_sample();
		if(errCode != NRF_SUCCESS)return ADC_ERR_TRIGGER_FAIL;

		m_cb = cb;

		return ADC_OP_SUCCESS;
	}
	
	return ADC_ERR_TRIGGER_FAIL;
}
/**
 @brief 开启ADC，与初始化没有区别，为了与Disable成对出现
 @param 无
 @return 无
*/
void ADC_Enable(void)
{
	ADC_Init();
}
/**
 @brief 禁用ADC
 @param 无
 @return 无
*/
void ADC_Disable(void)
{
	nrf_drv_saadc_uninit();
}






