#include "ads8688.h"
#include "drv_spi.h"
#include "gpio_manager.h"

void ads8688_write_command_reg(uint16_t command)
{
	uint8_t command_data[2] = {0, 0};
	command_data[0] = (uint8_t) (command >> 8);
	command_data[1] = (uint8_t) (command & 0x00FF);
	
	drv_spi_sync_send_receive(kSpiDev_2, command_data);
}

void ads8688_write_program_reg(uint8_t addr, uint8_t data)
{
	uint8_t w_data[2] = {0, 0};
	w_data[0] = (addr < 1) | 0x01;
	w_data[1] = data;
	
	drv_spi_sync_send_receive(kSpiDev_2, w_data);
}

void ads8688_read_program_reg(uint8_t addr)
{
	uint8_t r_data[2] = {0, 0};
	uint8_t RxBuff;
	r_data[0] = (addr < 1);
	
	drv_spi_series_sync_send_receive(kSpiDev_2, r_data, 2, &RxBuff, 1);
}

void ads8688_enter_auto_rst_mode()
{
	ads8688_write_command_reg(AUTO_RST);
}

void ads8688_set_autoscan_sequence(uint8_t data)
{
	ads8688_write_program_reg(AUTO_SEQ_EN, data);
}

void ads8688_set_ch_range_select(uint8_t ch, uint8_t range) 
{                              
	ads8688_write_program_reg(ch, range);
}

void ads8688_set_channel_power_down(uint8_t pwd)
{                              
	ads8688_write_program_reg(Channel_Power_Down, pwd);
}

short ads8688_adc_data_convert(uint16_t x, uint8_t AI_RANGE)
{
	short y;
	switch(AI_RANGE) {
        case 0:
            y = x * 15625 / 100000;		//channel range 0~10.24V
            break;
        case 1:
            y = x * 78125 / 1000000;	//channel range 0~5.12V
            break;
        case 2:
            y = (x - 0x8000) * 3125 / 10000;	//channel range 10.24V
            break;
		case 3:
            y = (uint16_t)(((double)(x - 32768) * 10.24 / (double)65535) * 1000);	//channel range 5.12V
            break;
		case 4:
            y = (uint16_t)(((double)(x - 32768) * 5.12 / (double)65535) * 1000);		//channel range 2.56V
            break;
    }
	return y;
}

uint16_t adc_data[8];
uint16_t adc_real[8];

void ads8688_get_real_adc_data(uint16_t *adc_real, uint8_t AI_RANGE)
{
	adc_real[0] = (uint16_t)ads8688_adc_data_convert(adc_data[0], AI_RANGE);
	adc_real[1] = (uint16_t)ads8688_adc_data_convert(adc_data[1], AI_RANGE);
	adc_real[2] = (uint16_t)ads8688_adc_data_convert(adc_data[2], AI_RANGE);
	adc_real[3] = (uint16_t)ads8688_adc_data_convert(adc_data[3], AI_RANGE);
	adc_real[4] = (uint16_t)ads8688_adc_data_convert(adc_data[4], AI_RANGE);
	adc_real[5] = (uint16_t)ads8688_adc_data_convert(adc_data[5], AI_RANGE);
	adc_real[6] = (uint16_t)ads8688_adc_data_convert(adc_data[6], AI_RANGE);
	adc_real[7] = (uint16_t)ads8688_adc_data_convert(adc_data[7], AI_RANGE);
}

void Get_AUTO_RST_Mode_Data(uint8_t chn)
{	
	uint16_t i = 0;
 
	for(i = 0; i < chn; i++)
	{
		uint8_t data;
		drv_spi_sync_send_rev(kSpiDev_2, data);
		adc_data[i] = data << 8;
		drv_spi_sync_send_rev(kSpiDev_2, data);
		adc_data[i] = data;
	}
}

void get_ADS_all(uint8_t chn, uint16_t *adc_real, uint8_t AI_RANGE)
{
	Get_AUTO_RST_Mode_Data(chn);
	ads8688_get_real_adc_data(adc_real, AI_RANGE);
}

void ads8688_init()
{
	drv_spi_init(kSpiDev_2, kSpiFreq_Div16, kSpiMode_C1E0, SpiFrame_MSBFirst, kGpioType_ADC_Clk, kGpioType_ADC_Miso, kGpioType_ADC_Mosi);
	//drv_spi_set_dma(kSpiDev_2, true, false);
	
	ads8688_set_autoscan_sequence(0xFF);
	ads8688_set_channel_power_down(0x00);
	ads8688_set_ch_range_select(Channel_0_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_1_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_2_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_3_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_4_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_5_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_6_Input_Range, VREF_U_0_25);
	ads8688_set_ch_range_select(Channel_7_Input_Range, VREF_U_0_25);
	ads8688_enter_auto_rst_mode();
}
