 /* @file apci3701-kapi.h
  * 
  * @brief Define the public API for the apci3701 ADDI-DATA board. 
  * 
  *
  */

/** @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 APCI3701KAPI_H_
#define APCI3701KAPI_H_

#include "apci.h"
#include "apci3701-events.h"

#ifdef __KERNEL__

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

/** Enable, disable and initialise the analog input hardware trigger
 *
 * @param[in]  pdev : PCI Device struct              			\n
 * @param[in]   b_HardwareTrigger : 0 : disable the hardware trigger 	\n
 *                      						   1 : enable the hardware trigger 	\n
 * @param[in]   b_HardwareTriggerLevel : ADDIDATA_LOW: If the hardware   \n
 *              	                                	  trigger is used, it triggers  \n
 *            	      	                    	          from "1" to "0"               \n
 *              	        	                          ADDIDATA_HIGH: If the         \n
 *                  	        	                      hardware trigger is used, it  \n
 *                      	        	                  triggers from "0" to "1"      \n
 *                          	        	              ADDIDATA_LOW_HIGH: If the     \n
 *                              	        	          hardware trigger is used, it  \n
 *                                  	        	      triggers from "0" to "1" or   \n
 *                                      	        	  from "1" to "0"               \n
 * @param[in]   b_HardwareTriggerAction : Trigger action selection       \n
 *            			            	ADDIDATA_TRIGGER_START_A_SINGLE_CONVERSION	  0 \n
 *            			            	ADDIDATA_ONE_SHOT_TRIGGER					  1 \n
 *            			            	ADDIDATA_TRIGGER_START_A_SEQUENCE_SERIES	  2 \n
 *            			            	ADDIDATA_TRIGGER_START_A_SINGLE_SEQUENCE	  3 \n
 *            			            	ADDIDATA_TRIGGER_START_A_SCAN_SERIES	      6 \n
 *            			            	ADDIDATA_TRIGGER_START_A_SINGLE_SCAN  		  7 \n
 *            			            	ADDIDATA_TRIGGER_START_A_AUTO_REFRESH_SERIES 10 \n
 *            			            	ADDIDATA_TRIGGER_START_A_SINGLE_AUTO_REFRESH 11 \n
 * @param[in] dw_HardwareTriggerCount  : Hardware trigger counter.      \n
 *                  		                              Define the number of trigger  \n
 *                          		                      events before the action      \n
 *                                  		              occur (> 0)                   \n
 *
 *
 * @retval  0 : No error                                          			\n
 * @retval  1 : The handle parameter of the board is wrong        			\n
 * @retval  2 : Wrong hardware trigger parameter                  			\n
 * @retval  3 : Wrong hardware trigger level parameter            			\n
 * @retval  4 : Wrong hardware trigger action parameter               		\n
 * @retval  5 : Wrong hardware trigger count parameter               		\n
 * @retval  6 : No analog input functionality available           			\n
 * @retval  7 : A conversion is already started                   			\n
 */
int i_APCI3701_EnableDisableAnalogInputHardwareTrigger (struct pci_dev * pdev,
							                            uint8_t   b_HardwareTrigger,
							                            uint8_t   b_HardwareTriggerLevel,   
							                            uint8_t   b_HardwareTriggerAction,  
							                            uint32_t  dw_HardwareTriggerCount);

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

/** Get the transducer index for the specified transducer type.
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_TrasnducerType		: Transducer type:<br>
 *										0:Schlumberger AGH 1<br>
 *										1:TESA GT21/GT22<br>
 *										2:TESA GT21HP/GT22HP<br>
 *										3:TESA GT61/GT62<br>
 *										4:ATI AXH/1.0<br>
 *										5:Mahr 1300<br>
 *										6:Mahr 1301/1303<br>
 *										7:Klingelnberg Sagamo<br>
 *										8:Solartron AX1.0S<br>
 *										9:Marposs F25<br>
 *										10:Peter Hirt T109/T110<br>
 *										11:Kn�bel +/-200 2m cable<br>
 *										12:RDP D5/200AG<br>
 *										13:Kn�bel +/-200 10m cable<br>
 *										14:Kn�bel +/-400 2m cable<br>
 *										15:Kn�bel +/-400 10m cable<br>
 *										16:Kn�bel +/-500 2m cable<br>
 *										17:Kn�bel +/-500 10m cable<br>
 *										18:Kn�bel +/-600 2m cable<br>
 *										19:Kn�bel +/-600 10m cable<br>
 *										20:Mahr P2004<br> 
 *										21:Solartron AX5.0SH<br>
 *										22:Solartron System 256 AX0.25S<br>
 *										23:Solartron System 256 AX0.5S<br>
 *										24:Solartron System 256 AX1.0S<br>
 *										25:Solartron System 256 AX2.5S<br>
 *										26:Solartron System 256 AX5.0S<br>
 *										27:Solartron System 256 AX10.0S<br>
 *										28:Schaevitz GCA121-250<br>
 *										29:Solartron AX1.0SH<br>
 *										30:RDP GTX 500Z-170 Ohm<br>
 *										31:RDP GTX 2500-110 Ohm<br>
 *										32:RDP GTX 2500P<br>
 *										33:RDP GTX 5000P<br>
 *										34:Solatron AX2.5H<br>
 *										35:Schaevitz PCA-116-100<br>
 *										36:Schaevitz PCA-116-300
 * @param [out] w_TrasnducerIndex	: This value has to be used with i_APCI3701_InitTransducerChannel.
 * 
 * @retval 0:	No error.
 * @retval 1:	Wrong board handle.
 * @retval 2:	Header informations not present.
 * @retval 3:	Transducer type not found.
 */
