/** @file apci3200-kapi.h

   Contains Kernel API of the APCI-3200.

   @par CREATION
   @author Krauth Julien
   @date   06.06.05

   @par VERSION
   @verbatim
   $LastChangedRevision: 128 $
   $LastChangedDate: 2005-11-18 14:51:33 +0100 (Fri, 18 Nov 2005) $
   @endverbatim

   @par COMPILER
   @verbatim
   Compiler	: gcc
   Version	: gcc (GCC) 3.3.6 (Debian 1:3.3.6-5)
   kernel	: 2.4.26
   @endverbatim

   @par UPDATES
   @verbatim
   Date			:
   Author		:
   Description	:
   @endverbatim

   @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 library is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2.1 of the License,
   or (at your option) any later version.

   This library 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 Lesser General Public License for more details.

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

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


#ifndef __APCI3200_KAPI_H__
#define __APCI3200_KAPI_H__


#include "apci.h"

#ifndef __KERNEL__
#error This header is intended for use in kernel context only
#endif

#ifdef __KERNEL__

/** Enable and set the interrupt routine.
 *
 * @param [in] pdev              : The device to initialize.
 * @param [in] InterruptCallback : The user interrupt callback.
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The interrupt callback is NULL.
 */
int i_APCI3200_SetBoardIntRoutine  (struct pci_dev * pdev, VOID (*InterruptCallback) (DWORD minor, DWORD mask, DWORD *value));

/** Disable and reset the interrupt routine.
 *
 * @param [in] pdev              : The device to initialize.
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 */
int i_APCI3200_ResetBoardIntRoutine (struct pci_dev * pdev);

/** Initialise scan module sensor type.
 *
 * @param [in] pdev				: The device to initialize.
 * @param [in] w_Module			: The module to use (0 to 3).
 * @param [in] b_SensorType		: ADDIDATA_THERMOCOUPLE or ADDIDATA_RTD.
 * @param [in] *b_SensorValue	: Thermocouple types: <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_B <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_E <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_J <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_K <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_N <br>
 * 									ADDIDATA_THERMOCOUPLE_TYPE_R <br>
 *									ADDIDATA_THERMOCOUPLE_TYPE_S <br>
 *									ADDIDATA_THERMOCOUPLE_TYPE_T <br>
 *
 * 								 RTD types: <br>
 * 									ADDIDATA_RTD_TYPE_PT <br>
 * 									ADDIDATA_RTD_TYPE_Ni
 *
 * @param [in] b_DiffSingSelected	:  Connection type:<br>
 * 									   if ADDIDATA_THERMOCOUPLE:
 *                                          - APCI3200_CONNECTION_TYPE_SINGLE<br>
 *                                          - APCI3200_CONNECTION_TYPE_DIFFERENTIAL
 * 									   if ADDIDATA_RTD:
 * 											- APCI3200_CONNECTION_TYPE_DIFFERENTIAL
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: The sensor parameter is wrong.
 *
 * @warning: this is an API change. previous version implicitely set APCI3200_CONNECTION_TYPE_SINGLE for ADDIDATA_THERMOCOUPLE
 */
int i_APCI3200_InitScanModuleAcquisitionSensor (struct pci_dev *pdev, WORD w_Module, BYTE b_SensorType, BYTE b_SensorValue[4], BYTE b_DiffSingSelected);

/** Initialise the scan.
 *
 * @param [in] pdev					: The device to initialize.
 * @param [in] w_Module				: The module to use (0 to 3).
 * @param [in] dw_ConversionTime	: Conversion time for each channels: <br>
 * 									  in Hz : 20 - 40 - 80 - 160
 *
 * @param [in] b_SCANTimeMode		: Define the mode of the delay: <br>
 * 										ADDIDATA_DELAY_NOT_USED: The delay between two SCANs is not used <br>
 * 										ADDIDATA_DELAY_MODE1_USED: The delay between two SCANs is used. <br>
 * 										The conversion is started at once, and the delay is used after the first SCAN.
 * @param [in] dw_SCANTime			: Total time of the SCAN (including delay).
 *
 * @param [in] b_SCANTimeUnit		: APCI3200_MS (millisecond) or APCI3200_S (second)
 *
 * @param [in] b_SCANMode			: ADDIDATA_SINGLE_SCAN or ADDIDATA_CONTINUOUS_SCAN.
 *
 * @param [in] b_ExternTriggerMode	: External Trigger action: <br>
 * 			 						  APCI3200_DISABLE <br>
 * 									  APCI3200_FIRST_LOW_EDGE_START_ALL_SCAN <br>
 * 									  APCI3200_FIRST_HIGH_EDGE_START_ALL_SCAN <br>
 * 									  APCI3200_FIRST_EDGE_START_ALL_SCAN
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: Scan not initialized.
 * @retval 4: Wrong conversion time value.
 * @retval 5: Wrong scan time mode.
 * @retval 6: Wrong scan time unit value.
 * @retval 7: Wrong scan time value.
 * @retval 8: Wrong trigger mode.
 */
