/* --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--*/

/*
 * ADS126x.c
 *
 *  Created on: Apr 25, 2014
 *      Author: a0406726
 */

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


/*****begin low level functions*************************************************/


/* Sets the state of the ADC's /CS pin:
*		0 = LOW 	(active)
*		1 = HIGH	(not selected)
*
*	Asserts:
*		'state' must be '0' or '1'
*/
void set_adc_CS(uint8_t state)
{
	if (0 == state)
	{
		GPIO_setOutputLowOnPin(CS_PORT, CS_PIN);
		__delay_cycles(Delay80ns);						//td(CSSC) delay
	}
	else if (1 == state)
	{
		__delay_cycles(Delay80ns);						//td(SCCS) delay
		GPIO_setOutputHighOnPin(CS_PORT, CS_PIN);
	}
	else
		assert(0);		//Aborts program
}


/* Sets the state of the ADC's START pin:
 *		0 = LOW 	(inactive)
 *		1 = HIGH	(converting)
 *
 *	Asserts:
 *		'state' must be '0' or '1'
*/
void set_adc_START(uint8_t state)
{
	if (0 == state)
		GPIO_setOutputLowOnPin(START_PORT, START_PIN);

	else if (1 == state)
		GPIO_setOutputHighOnPin(START_PORT, START_PIN);

	else
		assert(0);		//Aborts program
}

// receive byte, simultaneously send data
unsigned char ADS126xXferByte(unsigned char cData)
{
	while(USCI_B_SPI_isBusy(USCI_B0_BASE));
	USCI_B_SPI_transmitData(USCI_B0_BASE, cData);
	while(USCI_B_SPI_isBusy(USCI_B0_BASE));
	return USCI_B_SPI_receiveData(USCI_B0_BASE);
}

/*****end low level functions***************************************************/

/*****begin higher level functions***********************************************/

/* ADS126xReadData
*
*	Arguments:
*      NumBytes = the number of ADS126x data bytes to read (depends on STATUS and CRC settings)
*      DataByteStartNum = the location of the ADS126x MSB of data in the read operation
*      					= 1 if STATUS is enabled
*      					= 0 if STATUS is disabled
*
*	Asserts:
*      'NumBytes'  must be equal to 4, 5, or 6
*      'DataByteStartNum' must be equal to 0 or
*
*/
int32_t ADS126xReadData(uint8_t NumBytes, uint8_t DataByteStartNum)
{

	assert((4 == NumBytes) || (5 == NumBytes) || (6 == NumBytes));			//Aborts program if FALSE
	assert((0 == DataByteStartNum) || (1 == DataByteStartNum));				//Aborts program if FALSE

	uint8_t ADC_Bytes[6];													//Holds
	int32_t ADC_Data_Only;

	set_adc_CS(0);

	for(int i = 0; i < NumBytes; ++i)
		ADC_Bytes[i] = ADS126xXferByte(0);

	ADC_Data_Only = ((int32_t)ADC_Bytes[DataByteStartNum + 0] << 24) |		//Data MSB
					((int32_t)ADC_Bytes[DataByteStartNum + 1] << 16) |
					((int32_t)ADC_Bytes[DataByteStartNum + 2] <<  8) |
					((int32_t)ADC_Bytes[DataByteStartNum + 3] <<  0);		//Data LSB
	set_adc_CS(1);

	return ADC_Data_Only;
}

//// Reads data and writes to registers concurrently
//void ADS126xREADandWRITE(int NumDatBytes, int StartAddress, int NumRegs, unsigned char * pdata)
//{
//	uint8_t ADC_Bytes[6];
//	int32_t ADC_Data_Only;
//
//	WaitForDRDY();
//
//	set_adc_CS(0);
//
//	ADS126xXferByte(RDATA1);
//
//	ADS126xXferByte(0x40+StartAddress);
//	ADS126xXferByte(NumRegs-1);
//	for(int i=0;i<NumRegs;i++)
//	{
//		ADS126xXferByte(pdata[i]);
//	}
//	set_adc_CS(1);
//}



//unsigned char ADS126xReadADC2Data(bufferType_t *readbuffer){
//
//	set_adc_CS(0);
//	ADS126xXferByte(RDATA2);
//	readbuffer->data.status=ADS126xXferByte(0);
//	readbuffer->data.payload.bytes[3]=ADS126xXferByte(0);
//	readbuffer->data.payload.bytes[2]=ADS126xXferByte(0);
//	readbuffer->data.payload.bytes[1]=ADS126xXferByte(0);
//	readbuffer->data.payload.bytes[0]=ADS126xXferByte(0);
//	readbuffer->data.checksum=ADS126xXferByte(0);
//	readbuffer->data.adcindicator=0x80|g_packetCounter;
//	if(g_packetCounter<0x3F)
//		g_packetCounter++;
//	else
//		g_packetCounter=0;
//	set_adc_CS(1);
//	return readbuffer->data.checksum; //return CRC
//}


// write a number of consecutive registers from a given array pointer
void ADS126xWriteRegister(int StartAddress, int NumRegs, unsigned char * pdata)
{
	set_adc_CS(0);
	ADS126xXferByte(0x40+StartAddress);
	ADS126xXferByte(NumRegs-1);
	for(int i=0;i<NumRegs;i++)
		ADS126xXferByte(pdata[i]);
	set_adc_CS(1);
}

// read a number of consecutive registers to a given array pointer
void ADS126xReadRegister(int StartAddress, int NumRegs, unsigned char *pdata)
{
	set_adc_CS(0);
	ADS126xXferByte(0x20 + StartAddress);
	ADS126xXferByte(NumRegs - 1);
	for(int i=0;i<NumRegs;i++)
	{
		pdata[i] = ADS126xXferByte(0x00);
	}
	set_adc_CS(1);
}

// Reset by command (alternative to pin)
void ADS126xSendResetCommand(void){
	set_adc_CS(0);
	ADS126xXferByte(RESET);
	set_adc_CS(1);
}

// Start by command (alternative to pin)
void ADS126xSendStartCommand(void){
	set_adc_CS(0);
	ADS126xXferByte(START1);
	set_adc_CS(1);
}

// Stop by command (alternative to pin)
void ADS126xSendStopCommand(void){
	set_adc_CS(0);
	ADS126xXferByte(STOP1);
	set_adc_CS(1);
}

// Start by command
void ADS126xSendADC2StartCommand(void){
	set_adc_CS(0);
	ADS126xXferByte(START2);
	set_adc_CS(1);
}

// Stop by command
void ADS126xSendADC2StopCommand(void){
	set_adc_CS(0);
	ADS126xXferByte(STOP2);
	set_adc_CS(1);
}

// not implemented yet
void ADS126xShutdown(void){
	//pull PowerDown Pin low
}

// not implemented yet
void ADS126xWake(void){
	//pull PowerDown Pin high
}

/*****end higher level functions*************************************************/