int   i_APCI3701_GetTransducerIndex (struct pci_dev *pdev, WORD w_TrasnducerType, WORD *w_TrasnducerIndex);

int i_APCI3701_get_transducer_secondary_line_diagnostic_values ( struct pci_dev *pdev, uint16_t transducer_type, uint16_t* short_circuit, uint16_t* open_circuit);

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

/** Initialize the transducer of the specified channel.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_Channel            : Channel number to configure (0 to 15).
 * @param [in] w_TrasnducerIndex    : Use i_APCI3701_GetTransducerIndex to get the transducer index.
 * @param [in] w_MasterClock        : 
 * @param [in] w_LeftRightClock     : 
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: The channel parameter is wrong.
 * @retval 3: Acquisition already started.
 */
int   i_APCI3701_InitTransducerChannel (struct pci_dev *pdev,
										uint16_t w_Channel,
										uint16_t w_TrasnducerIndex,
										uint16_t w_MasterClock,
										uint16_t w_LeftRightClock);  

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

/** Initialize the autorefresh acquisition.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] w_SequenceSize       : Number of channels in the sequence. 
 * @param [in] w_ChannelSequence    : Channel sequence.<br>
 *                                    E.g.: For an acquisition on both A/D chip on each 4 first channels<br>
 *                                    The sequence has to be:<br>
 *                                    w_ChannelSequence[0] = 0;
 *                                    w_ChannelSequence[1] = 7;
 *                                    w_ChannelSequence[2] = 1;
 *                                    w_ChannelSequence[3] = 8;
 *                                    w_ChannelSequence[4] = 2;
 *                                    w_ChannelSequence[5] = 9;
 *                                    w_ChannelSequence[6] = 3;
 *                                    w_ChannelSequence[7] = 10;
 * @param [in] b_DivisionFactor     : The converting time division factor sets the switching time from channel to channel.<br>
 *                                    The base time is the transducer frequency. For example if the transducer connected to<br>
 *                                    channel 0 uses the 14 kHz frequency and the division factor is set to 5<br>
 *                                    then the switching time fron channel 0 to the next is: 1 (14/5) = 0.357 ms.<br>
 *                                    It is comprised between 5 and 255.
 *
 * @retval	0	No error. 
 * @retval	1	The handle parameter of the board is wrong.
 * @retval	2	The division factor is wrong.
 * @retval	3	Acquisition already started.
 */
int i_APCI3701_InitAnalogInputAutorefresh (struct pci_dev *pdev,
											uint32_t w_SequenceSize,
											uint32_t *w_ChannelSequence,
											uint8_t b_DivisionFactor);
   
//----------------------------------------------------------------------------

/** Start the autorefresh acquisition.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 *
 * @retval	0	No error. 
 * @retval	1	The handle parameter of the board is wrong.
 * @retval	2	Acquisition already started.
 */
int i_APCI3701_StartAnalogInputAutorefresh (struct pci_dev *pdev);

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

/** Stop the autorefresh acquisition.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 *
 * @retval	0	No error. 
 * @retval	1	The handle parameter of the board is wrong.
 * @retval	2	Acquisition not started.
 */
int i_APCI3701_StopAnalogInputAutorefresh (struct pci_dev *pdev);
	
//----------------------------------------------------------------------------

/** Read autorefresh acquisition.                                                 
 * 
 * @param [in]  pdev                 : The device to initialize.
 * @param [out] dw_ReadValue         : An array with each channel value.<br>
 *                                     Values are returned in the sequence order.
 * @param [out] dw_SequenceCounter   : Number of sequence.
 *                                     This value can be used to test if new value are available.

 * @retval	0	No error. 
 * @retval	1	The handle parameter of the board is wrong.
 * @retval	2	Acquisition not started.
 */