int i_APCI3200_InitScanModuleAcquisition (struct pci_dev *pdev,
										  WORD w_Module,
										  DWORD dw_ConversionTime,
										  BYTE b_SCANTimeMode,
										  DWORD dw_SCANTime,
										  BYTE b_SCANTimeUnit,
										  BYTE b_SCANMode,
										  BYTE b_ExternTriggerMode);

/** Start scan module.
 *
 * @param [in] pdev				: The device to initialize.
 * @param [in] w_Module			: The module to use (0 to 3).
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: Scan not initialized.
 * @retval 4: Scan already started.
 * @retval 5: Scan can't be started.
 */
int i_APCI3200_StartScanModuleAcquisition (struct pci_dev *pdev, WORD w_Module);

/** Stop scan module.
 *
 * @param [in] pdev				: The device to initialize.
 * @param [in] w_Module			: The module to use (0 to 3).
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The module parameter is wrong.
 * @retval 3: Scan not initialized.
 * @retval 4: Scan not started.
 * @retval 5: Scan can't be stopped.
 */
int i_APCI3200_StopScanModuleAcquisition (struct pci_dev *pdev, WORD w_Module);

/** Get the number of analog input channels.
 *
 * Return the number of analog input channels.
 * E.g.: For a board that has 4 modules, the number of channels
 * returned by this function will be 16.
 *
 * @param [in] pdev				: The device to use.
 * @param [in] b_SingleDiff		: The mode of the input channels APCI3200_CONNECTION_TYPE_DIFFERENTIAL or APCI3200_CONNECTION_TYPE_SINGLE.
 *
 * @param [out] b_NbrChannels	: The number of analog input channels.
 *
 * @retval 0: success.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Can't get the number of input channels.
 */
int i_APCI3200_GetNumberOfAnalogInputChannels (struct pci_dev *pdev, BYTE b_SingleDiff, BYTE *b_NbrChannels);

/** Get the APCI-3200 calibration values from the device structure.
 *
 * @param [in,out]	pdev					Pointer on the device structure.
 * @param [int]		channel_num				The channel on which value have to be read.
 * @param [int]		ConnectionType			The connection type:<br>
 *											- APCI3200_CONNECTION_TYPE_SINGLE<br>
 *											- APCI3200_CONNECTION_TYPE_DIFFERENTIAL
 * @param [int]		Gain					The agin to use:<br>
 *											- APCI3200_GAIN_1<br>
 *											- APCI3200_GAIN_2<br>
 *											- APCI3200_GAIN_4<br>
 *											- APCI3200_GAIN_8<br>
 *											- APCI3200_GAIN_16<br>
 *											- APCI3200_GAIN_32<br>
 *											- APCI3200_GAIN_128
 * @param [out]		CJCCurrentSource		The CJC current source value.
 * @param [out]		ChannelCurrentSource	The channel current source value.
 * @param [out]		ChannelGainFactor		The channel gain factor value.
 *
 * @retval			0						success.
 */
int i_APCI3200_GetChannelCalibrationValue (struct pci_dev *pdev,
											unsigned int channel_num,
											unsigned int ConnectionType,
											unsigned int Gain,
											unsigned long *CJCCurrentSource,
											unsigned long *ChannelCurrentSource,
											unsigned long *ChannelGainFactor);

