/*
 * AD7193.c
 *
 *  Created on: gg/mmm/ccaa
 *      Author: cognome.nome
 */

//==============================================================================
// Include files

#include "string.h"
#include "stdbool.h"
#include "stdint.h"

#include "inc/hw_memmap.h"

#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"

//#include "AD7193_internal.h"
#include "drivers/my_SPI.h"
#include "my_GPIO.h"
#include "my_timer.h"
#include "drivers/my_semaphore.h"
#include "AD7193.h"
#include "my_calibration.h"

//==============================================================================
// Constants

//==============================================================================
// Types

// ID register (RO) default 0xX2
typedef struct
{
	union
	{
		struct
		{
			unsigned char ID_LOW	        : 4;
			unsigned char ID_HIGH	        : 4;
		};
		unsigned char IDAll;
	};
}TID;

// GPOCon register (RW) default 0x00
typedef struct
{
	union
	{
		struct
		{
			unsigned char P0DAT	            :  1;
			unsigned char P1DAT           	:  1;
			unsigned char P2DAT       		:  1;
			unsigned char P3DAT           	:  1;
			unsigned char GP10EN   	        :  1;
			unsigned char GP32EN            :  1;
			unsigned char BPDSW      	    :  1;
			unsigned char DUMMY_7           :  1;
		};
		unsigned char GPOConAll;
	};
}TGPOCon;

//==============================================================================
// Static global variables

static TID ID;										  // ID register (RO)             default 0xX2
static TGPOCon GPOCon;								  // GPOCon register (RW)         default 0x00

//==============================================================================
// Static functions

static inline void GPIO_set_REL_MICRO1(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, value);
}

static inline void GPIO_set_REL_MICRO2(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4, value);
}

static inline void GPIO_set_REL_MICRO3(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_5, value);
}

static inline void GPIO_set_REL_MICRO4(unsigned long value)
{
	ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_6, value);
}

