/* --COPYRIGHT--,BSD
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
/*
 * ac_bridge.c
 *
 *  Created on: May 27, 2015
 *      Author: a0282860
 */

#include "adc2_demo.h" 								// All other required source files are declared here




//File global variables

//File constants
const uint8_t MinNumADCReadings 	= 64;

//Internal inline function prototypes (not declared in "control.h")
static inline void show_AppMenu(void);
static inline void LoadInitRegSettings(void);
static inline void ADS126xReadADC1FasterThanADC2(void);
static inline void ADS126xReadADC1EqualToADC2(void);
static inline void ADS126xReadADC1SlowerThanADC2(void);

void run_adc2_demo(char c)
{
	int16_t option = (int16_t) c - 48;	//Convert character "c" to a (0 through 9) integer "option"

	if (NULL == c)
		show_AppMenu();					//show application menu

	else if (0 == option)
		LoadInitRegSettings();			//configure register settings

	else if (1 == option)
		ADS126xReadADC1FasterThanADC2();

	else if (2 == option)
		ADS126xReadADC1EqualToADC2();

	else if (3 == option)
		ADS126xReadADC1SlowerThanADC2();

	else
		printError();					//invalid option
}


static inline void show_AppMenu(void)
{

#ifdef CONSOLE_OUTPUT
	strcpy(outString,"\r\nSelect Operation:\r\n");
	print2Console(outString);
	strcpy(outString,"\ty0) Configure Register Settings for ADC1 & ADC2\r\n");
	print2Console(outString);
	strcpy(outString,"\ty1) Read 16 results (DR1 > DR2)\r\n");
	print2Console(outString);
	strcpy(outString,"\ty2) Read 16 results (DR1 = DR2)\r\n");
	print2Console(outString);
	strcpy(outString,"\ty3) Read 16 results (DR1 < DR2)\r\n");
	print2Console(outString);
#endif
}

static inline void LoadInitRegSettings(void)
{
	uint8_t AdcRegData[ADS126x_NUM_REG];							//Stores the register read values
	uint8_t WriteRegData[ADS126x_NUM_REG];							//Stores the register write values

	ADS126xReadRegister(ID, ADS126x_NUM_REG, AdcRegData);			//Read ALL registers

	/* Configure Register Settings */
	WriteRegData[ID] = AdcRegData[ID];								//ID
	WriteRegData[POWER] = (AdcRegData[POWER] & ~RST) | INTREF;		//POWER (RESET = 0, INTREF = 1)
	WriteRegData[INTERFACE] = STATUS | CRC_ON;						//INTERFACE (STATUS & CRC bytes ON)
	WriteRegData[MODE0] = MODE0_DEFAULT_VALUE;						//MODE0 (reset to default)
	WriteRegData[MODE1] = AdcRegData[MODE1];						//MODE1
	WriteRegData[MODE2] = (AdcRegData[MODE2] & ~BYPASS) | GAIN_2;	//MODE2 (BYPASS OFF, GAIN1 = 32 V/V)
	WriteRegData[INPMUX] = MUXP_AIN6 | MUXN_AIN7;					//INPMUX (AINP1 = AIN1, AINN1 = AIN2)
	WriteRegData[OFCAL0] = OFCAL0_DEFAULT_VALUE;					//OFCAL0 (reset to default)
	WriteRegData[OFCAL1] = OFCAL1_DEFAULT_VALUE;					//OFCAL1 (reset to default)
	WriteRegData[OFCAL2] = OFCAL2_DEFAULT_VALUE;					//OFCAL2 (reset to default)
	WriteRegData[FSCAL0] = FSCAL0_DEFAULT_VALUE;					//FSCAL0 (reset to default)
	WriteRegData[FSCAL1] = FSCAL1_DEFAULT_VALUE;					//FSCAL1 (reset to default)
	WriteRegData[FSCAL2] = FSCAL2_DEFAULT_VALUE;					//FSCAL2 (reset to default)
	WriteRegData[IDACMUX] = MUX2_NO_CONM | MUX1_AINCOM;				//IDACMUX (IDAC1MUX = AINCOM)
	WriteRegData[IDACMAG] = MAG2_OFF | MAG1_500uA;					//IDACMAG (IDAC1MAG = 500 uA)
	WriteRegData[REFMUX] = RMUXP_AIN4 | RMUXN_AIN5;					//REFMUX (REFP = AIN0, REFN = AIN3)
	WriteRegData[TDACP] = TDACP_DEFAULT_VALUE;						//TDACP (reset to default)
	WriteRegData[TDACN] = TDACN_DEFAULT_VALUE;						//TDACN (reset to default)
	WriteRegData[GPIOCON] = CON6_AIN09 | CON5_AIN08;				//GPIOCON (Enable GPIOs on AIN8 & AIN9)
	WriteRegData[GPIODIR] = GPIOCON_DEFAULT_VALUE;					//GPIODIR (reset to default)
	WriteRegData[GPIODAT] = DAT5_AIN08;								//GPIODAT (Biases bridge with + polarity)
#ifdef ADS1263
	WriteRegData[ADC2CFG] = REF2_AIN4_AIN5 | GAIN2_2;				//ADC2CFG (REF2 = AIN4/AIN5, GAIN2 = 2 V/V)
	WriteRegData[ADC2MUX] = MUXP2_AIN6 | MUXN2_AIN7;				//ADC2MUX (AINP2 = AIN6, AINN2 = AIN7)
	WriteRegData[ADC2OFC0] = ADC2OFC0_DEFAULT_VALUE;				//ADC2OFC0 (reset to default)
	WriteRegData[ADC2OFC1] = ADC2OFC1_DEFAULT_VALUE;				//ADC2OFC1 (reset to default)
	WriteRegData[ADC2FSC0] = ADC2FSC0_DEFAULT_VALUE;				//ADC2FSC0 (reset to default)
	WriteRegData[ADC2FSC1] = ADC2FSC1_DEFAULT_VALUE;				//ADC2FSC1 (reset to default)
#endif

	ADS126xWriteRegister(ID, ADS126x_NUM_REG, &WriteRegData[0]);	//Write ALL registers

#ifdef CONSOLE_OUTPUT
	show_parms('0');		//read back registers and output to console
#endif
}

