/** @file testapci3200_cjc.c

read raw CJC related values and output them

@par LICENCE
@verbatim
Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.

ADDI-DATA GmbH
Dieselstrasse 3
D-77833 Ottersweier
Tel: +19(0)7223/9493-0
Fax: +49(0)7223/9493-92
http://www.addi-data-com
info@addi-data.com

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

You shoud also find the complete GPL in the COPYING file
accompanying this source code.
@endverbatim
*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <sys/sysmacros.h> /* major() minor() */
#define NDEBUG
#include <assert.h>
#include <apci3200.h>
#include "convert.h"
#include "findboards.h"
#include "input.h"
#include "errorlib.h"
#include "errormsg.h"

#ifdef WITH_PROMPT
#define _get_integer get_integer
#else
#define _get_integer get_integer_noprompt
#endif

/** Time to wait with sleep function */
#define WAIT_MILLISECONDS	250000
//--------------------------------------------------------------------------------
/** this function look up for cards in the /proc/sys/apci3200/ directory
* @param cards A pointer to the card area to fill
* @return The number of cards detected (may be zero if nor cards found).
*/
int apci3200_find_cards(int ** cards)
{
	return apci_find_boards("apci3200", cards);
}
//--------------------------------------------------------------------------------
int verbose=0;
//--------------------------------------------------------------------------------
/* utility function to convert numerical unit value in symbol */
const char* unit2symb(unsigned int val)
{
	switch(val)
	{
	case APCI3200_NANOVOLT:
		return "nV";
	case APCI3200_MICROVOLT:
		return "uV";
	case APCI3200_MILLIVOLT:
		return "mV";
	case APCI3200_VOLT:
		return "V";
	case APCI3200_NANOAMPERE:
		return "nA";
	case APCI3200_MICROAMPERE:
		return "uA";
	case APCI3200_MILLIAMPERE:
		return "mA";
	case APCI3200_AMPERE:
		return "A";
	default:
		return "?";
	}
}

//--------------------------------------------------------------------------------