static long SingleEndedChannelSet(void)
{
	switch(AcquisitionManage.ChannelNumberSingleEnded)
	{
		case ChannelNum1:
		{
			GPIO_set_REL_MICRO1(WRITE_0);
			GPIO_set_REL_MICRO2(WRITE_1);
			GPIO_set_REL_MICRO3(WRITE_1);
			GPIO_set_REL_MICRO4(WRITE_1);
			Configuration.CH0 = 1; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 0; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum2:
		{
			GPIO_set_REL_MICRO1(WRITE_0);
			GPIO_set_REL_MICRO2(WRITE_0);
			GPIO_set_REL_MICRO3(WRITE_1);
			GPIO_set_REL_MICRO4(WRITE_1);
			Configuration.CH0 = 1; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 1; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum3:
		{
			GPIO_set_REL_MICRO1(WRITE_0);
			GPIO_set_REL_MICRO2(WRITE_0);
			GPIO_set_REL_MICRO3(WRITE_0);
			GPIO_set_REL_MICRO4(WRITE_1);
			Configuration.CH0 = 1; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 1; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 1; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum4:
		{
			GPIO_set_REL_MICRO1(WRITE_0);
			GPIO_set_REL_MICRO2(WRITE_0);
			GPIO_set_REL_MICRO3(WRITE_0);
			GPIO_set_REL_MICRO4(WRITE_0);
			Configuration.CH0 = 1; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 1; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 1; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 1; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		default:
		{
			GPIO_set_REL_MICRO1(WRITE_1);
			GPIO_set_REL_MICRO2(WRITE_1);
			GPIO_set_REL_MICRO3(WRITE_1);
			GPIO_set_REL_MICRO4(WRITE_1);
			Configuration.CH0 = 0; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 0; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		};
	}
	return 0;
}

static long DifferentialChannelSet(void)
{
	GPIO_set_REL_MICRO1(WRITE_1);
	GPIO_set_REL_MICRO2(WRITE_1);
	GPIO_set_REL_MICRO3(WRITE_1);
	GPIO_set_REL_MICRO4(WRITE_1);

	switch(AcquisitionManage.ChannelNumberDifferential)
	{
		case ChannelNum1:
		{
			Configuration.CH0 = 1; // Channel 1
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 0; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum2:
		{
			Configuration.CH0 = 1; // Channel 1
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 0; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 1; // Channel 2
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum3:
		{
			Configuration.CH0 = 1; // Channel 1
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 1; // Channel 3
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 1; // Channel 2
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		}break;
		case ChannelNum4:
		{
			Configuration.CH0 = 1; // Channel 1
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 1; // Channel 3
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 1; // Channel 2
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 1; // Channel 4
		}break;
		default:
		{
			Configuration.CH0 = 0; // Channel select bits
			Configuration.CH1 = 0; // Channel select bits
			Configuration.CH2 = 0; // Channel select bits
			Configuration.CH3 = 0; // Channel select bits
			Configuration.CH4 = 0; // Channel select bits
			Configuration.CH5 = 0; // Channel select bits
			Configuration.CH6 = 0; // Channel select bits
			Configuration.CH7 = 0; // Channel select bits
		};
	}
	return 0;
}

//==============================================================================
// Global variables

// registers
TCommunications Communications;						  // Communication register (WO)  default 0x00
TStatus Status;										  // Status register (RO)         default 0x80
TMode Mode;			    							  // Mode register (R/W)          default 0x080060
TMode ModeForCalib;			    					  // Mode register (R/W)          default 0x080060
TConfiguration Configuration;	 					  // Configuration register (R/W) default 0x000117
TConfiguration ConfigurationForCalib;	 			  // Configuration register (R/W) default 0x000117
TData Data;											  // Data register (RO)           default 0x000000
TOffset Offset;									  	  // Offset register (RW)         default 0x800000
TFullScale FullScale;							 	  // Full-scale register (R/W)    default 0x5XXXX0

// settings
TAcquisitionManage AcquisitionManage;

//==============================================================================
// Global functions

inline unsigned long AD7193_Is_continuous_read(void)
{
	return(AcquisitionManage.ContinousReadAD);
}

long InitAD7193(TAcquisitionManage AcquisitionManageTLGB, TMode ModeTLGB, TConfiguration ConfigurationTLGB)
{
	int i = 0;

	//--------------------------------------------------------
	// Settaggio GPIO per relays
	//--------------------------------------------------------
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    // REL_MICRO1
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    // REL_MICRO2
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4);
    // REL_MICRO3
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_5);
    // REL_MICRO4
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6);
	//--------------------------------------------------------

	memset(&Communications,0,sizeof(TCommunications));
	memset(&Status,0,sizeof(TStatus));
	memset(&Mode,0,sizeof(TMode));
	memset(&ModeForCalib,0,sizeof(TMode));
	memset(&Configuration,0,sizeof(TConfiguration));
	memset(&ConfigurationForCalib,0,sizeof(TConfiguration));
	memset(&Data,0,sizeof(TData));
	memset(&ID,0,sizeof(TID));
	memset(&GPOCon,0,sizeof(TGPOCon));
	memset(&Offset,0,sizeof(TOffset));
	memset(&FullScale,0,sizeof(TFullScale));

	memset(&AcquisitionManage,0,sizeof(TAcquisitionManage));

	// parametri da modificare

	Mode.CLK1    = 1; // Internal 4.92 MHz clock. Pin MCLK2 is tristated.
	Mode.DAT_STA = 1; // This bit enables the transmission of status register contents after each data register read.

	//Filter output data rate select bits. The 10 bits of data programmed into these bits determine the filter
	//cutoff frequency, the position of the first notch of the filter, and the output data rate for the part. In
	//association with the gain selection, they also determine the output noise and, therefore, the effective
	//resolution of the device (see Table 7 through Table 15).

	Mode.FS = ModeTLGB.FS; //48; // da 1 a 1023

	//Single cycle conversion enable bit. When this bit is set, the AD7193 settles in one conversion cycle so
	//that it functions as a zero latency ADC. This bit has no effect when multiple analog input channels are
	//enabled or when the single conversion mode is selected. If the average + decimate filter is enabled, this
	//bit (single) does not have an effect on the conversions unless chopping is also enabled.
	Mode.Single = ModeTLGB.Single; // 0

	// The AVG1 and AVG0 bits select the amount of averaging.
	// Fast settling mode can be used for FS words less than 512 only.
	// When the sinc3 filter is selected, the FS word must be less than 256 when averaging by 16.
	//  0   -  0   -  NO
	//  0   -  1   -  2 valori
	//  1   -  0   -  8 valori
	//  1   -  1   - 16 valori
	Mode.AVG1 = ModeTLGB.AVG1; // 1
	Mode.AVG0 = ModeTLGB.AVG0; // 0

	Mode.SINC3 = ModeTLGB.SINC3; //
	//if(Mode.FS >= 15) // 4800 / 15 = 320 Hz, fino a 320 Hz e' meglio usare sync 3
	//{
	//	Mode.SINC3   = 1; //
	//}
	//else
	//{
	//	Mode.SINC3   = 0; //
	//}

	Configuration.Chop = ConfigurationTLGB.Chop; //1; // filtro per il drift di default = 0

	//-------------------------------------------
	// Parametri utente
	//-------------------------------------------
	AcquisitionManage.AcquisitionMode = AcquisitionManageTLGB.AcquisitionMode; // Differential;
	AcquisitionManage.ChannelNumberSingleEnded  = AcquisitionManageTLGB.ChannelNumberSingleEnded; // ChannelNum4;
	AcquisitionManage.ChannelNumberDifferential = AcquisitionManageTLGB.ChannelNumberDifferential; // ChannelNum4;
	AcquisitionManage.GainSel = AcquisitionManageTLGB.GainSel;

	// valore da salvare in flash
	// ReferenceValueRefin_1 e' quello regolabile con il trimmer, schema VREF_ADC_1
	//AcquisitionManage.ReferenceValueRefin_1 = 4.960f;
	AcquisitionManage.ReferenceValueRefin_1 = 4.10f;
	// valore da salvare in flash
	// ReferenceValueRefin_2 e' quello fisso generato da IC8
	AcquisitionManage.ReferenceValueRefin_2 = 4.9899f;

	//Configuration.BUF = 1; // Enables the buffer on the analog inputs
	//-------------------------------------------
	// 5V tensione di riferimento
	// G2 - G1 - G0 - GAIN - ADC input Range
	//  0 -  0 -  0 -  1   - +- 5V
	//  0 -  1 -  1 -  8   - +- 625mV
	//  1 -  0 -  0 -  16  - +- 312.5mV
	//  1 -  0 -  1 -  32  - +- 156.2mV
	//  1 -  1 -  0 -  64  - +- 78.125mV
	//  1 -  1 -  1 -  128 - +- 39.06mV
	//-------------------------------------------
	GainSelector(&Configuration, &AcquisitionManage);

	//------------------------------------------------------------------
	// abilita o disabilita la possibilita' di pilotare il LED rosso sulla scheda ADC che serve per una diagnostica
	GPOCon.GP32EN = 1; // Digital Output P3 and Digital Output P2 enable
	//------------------------------------------------------------------

	// parametri da NON modificare!!!
	switch(AcquisitionManage.AcquisitionMode)
	{
		case Single_ended:
		{
									  // 0 - External reference applied between REFIN1(+) and REFIN1(−).
			Configuration.REFSEL = 1; // 1 - External reference applied between the P1/REFIN2(+) and P0/REFIN2(−) pins.
			Configuration.Pseudo = 1;
			Configuration.U_B = 1; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_2;
			SingleEndedChannelSet();
		}break;
		case Differential:
		{
			Configuration.REFSEL = 0;
			Configuration.Pseudo = 0;
			Configuration.U_B = 0; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_1;
			DifferentialChannelSet();
		}break;
		default:
		{
			Configuration.REFSEL = 1;
			Configuration.Pseudo = 1;
			Configuration.U_B = 1; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_2;
			SingleEndedChannelSet();
		}
	}

    //----------------------------------------
    // RESET AD
    for(i = 0 ; i < 40 ; i++)
    {
    	GPIO_set_ADC_SCLK(WRITE_0);
    	GPIO_set_ADC_DIN(WRITE_1);
    	GPIO_set_ADC_SCLK(WRITE_1);
    }
    ROM_SysCtlDelay(500*MICRO_DELAY);
    //----------------------------------------

    //----------------------------------------
    // STRUTTURE PER CALIBRAZIONE
    ConfigurationForCalib = Configuration;
    ModeForCalib          = Mode;
    //----------------------------------------

    AD7193_WriteConfigurationRegister(&Configuration);
    AD7193_WriteModeRegister(&Mode);

    ApplyCalibrationFromFlashOffset();
    ApplyCalibrationFromFlashFullScale();

	return 0;
}

long InitAD7193ForCalibration(EAcquistionMode AcquisitionMode, EGainSelection GainSelection)
{
	int i = 0;

	//--------------------------------------------------------
	// Settaggio GPIO per relays
	//--------------------------------------------------------
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    // REL_MICRO1
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    // REL_MICRO2
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4);
    // REL_MICRO3
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_5);
    // REL_MICRO4
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_6);
	//--------------------------------------------------------

	memset(&Communications,0,sizeof(TCommunications));
	memset(&Status,0,sizeof(TStatus));
	memset(&Mode,0,sizeof(TMode));
	memset(&ModeForCalib,0,sizeof(TMode));
	memset(&Configuration,0,sizeof(TConfiguration));
	memset(&ConfigurationForCalib,0,sizeof(TConfiguration));
	memset(&Data,0,sizeof(TData));
	memset(&ID,0,sizeof(TID));
	memset(&GPOCon,0,sizeof(TGPOCon));
	memset(&Offset,0,sizeof(TOffset));
	memset(&FullScale,0,sizeof(TFullScale));

	memset(&AcquisitionManage,0,sizeof(TAcquisitionManage));

	// parametri da modificare

	Mode.CLK1    = 1; // Internal 4.92 MHz clock. Pin MCLK2 is tristated.
	Mode.DAT_STA = 1; // This bit enables the transmission of status register contents after each data register read.

	Mode.FS = 48;

	if(Mode.FS >= 15)
	{ // 4800 / 15 = 320 Hz, fino a 320 Hz e' meglio usare sync 3
		Mode.SINC3   = 1; //
	}
	else
	{
		Mode.SINC3   = 0; //
	}

	// AVG1 - AVG0 - Media
	//  0   -  0   -  NO
	//  0   -  1   -  2 valori
	//  1   -  0   -  8 valori
	//  1   -  1   - 16 valori
	Mode.AVG1    = 1;
	Mode.AVG0    = 0;

	Configuration.Chop = 1; // filtro per il drift di default = 0

	//-------------------------------------------
	// Parametri utente
	//-------------------------------------------
	AcquisitionManage.AcquisitionMode = AcquisitionMode;
	//AcquisitionManage.AcquisitionMode = Differential;
	AcquisitionManage.ChannelNumberSingleEnded  = ChannelNum4;
	AcquisitionManage.ChannelNumberDifferential = ChannelNum4;
	AcquisitionManage.GainSel = GainSelection;

	// valore da salvare in flash
	// ReferenceValueRefin_1 e' quello regolabile con il trimmer, schema VREF_ADC_1
	//AcquisitionManage.ReferenceValueRefin_1 = 4.960f;
	AcquisitionManage.ReferenceValueRefin_1 = 4.10f;

	// valore da salvare in flash
	// ReferenceValueRefin_2 e' quello fisso generato da IC8
	AcquisitionManage.ReferenceValueRefin_2 = 4.9899f;


	//Configuration.BUF = 1; // Enables the buffer on the analog inputs
	//-------------------------------------------
	// 5V tensione di riferimento
	// G2 - G1 - G0 - GAIN - ADC input Range
	//  0 -  0 -  0 -  1   - +- 5V
	//  0 -  1 -  1 -  8   - +- 625mV
	//  1 -  0 -  0 -  16  - +- 312.5mV
	//  1 -  0 -  1 -  32  - +- 156.2mV
	//  1 -  1 -  0 -  64  - +- 78.125mV
	//  1 -  1 -  1 -  128 - +- 39.06mV
	//-------------------------------------------
	GainSelector(&Configuration,&AcquisitionManage);

	//------------------------------------------------------------------
	// abilita o disabilita la possibilita' di pilotare il LED rosso sulla scheda ADC che serve per una diagnostica
	GPOCon.GP32EN = 1; // Digital Output P3 and Digital Output P2 enable
	//------------------------------------------------------------------

	// parametri da NON modificare!!!
	switch(AcquisitionManage.AcquisitionMode)
	{
		case Single_ended:
		{
									  // 0 - External reference applied between REFIN1(+) and REFIN1(−).
			Configuration.REFSEL = 1; // 1 - External reference applied between the P1/REFIN2(+) and P0/REFIN2(−) pins.
			Configuration.Pseudo = 1;
			Configuration.U_B = 1; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_2;
			SingleEndedChannelSet();
		}break;
		case Differential:
		{
			Configuration.REFSEL = 0;
			Configuration.Pseudo = 0;
			Configuration.U_B = 0; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_1;
			DifferentialChannelSet();
		}break;
		default:
		{
			Configuration.REFSEL = 1;
			Configuration.Pseudo = 1;
			Configuration.U_B = 1; //When this bit is set, unipolar operation is selected.
			//AcquisitionManage.Reference = Refin_1;
			AcquisitionManage.ReferenceValue = AcquisitionManage.ReferenceValueRefin_2;
			SingleEndedChannelSet();
		}
	}

    //----------------------------------------
    // RESET AD
    for(i = 0 ; i < 40 ; i++)
    {
    	GPIO_set_ADC_SCLK(WRITE_0);
    	GPIO_set_ADC_DIN(WRITE_1);
    	GPIO_set_ADC_SCLK(WRITE_1);
    }
    ROM_SysCtlDelay(500*MICRO_DELAY);
    //----------------------------------------

    //----------------------------------------
    // STRUTTURE PER CALIBRAZIONE
    ConfigurationForCalib = Configuration;
    ModeForCalib          = Mode;
    //----------------------------------------

    AD7193_WriteConfigurationRegister(&Configuration);
    AD7193_WriteModeRegister(&Mode);

	return 0;
}