int i_APCI3701_ReadAnalogInputAutorefreshValue (struct pci_dev *pdev,
												uint32_t *dw_ReadValue,
												uint32_t *dw_SequenceCounter);

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

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

/** Read 8 digital input.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [out] b_DigitalInputValue : Digital input value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_APCI3701_Read8DigitalInput (struct pci_dev *pdev, uint8_t *b_DigitalInputValue);	

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

/** Write 8 digital output.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 * @param [in] b_DigitalOutputValue : Digital output value.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 */
int   i_APCI3701_Write8DigitalOutput (struct pci_dev *pdev, uint8_t b_DigitalOutputValue);	 			

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

/** Get the autorefresh status.                                                 
 * 
 * @param [in] pdev                 : The device to initialize.
 *
 * @retval 0: No error.
 * @retval 1: The handle parameter of the board is wrong.
 * @retval 2: Acquisition already started.
 */
int   i_APCI3701_GetAutorefreshStatus (struct pci_dev *pdev);


/*
 * Enable interruption to detect a short circuit on primary
 */
int i_APCI3701_PrimaryTransducerEnableDisablePrimaryShortCircuitInterrupt( struct pci_dev *pdev, BYTE b_interrupt_flag );

/*
 * Enables the test of open input on primary
 */
int i_APCI3701_PrimaryTransducerEnableDisablePrimaryOpenInputTest( struct pci_dev *pdev, BYTE b_flag );


/*
 * Rearm the primary short circuit
 */
int i_APCI3701_PrimaryTransducerRearmPrimaryOpenShortCircuitTest( struct pci_dev* pdev );

/*
 * Enables to test the secondary line short circuit
 */
int i_APCI3701_PrimaryTransducerEnableDisableSecondaryShortCircuitTest( struct pci_dev* pdev, BYTE b_flag);

/*
 * Enables to test the secondary line open circuit
 */
int i_APCI3701_PrimaryTransducerEnableDisableSecondaryOpenCircuitTest ( struct pci_dev* pdev, BYTE b_flag );

/*
 * To read the value of one channel
 */
int i_APCI3701_read_1_analog_channel( struct pci_dev *pdev, BYTE channel, uint32_t* value );

/*
 * To test the primary line without interruption
 */
int i_APCI3701_test_primary_line ( struct pci_dev* pdev, uint32_t* status);


/*
 * Role: This function enables, given a transducer_type, to know the value for which we have an open or a short circuit for this transducer
 * These two values depend on the transducer type.
 *
 * @param [in]	pdev : a pointer to the structure of the device
 * @param [in]	transducer_type : the type of the transducer. For example, for a solartron AX1, the type is 0x18 or 24 in decimal. You can find these type thanks to the programm
 * set3701 (not available under Linux for the moment)
 * @param [out]	short_circuit	: the short circuit value for the channel
 * @param [out]	short_circuit	: the open circuit value for the channel
 *
 *	Return value
 *	0	: no error
 *	1	: wrong board handler
 *	2	: board header not present
 */
int i_APCI3701_get_transducer_secondary_line_diagnostic_values ( struct pci_dev *pdev, uint16_t transducer_type, uint16_t* short_circuit, uint16_t* open_circuit);


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

/** find a apci3701 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.
 */
extern struct pci_dev * apci3701_lookup_board_by_index(unsigned int index);

//----------------------------------------------------------------------------
#include <linux/spinlock.h>

//----------------------------------------------------------------------------
/** return a pointer to the lock protecting the board */
extern spinlock_t * apci3701_get_lock(struct pci_dev *pdev);
//----------------------------------------------------------------------------
/** lock the board using spin_lock_irqsave(), disabling local software and hardware interrupts
 * @param[in] pdev The device to acquire.
 * @param[out] flags interuption flag used with unlock() 
 *
 * This function is to be used before calling any kAPI function; BUT not in user interrupt handler where the board is already acquired.
 *  
 * @warning lock aren't reentrant, that means that you can not nest call to lock() 
 *  
 */
static inline void apci3701_lock(struct pci_dev *pdev, unsigned long * flags)
{
	spin_lock_irqsave(apci3701_get_lock(pdev), *flags);
}

//----------------------------------------------------------------------------
/** unlock the board using spin_lock_irqrestore()
 * @param[in] pdev The device to acquire.
 * @param[out] flags interuption flag initialised by lock() 
 *
 * This function is to be used before calling any kAPI function; BUT not in user interrupt handler where the board is already acquired.
 * 
 *  
 *  
 */
static inline void apci3701_unlock(struct pci_dev *pdev, unsigned long flags)
{
	spin_unlock_irqrestore(apci3701_get_lock(pdev), flags);
}

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

#endif /*__KERNEL__*/

#endif /*APCI3701KAPI_H_*/