int call_CMD_APCI3200_InitAnalogInputChannel(int fd, int ch, struct InitAnalogInputChannel_t* ChannelInit)
{
	ChannelInit->b_Channel = ch;

#ifdef WITH_PROMPT
	printf("polarity [unipolar:%d bipolar:%d]",APCI3200_POLARITY_UNIPOLAR,APCI3200_POLARITY_BIPOLAR);
#endif
	ChannelInit->b_PolaritySelected = _get_integer(APCI3200_POLARITY_UNIPOLAR,APCI3200_POLARITY_BIPOLAR);

	if(ChannelInit->b_PolaritySelected==APCI3200_POLARITY_BIPOLAR)
		ChannelInit->w_GainSelected = 0;
	else
	{
#ifdef WITH_PROMPT
		printf("value\tgain:\n");
		printf("0\t1\n");
		printf("1\t2\n");
		printf("2\t4\n");
		printf("3\t8\n");
		printf("4\t16\n");
		printf("5\t32\n");
		printf("6\t64\n");
		printf("7\t128\n");
		printf("choice");
#endif
		ChannelInit->w_GainSelected = _get_integer(APCI3200_GAIN_1,APCI3200_GAIN_128);
	}

	// On one module the connection type has to be the same.
	// One module can have 4 single channels or 2 differential
	// channels.

	// If you chose to use one channel in differential,
	// you have to use all channels from this module in
	// differential mode!

#ifdef WITH_PROMPT
	printf("connection type [single:%d differential:%d]",APCI3200_CONNECTION_TYPE_SINGLE,APCI3200_CONNECTION_TYPE_DIFFERENTIAL);
#endif
	ChannelInit->b_DiffSingSelected = _get_integer(0,1);

	if(verbose) printf("=> CMD_APCI3200_InitAnalogInputChannel on input %i\n", ChannelInit->b_Channel);
	if ( call_ioctl (fd,CMD_APCI3200_InitAnalogInputChannel, ChannelInit))
		return -1;
	return 0;
}
//--------------------------------------------------------------------------------
int ask_frequence(void)
{
#ifdef WITH_PROMPT
	printf("acquisition frequence ?\n");
	printf("1: 20Hz/50ms\n");
	printf("2: 40Hz/25ms\n");
	printf("3: 80Hz/12.5ms\n");
	printf("4: 160Hz/6.25ms\n");
#endif
	return _get_integer(1,4);
}
//--------------------------------------------------------------------------------
int call_CMD_APCI3200_ReadCJCValue(int fd, unsigned long Frequence, unsigned long* dw_CJCValue)
{
	struct Read1CJCInputChannel_t read;

	read.dw_TimerReloadValue = Frequence;
	read.b_ConvertingTimeUnit = APCI3200_UNIT_HZ;
	read.dw_ChannelValue = 0;		// will be the channel value

	if(verbose) printf("=> CMD_APCI3200_ReadCJCValue\n");
	{
		if ( call_ioctl (fd,CMD_APCI3200_ReadCJCValue, &read))
			return -1;

		printf("CJC input value = %lu \n", read.dw_ChannelValue);
		*dw_CJCValue = read.dw_ChannelValue;
	}
	return 0;
}
//--------------------------------------------------------------------------------
void dump_sensor(unsigned long SensorClass, unsigned long SensorType, unsigned long RTDValue)
{
	switch(SensorClass)
	{
	case ADDIDATA_THERMOCOUPLE: /* */
		printf("termocouple ");
		switch(SensorType)
		{
		case 0:
			printf("type B\n");
			break;
		case 1:
			printf("type E\n");
			break;
		case 2:
			printf("type J\n");
			break;
		case 3:
			printf("type K\n");
			break;
		case 4:
			printf("type N\n");
			break;
		case 5:
			printf("type R\n");
			break;
		case 6:
			printf("type S\n");
			break;
		case 7:
			printf("type T\n");
			break;
		default:
			printf("UNKNOWN");
		}
		break;
	case ADDIDATA_RTD:
		switch(SensorType)
		{
			case 0:
				printf("PT\n");
				break;
			case 1:
				printf("Ni\n");
				break;
			default:
				printf("UNKNOWN\n");
				break;
		}
		break;
	default:
		printf("class UNKNOWN\n");
	}
}
//--------------------------------------------------------------------------------
void ask_SensorType(int ch, unsigned long* SensorClass, unsigned long* SensorType, unsigned long* RTDValue)
{
#ifdef WITH_PROMPT
	printf("channel %d: class of sensor [0: Thermocouple 1:RTD]\n",ch);
#endif
	*SensorClass=_get_integer(0,1);

	switch(*SensorClass)
	{
	case ADDIDATA_THERMOCOUPLE: /* */
#ifdef WITH_PROMPT
		printf("\n");
		printf("0: type B\n");
		printf("1: type E\n");
		printf("2: type J\n");
		printf("3: type K\n");
		printf("4: type N\n");
		printf("5: type R\n");
		printf("6: type S\n");
		printf("7: type T\n");
#endif
		*SensorType=_get_integer(0,7);
		break;
	case ADDIDATA_RTD:
		printf("0: type PT 1: type Ni");
		*SensorType = _get_integer(0,1);
		{
			int tmp;
			printf("RTD Value [0:100 1:1000]");
			tmp=_get_integer(0,1);
			switch(tmp)
			{
			case 0:
				*RTDValue = 100;
				break;
			case 1:
				*RTDValue = 1000;
			default:
				assert(0);
			}
		}
		break;
	}
}
//--------------------------------------------------------------------------------
int call_CMD_APCI3200_ReadCJCCalibrationGainValue(int fd, unsigned long Frequence,unsigned long* dw_CJCGainValue)
{
	struct Read1CJCInputChannel_t read;

	read.dw_TimerReloadValue = Frequence;
	read.b_ConvertingTimeUnit = APCI3200_UNIT_HZ;
	read.dw_ChannelValue = 0;		// will be the channel value

	if(verbose) printf("=> CMD_APCI3200_ReadCJCCalibrationGainValue\n");
	{
		if ( call_ioctl (fd,CMD_APCI3200_ReadCJCCalibrationGainValue, &read))
			return -1;

		printf("CJC gain input value = %lu \n", read.dw_ChannelValue);
		*dw_CJCGainValue = read.dw_ChannelValue;
	}
	return 0;
}
//--------------------------------------------------------------------------------
int call_CMD_APCI3200_ReadCJCCalibrationOffsetValue(int fd, unsigned long  Frequence,unsigned long* dw_CJCOffsetValue)
{
	struct Read1CJCInputChannel_t read;

	read.dw_TimerReloadValue = Frequence;
	read.b_ConvertingTimeUnit = APCI3200_UNIT_HZ;
	read.dw_ChannelValue = 0;		// will be the channel value

	if(verbose) printf("=> CMD_APCI3200_ReadCJCCalibrationOffsetValue\n");
	{
		if ( call_ioctl (fd,CMD_APCI3200_ReadCJCCalibrationOffsetValue, &read))
			return -1;

		printf("CJC offset input value = %lu \n", read.dw_ChannelValue);
		*dw_CJCOffsetValue = read.dw_ChannelValue;
	}
	return 0;
}
//--------------------------------------------------------------------------------
int apci3200_test_read_cjc(int fd, int ch)
{
	unsigned long dw_CJCValue;				// CJC Value
	unsigned long dw_CJCOffsetValue;		// CJC Offset
	unsigned long dw_CJCGainValue;			// CJC Gain

	/* configuration */
	struct InitAnalogInputChannel_t ChannelInit;
	unsigned long Frequence;				//
	unsigned long SensorClass;
	unsigned long SensorType;
	unsigned long RTDValue;

	ask_SensorType(ch, &SensorClass, &SensorType, &RTDValue);
	Frequence = ask_frequence();

	if(call_CMD_APCI3200_InitAnalogInputChannel(fd, ch, &ChannelInit))
		return -1;

#ifdef WITH_PROMPT
	printf("\n");
#endif
	// If the sensor type is a thermocouple, CJC values have to be read.
	if(SensorClass== ADDIDATA_THERMOCOUPLE)
		if( call_CMD_APCI3200_ReadCJCValue(fd, Frequence, &dw_CJCValue) )
			return -1;

	// If the sensor type is a thermocouple, CJC values have to be read.

	if( call_CMD_APCI3200_ReadCJCCalibrationGainValue(fd, Frequence,&dw_CJCGainValue) )
		return -1;

	// If the sensor type is a thermocouple, CJC values have to be read.
	if( call_CMD_APCI3200_ReadCJCCalibrationOffsetValue(fd, Frequence, &dw_CJCOffsetValue) )
		return -1;

	{ printf("sensor: "); dump_sensor(SensorClass, SensorType, RTDValue); };

	return 0;
}

//--------------------------------------------------------------------------------
int run_test(int fd)
{
	int channel;
#ifdef WITH_PROMPT
	printf("channel number>");
#endif
	channel = _get_integer(0,15);
	return apci3200_test_read_cjc(fd, channel);
}
//--------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	int * apci3200_card_fd;

	unsigned int apci3200_card_number = 0;
	{
		apci3200_card_number = apci3200_find_cards(&apci3200_card_fd);

		printf("total: %d cards\n",apci3200_card_number);
	}

	{
		int index;
		switch(apci3200_card_number)
		{
		case 1:
			index = 0;
			break;
		case 0:
			exit(0);
		default:
#ifdef WITH_PROMPT
			printf("board>");
#endif
			index = _get_integer(0,apci3200_card_number-1);
		}
		return run_test(apci3200_card_fd[index]);
	}
	return 0;
}
//--------------------------------------------------------------------------------