long GainSelector(TConfiguration *Config, TAcquisitionManage *AcqManage)
{
	switch(AcqManage->GainSel)
	{
		case Gain1:
		{
			Config->gain    = 0;
			Config->BUF     = 0;
			AcqManage->Gain = 1;
		}
		break;
		case Gain8:
		{
			Config->gain    = 3;
			Config->BUF     = 1;
			AcqManage->Gain = 8;
		}
		break;
		case Gain16:
		{
			Config->gain    = 4;
			Config->BUF     = 1;
			AcqManage->Gain = 16;
		}
		break;
		case Gain32:
		{
			Config->gain    = 5;
			Config->BUF     = 1;
			AcqManage->Gain = 32;
		}
		break;
		case Gain64:
		{
			Config->gain    = 6;
			Config->BUF     = 1;
			AcqManage->Gain = 64;
		}
		break;
		case Gain128:
		{
			Config->gain    = 7;
			Config->BUF     = 1;
			AcqManage->Gain = 128;
		}
		break;
		default:
		{
			Config->gain    = 0;
			Config->BUF     = 0;
			AcqManage->Gain = 1;
		}
	}

	return 0;
}

long AD7193_ReadOffsetRegister(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW = 1;
	RegisterSelection(Offset_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Offset_register;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_24;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	// Aspetto che il registro sia letto
	WaitSemaphore(&sem_ADC);
	ReleaseSemaphore(&sem_ADC);

	return 0;
}

long AD7193_ReadFullScaleRegister(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW = 1;
	RegisterSelection(Full_scale_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Full_scale_register;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_24;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	// Aspetto che il registro sia letto
	WaitSemaphore(&sem_ADC);
	ReleaseSemaphore(&sem_ADC);

	return 0;
}

long AD7193_WriteModeRegister(TMode *Mode)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(Mode_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Mode_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_24;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = Mode->ModeAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}

long AD7193_WriteConfigurationRegister(TConfiguration *Configuration)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(Configuration_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Configuration_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_24;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = Configuration->ConfigurationAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}

long AD7193_LED_ON(void)
{
	WaitSemaphore(&sem_ADC);

	GPOCon.P3DAT = 1; // Digital Output P3

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(GPOCON_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = GPOCON_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_8;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = GPOCon.GPOConAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}

long RegisterSelection(ERegisterSelection RegisterSelection)
{
	switch(RegisterSelection)
	{
		case Communications_register_during_a_write_operation:
		{
			Communications.RS0 = 0;
		    Communications.RS1 = 0;
			Communications.RS2 = 0;
		}break;
		case Status_register_during_a_read_operation:
		{
			Communications.RS0 = 0;
		    Communications.RS1 = 0;
			Communications.RS2 = 0;
		}break;
		case Mode_register:
		{
			Communications.RS0 = 1;
		    Communications.RS1 = 0;
			Communications.RS2 = 0;
		}break;
		case Configuration_register:
		{
			Communications.RS0 = 0;
		    Communications.RS1 = 1;
			Communications.RS2 = 0;
		}break;
		case Data_register_data_register_plus_status_information:
		{
			Communications.RS0 = 1;
		    Communications.RS1 = 1;
			Communications.RS2 = 0;
		}break;
		case ID_register:
		{
			Communications.RS0 = 0;
		    Communications.RS1 = 0;
			Communications.RS2 = 1;
		}break;
		case GPOCON_register:
		{
			Communications.RS0 = 1;
		    Communications.RS1 = 0;
			Communications.RS2 = 1;
		}break;
		case Offset_register:
		{
			Communications.RS0 = 0;
		    Communications.RS1 = 1;
			Communications.RS2 = 1;
		}break;
		case Full_scale_register:
		{
			Communications.RS0 = 1;
		    Communications.RS1 = 1;
			Communications.RS2 = 1;
		}break;
		default:{};
	}

	return 0;
}

// To enable continuous read, Instruction 01011100 must be written to the
// communications register. To disable continuous read, Instruction 01011000 must be written to the communications
// register while the RDY pin is low.
long AD7193_Enable_Continuous_Read(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 1;
	RegisterSelection(Data_register_data_register_plus_status_information);
	Communications.CREAD = 1;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Data_register_data_register_plus_status_information;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	WaitSemaphore(&sem_ADC);

	SPI_Continuous_Read_Enable();

	AcquisitionManage.ContinousReadAD = 1;

	return 0;
}

long AD7193_Disable_Continuous_Read(void)
{
	// se non è abilitata la modalità continua esco
	if(AcquisitionManage.ContinousReadAD == 0)
		return 0;

	AcquisitionManage.WaitDisableInterruptAD = 1;
	while(AcquisitionManage.WaitDisableInterruptAD);
	while(GPIO_get_ADC_DOUT() == 1);
	// ora posso disabilitare la lettura

	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 1;
	RegisterSelection(Data_register_data_register_plus_status_information);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Data_register_data_register_plus_status_information;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	AcquisitionManage.ContinousReadAD = 0;

	return 0;
}

/*
long AD7193_ReadStatusRegister(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW = 1;
	RegisterSelection(Status_register_during_a_read_operation);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Status_register_during_a_read_operation;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_8;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	// Aspetto che il registro sia letto
	WaitSemaphore(&sem_ADC);
	ReleaseSemaphore(&sem_ADC);

	return 0;
}
*/

/*
long AD7193_ReadModeRegister(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW = 1;
	RegisterSelection(Mode_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = Mode_register;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_24;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	// Aspetto che il registro sia letto
	WaitSemaphore(&sem_ADC);
	ReleaseSemaphore(&sem_ADC);

	return 0;
}
*/

/*
long AD7193_ReadDataRegisterWithoutCommRegister(void)
{
	WaitSemaphore(&sem_ADC);

	//------------------------------------------------------------------
	SPI.RegisterSelection = Data_register_data_register_plus_status_information;
	SPI.RnW               = 1;
	SPI.COMM_counter      = WORD_NONE;
	SPI.RD_counter        = WORD_32;
	SPI.WR_counter        = WORD_NONE;
	//------------------------------------------------------------------

	// abilitazione interrupt gestione SPI
	SPI_Read_Timer_Enable();

	// Aspetto che il registro sia letto
	WaitSemaphore(&sem_ADC);
	ReleaseSemaphore(&sem_ADC);

	return 0;
}
*/

/*
long AD7193_LED_OFF(void)
{
	WaitSemaphore(&sem_ADC);

	GPOCon.P3DAT = 0; // Digital Output P3

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(GPOCON_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = GPOCON_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_8;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = GPOCon.GPOConAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}
*/

/*
long AD7193_REL1_ON(void)
{
	WaitSemaphore(&sem_ADC);

	GPOCon.P2DAT = 1; // Digital Output P2

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(GPOCON_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = GPOCON_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_8;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = GPOCon.GPOConAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}
*/

/*
long AD7193_REL1_OFF(void)
{
	WaitSemaphore(&sem_ADC);

	GPOCon.P2DAT = 0; // Digital Output P2

	//------------------------------------------------------------------
	Communications.nWEN = 0;
	Communications.RnW  = 0;
	RegisterSelection(GPOCON_register);
	Communications.CREAD = 0;
	//------------------------------------------------------------------

	//------------------------------------------------------------------
	SPI.RegisterSelection = GPOCON_register;
	SPI.RnW               = 0;
	SPI.COMM_counter      = WORD_8;
	SPI.RD_counter        = WORD_NONE;
	SPI.WR_counter        = WORD_8;
	//------------------------------------------------------------------

	SPI.DataW.DataSPIAll = GPOCon.GPOConAll;

	// abilitazione interrupt gestione SPI
	SPI_WriteCommunication_Timer_Enable();

	return 0;
}
*/