static inline void ADS126xReadADC1FasterThanADC2(void)
{
	uint8_t i = 0;
	uint16_t ADC1count = 0, ADC2count = 0;							//Data conversion counters
	uint8_t AdcRegData[ADS126x_NUM_REG];							//Stores the register read values
	uint8_t WriteRegData;											//Stores register write value

	uint8_t ADC1_Bytes[6];
	uint8_t ADC2_Bytes[6];

	set_adc_START(0);												//Set START low
	ADS126xReadRegister(ID, ADS126x_NUM_REG, AdcRegData);			//Read ALL registers
	WriteRegData = (AdcRegData[MODE2] & ~DR_MASK) | DR_60_SPS;					//MODE2
	ADS126xWriteRegister(MODE2, 1, &WriteRegData);						//Configure ADC1 data rate
	WriteRegData = (AdcRegData[ADC2CFG] & ~DR2_MASK) | DR2_10SPS;	//ADC2CFG
	ADS126xWriteRegister(ADC2CFG, 1, &WriteRegData);					//Configure ADC2 data rate
	set_adc_START(1);												//Set START high

	set_adc_CS(0);
	ADS126xXferByte(START2);										//Start ADC2 conversions
	set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
	strcpy(outString,"\r\nADC1count\tADC2count\tSTATUS1\tADC1data\tSTATUS2\tADC2data\r\n");
	print2Console(outString);
	strcpy(outString,"---------\t---------\t-------\t----------\t-------\t----------\r\n");
	print2Console(outString);
#endif

	while((ADC1count < MinNumADCReadings) && (ADC2count < MinNumADCReadings))
	//for(k = 0; k < MinNumADCReadings; ++k)
	{
		for(i = 0; i < 6; ++i)							//Clear Data Arrays
		{
			ADC1_Bytes[i] = 0;
			ADC2_Bytes[i] = 0;
		}

		WaitForDRDY();									//Wait

		set_adc_CS(0);
		ADS126xXferByte(RDATA1);						//Send RDATA1 command
		for(i = 0; i < 6; ++i)
			ADC1_Bytes[i] = ADS126xXferByte(0);

		if (ADC1_Bytes[0] & ADC1_NEW)					//ADC1 Data New?
			ADC1count++;

		if (ADC1_Bytes[0] & ADC2_NEW)					//ADC2 Data New?
		{
			ADS126xXferByte(RDATA2);					//Send RDATA2 command
			for(i = 0; i < 6; ++i)
				ADC2_Bytes[i] = ADS126xXferByte(0);
		}

//		ADS126xXferByte(0);				//NOTE: Repeating data read keep the previous STATUS byte.
//		ADS126xXferByte(0);
//		ADS126xXferByte(RDATA2);		//NOTE: Only after RDATAx is sent again, does the ADC1/2 bit update to show old data
//		ADS126xXferByte(0);
//		ADS126xXferByte(0);

		if (ADC2_Bytes[0] & ADC2_NEW)					//ADC2 Data New?
			ADC2count++;
		set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
		strcpy(outString,"0x");
		hex2asc(&ADC1count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC2count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC1_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC1_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\r\n");
		print2Console(outString);
#endif
	}

	//Set START low
	set_adc_START(0);


	strcpy(outString,"\r\nADC1count = 0x");
	hex2asc(&ADC1count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\nADC2count = 0x");
	hex2asc(&ADC2count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\n");
	print2Console(outString);
}

static inline void ADS126xReadADC1EqualToADC2(void)
{
	uint8_t i = 0;
	uint16_t ADC1count = 0, ADC2count = 0;							//Data conversion counters
	uint8_t AdcRegData[ADS126x_NUM_REG];							//Stores the register read values
	uint8_t WriteRegData;											//Stores register write value

	uint8_t ADC1_Bytes[6];
	uint8_t ADC2_Bytes[6];

	set_adc_START(0);												//Set START low
	ADS126xReadRegister(ID, ADS126x_NUM_REG, AdcRegData);			//Read ALL registers
	WriteRegData = (AdcRegData[MODE2] &~ DR_MASK) | DR_10_SPS;		//MODE2
	ADS126xWriteRegister(MODE2, 1, &WriteRegData);						//Configure ADC1 data rate
	WriteRegData = (AdcRegData[ADC2CFG] & ~DR2_MASK) | DR2_10SPS;	//ADC2CFG
	ADS126xWriteRegister(ADC2CFG, 1, &WriteRegData);					//Configure ADC2 data rate
	set_adc_START(1);												//Set START high

	set_adc_CS(0);
	ADS126xXferByte(START2);										//Start ADC2 conversions
	set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
	strcpy(outString,"\r\nADC1count\tADC2count\tSTATUS1\tADC1data\tSTATUS2\tADC2data\r\n");
	print2Console(outString);
	strcpy(outString,"---------\t---------\t-------\t----------\t-------\t----------\r\n");
	print2Console(outString);
#endif

	while((ADC1count < MinNumADCReadings) && (ADC2count < MinNumADCReadings))
	//for(k = 0; k < MinNumADCReadings; ++k)
	{
		for(i = 0; i < 6; ++i)							//Clear Data Arrays
		{
			ADC1_Bytes[i] = 0;
			ADC2_Bytes[i] = 0;
		}

		WaitForDRDY();									//Wait

		set_adc_CS(0);
		ADS126xXferByte(RDATA1);						//Send RDATA1 command
		for(i = 0; i < 6; ++i)
			ADC1_Bytes[i] = ADS126xXferByte(0);

		if (ADC1_Bytes[0] & ADC1_NEW)					//ADC1 Data New?
			ADC1count++;

		if (ADC1_Bytes[0] & ADC2_NEW)					//ADC2 Data New?
		{
			ADS126xXferByte(RDATA2);					//Send RDATA2 command
			for(i = 0; i < 6; ++i)
				ADC2_Bytes[i] = ADS126xXferByte(0);
		}

		if (ADC2_Bytes[0] & ADC2_NEW)					//ADC2 Data New?
			ADC2count++;
		set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
		strcpy(outString,"0x");
		hex2asc(&ADC1count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC2count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC1_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC1_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\r\n");
		print2Console(outString);
#endif
	}

	//Set START low
	set_adc_START(0);


	strcpy(outString,"\r\nADC1count = 0x");
	hex2asc(&ADC1count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\nADC2count = 0x");
	hex2asc(&ADC2count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\n");
	print2Console(outString);
}


static inline void ADS126xReadADC1SlowerThanADC2(void)
{
	uint8_t i = 0;
	uint16_t ADC1count = 0, ADC2count = 0;							//Data conversion counters
	uint8_t AdcRegData[ADS126x_NUM_REG];							//Stores the register read values
	uint8_t WriteRegData;											//Stores register write value

	uint8_t ADC1_Bytes[6];
	uint8_t ADC2_Bytes[6];

	set_adc_START(0);												//Set START low
	ADS126xReadRegister(ID, ADS126x_NUM_REG, AdcRegData);			//Read ALL registers
	WriteRegData = (AdcRegData[MODE2] &~ DR_MASK) | DR_2_5_SPS;		//MODE2
	ADS126xWriteRegister(MODE2, 1, &WriteRegData);						//Configure ADC1 data rate
	WriteRegData = (AdcRegData[ADC2CFG] & ~DR2_MASK) | DR2_10SPS;	//ADC2CFG
	ADS126xWriteRegister(ADC2CFG, 1, &WriteRegData);					//Configure ADC2 data rate
	set_adc_START(1);												//Set START high

	set_adc_CS(0);
	ADS126xXferByte(START2);										//Start ADC2 conversions
	set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
	strcpy(outString,"\r\nADC1count\tADC2count\tSTATUS1\tADC1data\tSTATUS2\tADC2data\r\n");
	print2Console(outString);
	strcpy(outString,"---------\t---------\t-------\t----------\t-------\t----------\r\n");
	print2Console(outString);
#endif

	while((ADC1count < MinNumADCReadings) && (ADC2count < MinNumADCReadings))
	//for(k = 0; k < MinNumADCReadings; ++k)
	{
		for(i = 0; i < 6; ++i)							//Clear Data Arrays
		{
			ADC1_Bytes[i] = 0;
			ADC2_Bytes[i] = 0;
		}

		__delay_cycles(Delay50ms);						//Polling Rate - TODO: Use a timer for best performance
		//WaitForDRDY();									//Wait

		set_adc_CS(0);
		ADS126xXferByte(RDATA2);						//Send RDATA1 command
		ADC2_Bytes[0] = ADS126xXferByte(0);				//Read STATUS byte

		if(ADC2_Bytes[0] & ADC2_NEW)					//If ADC2_NEW
		{
			for(i = 1; i < 6; ++i)
				ADC2_Bytes[i] = ADS126xXferByte(0);			//Read ADC1 Data
			ADC2count++;
		}

		if(ADC2_Bytes[0] & ADC1_NEW)					//If ADC1_NEW
		{
			set_adc_CS(1);								//Toggle /CS
			set_adc_CS(0);

			ADS126xXferByte(RDATA1);						//Send RDATA2 command
			for(i = 0; i < 6; ++i)
				ADC1_Bytes[i] = ADS126xXferByte(0);			//Read ADC2 Data
			ADC1count++;
		}
		set_adc_CS(1);

#ifdef CONSOLE_OUTPUT
		strcpy(outString,"0x");
		hex2asc(&ADC1count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC2count,4,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t\t0x");
		hex2asc(&ADC1_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC1_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC1_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[0],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\t0x");
		hex2asc(&ADC2_Bytes[1],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[2],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[3],2,2,tempString,1);
		strcat(outString,tempString);
		hex2asc(&ADC2_Bytes[4],2,2,tempString,1);
		strcat(outString,tempString);
		strcat(outString,"\r\n");
		print2Console(outString);
#endif
	}

	set_adc_CS(0);
	ADS126xXferByte(STOP2);
	set_adc_CS(1);

	//Set START low
	set_adc_START(0);


	strcpy(outString,"\r\nADC1count = 0x");
	hex2asc(&ADC1count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\nADC2count = 0x");
	hex2asc(&ADC2count,4,2,tempString,1);
	strcat(outString,tempString);
	strcat(outString,"\r\n");
	print2Console(outString);
}