/** please see the synonymous IOCTL functions */
int i_APCI3200_InitAnalogInputChannel(struct pci_dev *pdev, struct InitAnalogInputChannel_t *AnalogInputConfig);
int i_APCI3200_Read1AnalogInputChannel(struct pci_dev *pdev, struct Read1AnalogInputChannel_t *AnalogInputConfig);
int i_APCI3200_ReadCalibrationGainValue(struct pci_dev *pdev, struct Read1AnalogInputChannel_t *AnalogInputConfig);
int i_APCI3200_ReadCalibrationOffsetValue(struct pci_dev *pdev, struct Read1AnalogInputChannel_t *AnalogInputConfig);
int i_APCI3200_SetConvertingTime(struct pci_dev *pdev, uint8_t module, unsigned long dw_TimerReloadValue);

int i_APCI3200_Read1AnalogInputChannelFast (struct pci_dev *pdev, unsigned char channel, unsigned long *value);
int i_APCI3200_ReadCalibrationGainValueFast (struct pci_dev *pdev, unsigned char channel, unsigned long *value);
int i_APCI3200_ReadCalibrationOffsetValueFast (struct pci_dev *pdev, unsigned char channel, unsigned long *value);
int i_APCI3200_ReadCalibrationGainValueFast (struct pci_dev *pdev, unsigned char channel, unsigned long *value);
int i_APCI3200_ReadCJCValueFast(struct pci_dev *pdev, unsigned long *value);

/** Read the reference voltage for a given channel
*
* @param [in,out]	pdev	Pointer on the device structure.
* @param [in]		Channel	0 to 15 when unipolar, 0 to 7 when bipolar
* @param [out]		ReferenceVoltage 2500 mV or 1250 mV
* @param [out]		Unit always APCI3200_MILLIVOLT
*
* @retval 0			success.
* @retval -EINVAL	Incorrect parameter
*/
int i_APCI3200_ReadReferenceVoltage(struct pci_dev *pdev, uint8_t Channel, unsigned int* ReferenceVoltage, unsigned int* Unit);

/** Set / Reset the diagnostic mode.
 *
 * This function permits to enable disable diagnostic test.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 *
 * @param [in]		mode:
 *  					- APCI3200_DIAGNOSTIC_NONE:				Disable diagnostic test.
 * 						- APCI3200_DIAGNOSTIC_OPEN_CONNECTION:	Open connection test.
 * @param [in]		channel: The channel to test (single 0 - 15, differential 0 - 7).
 *
 * @retval 0		No error.
 * @retval -EINVAL	Incorrect parameter.
 */
int i_APCI3200_SetDiagnosticMode (struct pci_dev *pdev, unsigned char mode, unsigned char channel);

/** Get the diagnostic mode.
 *
 * This function permits to get the configured diagnostic test.
 *
 * @param [in,out]	pdev	Pointer on the device structure.
 * @param [in]		channel: The channel to test (single 0 - 15, differential 0 - 7).
 *
 * @retval APCI3200_DIAGNOSTIC_NONE:				Disable diagnostic test.
 * @retval APCI3200_DIAGNOSTIC_OPEN_CONNECTION:		Open connection test.
 * @retval -EINVAL	Incorrect parameter.
 * @retval -EFAULT	Fail to return user parameters.
 */
int i_APCI3200_GetDiagnosticMode (struct pci_dev *pdev, unsigned char channel);

/** find a APCI 3200 device of a given index in the system PCI device list.
 * @param index The index (minor number) to lookup
 * @return A pointer to the device or NULL
 *
 * This function is used to map a minor number to an actual device.
 */
static __inline__  struct pci_dev * apci3200_lookup_board_by_index(unsigned int index)
{
	struct pci_dev * dev = NULL;
	int i = 0;

	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
	while ( (dev = pci_find_device(APCI3200_BOARD_VENDOR_ID,APCI3200_BOARD_DEVICE_ID,dev)) )
	#else
	while ( (dev = pci_get_device(APCI3200_BOARD_VENDOR_ID,APCI3200_BOARD_DEVICE_ID,dev)) )
	#endif
	{
		if (i == index) return dev;
		i++;
	}

	return NULL;
}


#endif // __KERNEL__

#endif // __APCI3200_KAPI_H__
