/***************************************************************************************************************:')

U3Config.cpp

Main functions for the Labjack U3 handling.

Emilie Jude
Nassima Bouchelit
Fabrice Le Bars
Arunas Mazeika
Stéphane Bazeille
Some functions and parts of functions are from the file u3.c and the examples provided by www.labjack.com

2006-2007

Version 1.0.0

***************************************************************************************************************:)*/

#include "U3Config.h"

/*
Error handling function that is called after every Labjack function call.
This function displays the errorcode and string description of the error.
It also has a line number input that can be used with the macro __LINE__ to 
display the line number in source code that called the error handler.
It also has an iteration input that is useful when processing results in a loop (getfirst/getnext).

LJ_ERROR lngErrorcode : (IN) error code returned by a Labjack function
long lngLineNumber : (IN) should be __LINE__
long lngIteration : (IN) current iteration when processing results in a loop (getfirst/getnext)

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int ErrorHandler (LJ_ERROR lngErrorcode, long lngLineNumber, long lngIteration)	{

	char err[255];

	if (lngErrorcode != LJE_NOERROR)	{
		ErrorToString(lngErrorcode,err);
		fprintf(stdout, "Error number = %d\n", lngErrorcode);
		fprintf(stdout, "Error string = %s\n", err);
		fprintf(stdout, "Source line number = %d\n", lngLineNumber);
		fprintf(stdout, "Iteration = %d\n\n", lngIteration);
		if(lngErrorcode > LJE_MIN_GROUP_ERROR)	{
			//Quit if this is a group error.
			//getchar();
			//exit(0);
		}
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}

/*
Opens the first found LabJack U3.

LJ_HANDLE* pHandle : (OUT) pointer to an identifier representing the device

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3Open(LJ_HANDLE* pHandle)	{

	LJ_ERROR lngErrorcode; // Variable used to store the error code

	// Opens the first found LabJack U3.
	lngErrorcode = OpenLabJack(LJ_dtU3, LJ_ctUSB, "1", 1, pHandle);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	return EXIT_SUCCESS;
}

/*  
Resets all U3 ports to their default configuration.  
This is recommended before using the U3 to ensure its ports are in the proper state. 

LJ_HANDLE pHandle : (IN) identifier representing the device

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3Reset(LJ_HANDLE lngHandle) {

	LJ_ERROR lngErrorcode; // Variable used to store the error code

	// Start by using the pin_configuration_reset IOType so that all
	// pin assignments are in the factory default condition.
	lngErrorcode = ePut(lngHandle, LJ_ioPIN_CONFIGURATION_RESET, 0, 0, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	return EXIT_SUCCESS;
}

/*
Outputs a PWM (freq_syst = 24 MHz and freq_PWM = freq_syst/(timer_clock_divisor * 2^16)) on FIO0.

LJ_HANDLE pHandle : (IN) identifier representing the device
int timer_clock_divisor : (IN) divisor of the frequency
int timer_duty_cycle0 : (IN) value setting the duty cycle of Timer0 (between 0 and 65535)

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3ConfigTimers(LJ_HANDLE lngHandle, int timer_clock_divisor, int timer_duty_cycle)	{

	// Used to get the results of the different requests
	long lngGetNextIteration = 0, lngIOType = 0, lngChannel = 0; 
	double dblValue = 0;
	LJ_ERROR lngErrorcode; // Variable used to store the error code

	// First requests to configure the timer and counter. These will be
	// done with and add/go/get block.

	// Sets the timer/counter pin offset to 0, which will put the first
	// timer/counter on FIO0.
	lngErrorcode = AddRequest (lngHandle,  LJ_ioPUT_CONFIG, LJ_chTIMER_COUNTER_PIN_OFFSET, 0, 0, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	// Enables one timer. It will use FIO0
	AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chNUMBER_TIMERS_ENABLED, 1, 0, 0);

	// Makes sure Counter0 is disabled.
	AddRequest (lngHandle, LJ_ioPUT_COUNTER_ENABLE, 0, 0, 0, 0);

	// Makes sure Counter1 is disabled.
	AddRequest (lngHandle, LJ_ioPUT_COUNTER_ENABLE, 1, 0, 0, 0);


	// All output timers use the same timer clock, configured here. The
	// base clock is set to 24MHZ_DIV, meaning that the clock divisor
	// is supported and Counter0 is not available.
	//AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc4MHZ_DIV, 0, 0);
#ifdef OLD_HARDWARE_VERSION
	AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc24MHZ_DIV, 0, 0);
#else
	AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_BASE, LJ_tc48MHZ_DIV, 0, 0);
#endif // OLD_HARDWARE_VERSION
	// Sets the timer clock divisor
	AddRequest (lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, timer_clock_divisor, 0, 0);
	// Configures Timer0 as 16-bit PWM.
	AddRequest (lngHandle, LJ_ioPUT_TIMER_MODE, 0, LJ_tmPWM16, 0, 0);
	// Initializes the 16-bit PWM with a duty cycle.
	AddRequest (lngHandle, LJ_ioPUT_TIMER_VALUE, 0, timer_duty_cycle, 0, 0);

	// Executes the requests.
	lngErrorcode = GoOne (lngHandle);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	// Gets all the results just to check for errors.
	lngErrorcode = GetFirstResult(lngHandle, &lngIOType, &lngChannel, &dblValue, 0, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);
	lngGetNextIteration = 0;	// Used by the error handling function.
	while (lngErrorcode < LJE_MIN_GROUP_ERROR)	{

		lngErrorcode = GetNextResult(lngHandle, &lngIOType, &lngChannel, &dblValue, 0, 0);
		if (lngErrorcode != LJE_NO_MORE_DATA_AVAILABLE)	{
			ErrorHandler(lngErrorcode, __LINE__, lngGetNextIteration);
		}

		lngGetNextIteration++;
	}

	// Changes Timer0 duty cycle
	lngErrorcode = ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, 0, timer_duty_cycle, 0);

	// Changes Timer0 timer clock divisor
	lngErrorcode = ePut(lngHandle, LJ_ioPUT_CONFIG, LJ_chTIMER_CLOCK_DIVISOR, timer_clock_divisor, 0);

	return EXIT_SUCCESS;
}

/*
Gets the temperature (in Kelvin) in the device.

LJ_HANDLE pHandle : (IN) identifier representing the device
double* pTemperature : (OUT) pointer receiving the value of the temperature

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3GetTemperature(LJ_HANDLE lngHandle, double* pTemperature)	{

	LJ_ERROR lngErrorcode; // Variable used to store the error code

	//lngErrorcode = eAIN(lngHandle, 30, 0, pTemperature, -1, -1, -1, 0, 0, 0);
	lngErrorcode = eGet(lngHandle, LJ_ioGET_AIN, 30, pTemperature, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	return EXIT_SUCCESS;
}

/*
Reads the voltage from AINX, X = Channel.

LJ_HANDLE pHandle : (IN) identifier representing the device
long Channel : (IN) port to use
double* pVoltage : (OUT) pointer receiving the value of the voltage

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3GetVoltage(LJ_HANDLE lngHandle, long Channel, double* pVoltage)	{

	LJ_ERROR lngErrorcode; // Variable used to store the error code

	// Configures FIOX as an analog input (AINX)
	lngErrorcode = ePut(lngHandle, LJ_ioPUT_ANALOG_ENABLE_BIT, Channel, 1, 0);
	// Reads the voltage on it
	lngErrorcode = eGet(lngHandle, LJ_ioGET_AIN, Channel, pVoltage, 0);
	// You can also just do this instead of the 2 previous lines
	//	lngErrorcode = eAIN (lngHandle, Channel, 0, pVoltage, -1, -1, -1, 0, 0, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	return EXIT_SUCCESS;
}

/*
Outputs a voltage at DACX, X = Channel.

LJ_HANDLE pHandle : (IN) identifier representing the device
long Channel : (IN) port to use
double voltage : (IN) value of the voltage to output

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3SetVoltage(LJ_HANDLE lngHandle, long Channel, double voltage)	{

	LJ_ERROR lngErrorcode; // Variable used to store the error code

	lngErrorcode = ePut(lngHandle, LJ_ioPUT_DAC, Channel, voltage, 0);
	ErrorHandler(lngErrorcode, __LINE__, 0);

	return EXIT_SUCCESS;
}

/*
Modify the timer_duty_cycle .

LJ_HANDLE* pHandle : (IN,OUT) pointer to an identifier representing the device

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3ModifyDutyCycle(LJ_HANDLE lngHandle, int timer_duty_cycle, int num_timer)	{

	ePut(lngHandle, LJ_ioPUT_TIMER_VALUE, num_timer, timer_duty_cycle, 0);

	return EXIT_SUCCESS;
}

/*
Closes the device.

LJ_HANDLE* pHandle : (IN,OUT) pointer to an identifier representing the device

Returns : EXIT_SUCCESS or EXIT_FAILURE if there is an error
*/
int U3Close(LJ_HANDLE* pHandle)	{


	return EXIT_SUCCESS;
}


