/** @file sample_xpci3009.c
 
   This demonstarte how to use digital I/O in user mode.
 
   @par CREATION  
   @author Krauth Julien
   @date   30.05.06
   
   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim   
   
   @par LICENCE
   @verbatim
    Copyright (C) 2009  ADDI-DATA GmbH for the source code of this module.
        
    ADDI-DATA GmbH
    Airpark Business Center
    Airport Boulevard B210
    77836 Rheinm�nster
    Germany
    Tel: +49(0)7229/1847-0
    Fax: +49(0)7229/1847-200
    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 <signal.h>
#include <sys/sysmacros.h> /* major() minor() */

#include <xpci3009.h>
#include "findboards.h"

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

void sample (int fd)
	{
	unsigned char  b_ModuleNbr = 0;             // Module number to test
	unsigned char  b_ChannelCpt;		// Channel counter
	char *        pc_ChannelArray = {"HAB"};
	int            i_ReturnValue;           // Return error code
	unsigned char b_ArgArray[3];


	/* Print sample information */
	printf ("\n+---------------------------------------------------+");
	printf ("\n| XPCI-3009 Digital I/O:                            |");
	printf ("\n| Digital channel output sample                     |");
	printf ("\n| Channel A and channel B for output                |");
	printf ("\n+---------------------------------------------------+");

	/* 
	 * Initialise the digital I/O module
	 * Channel A and Channel B for input
	 */
 	
 	/* Module number to configure (0 to 3).*/
	b_ArgArray[0] = b_ModuleNbr;
	
	/*
	 * Channel A mode selection
	 * 0 : Channel used for digital input
	 * 1 : Channel used for digital output
	 */	
	b_ArgArray[1] = 1;

	/*
	 * Channel B mode selection
	 * 0 : Channel used for digital input
	 * 1 : Channel used for digital output
	 */	
	b_ArgArray[2] = 1;
			
	i_ReturnValue = ioctl (fd,CMD_XPCI3009_InitDigitalIO, b_ArgArray);

	/* Test the return value */
	switch (i_ReturnValue)
		{
		case 0:
		printf ("\nCMD_XPCI3009_InitDigitalIO OK");
		break;

		case 1:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
		break;

		case 2:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d. The module parameter is wrong", i_ReturnValue);
		break;

		case 3:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d. The module is not a digital I/O module", i_ReturnValue);
		break;

		case 4:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d. Bi-directional channel A configuration error", i_ReturnValue);
		break;
	
		case 5:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d. Bi-directional channel B configuration error", i_ReturnValue);
		break;
	
		default:
		printf ("\nCMD_XPCI3009_InitDigitalIO error");
		printf ("\nError = %d", i_ReturnValue);
		break;
		} // switch (i_ReturnValue)

		/* Set the digital I/O output memory on */
		i_ReturnValue = ioctl (fd,CMD_XPCI3009_SetDigitalIOMemoryOn, b_ModuleNbr);

		/* Test the return value */
		switch (i_ReturnValue)
			{
			case 0:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn OK");
			break;

			case 1:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn error");
			printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
			break;

			case 2:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn error");
			printf ("\nError = %d. The module parameter is wrong", i_ReturnValue);
			break;

			case 3:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn error");
			printf ("\nError = %d. The module is not a digital I/O module", i_ReturnValue);
			break;

			case 4:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn error");
			printf ("\nError = %d. Digital I/O not initialised", i_ReturnValue);
			break;

			default:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOn error");
			printf ("\nError = %d", i_ReturnValue);
			break;
			} // switch (i_ReturnValue)

		/* Set the digital outputs on */
		for (b_ChannelCpt = 0; b_ChannelCpt < 3; b_ChannelCpt ++)
			{
			printf ("\n\nSet digital output %c on", pc_ChannelArray [b_ChannelCpt]);
			printf ("\nWait 2 seconds");
			sleep (2);

			/* Set the digital output on */
			
			b_ArgArray[0] = b_ModuleNbr;
			b_ArgArray[1] = b_ChannelCpt;		
			i_ReturnValue = ioctl (fd,CMD_XPCI3009_SetDigitalIOChlOn, b_ArgArray);

			/* Test the return value */
			switch (i_ReturnValue)
				{
				case 0:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn for channel %c OK", pc_ChannelArray [b_ChannelCpt]);
				break;

				case 1:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
				break;

				case 2:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The module parameter is wrong", i_ReturnValue);
				break;
				
				case 3:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The module is not a digital I/O module", i_ReturnValue);
				break;
				
				case 4:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The selected digital output is wrong", i_ReturnValue);
				break;
				
				case 5:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. Digital I/O not initialised", i_ReturnValue);
				break;
				
				case 6:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The digital channel A is used for input", i_ReturnValue);
				break;
				
				case 7:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The digital channel B is used for input", i_ReturnValue);
				break;
				
				default:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOn channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d", i_ReturnValue);
				break;
				} // switch (i_ReturnValue)
			}

		/* Set the digital outputs off */
		for (b_ChannelCpt = 0; b_ChannelCpt < 3; b_ChannelCpt ++)
			{
			printf ("\n\nSet digital output %c off", pc_ChannelArray [b_ChannelCpt]);
			printf ("\nWait 2 seconds");
			sleep (2);

			/* Set the digital output on */
			b_ArgArray[0] = b_ModuleNbr;
			b_ArgArray[1] = b_ChannelCpt;		
			i_ReturnValue = ioctl (fd,CMD_XPCI3009_SetDigitalIOChlOff, b_ArgArray);

			/* Test the return value */
			switch (i_ReturnValue)
				{
				case 0:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff for channel %c OK", pc_ChannelArray [b_ChannelCpt]);
				break;
				
				case 1:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
				break;
				
				case 2:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The module parameter is wrong", i_ReturnValue);
				break;
				
				case 3:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The module is not a digital I/O module", i_ReturnValue);
				break;
				
				case 4:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The selected digital output is wrong", i_ReturnValue);
				break;
				
				case 5:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. Digital I/O not initialised", i_ReturnValue);
				break;
				
				case 6:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The digital channel A is used for input", i_ReturnValue);
				break;
				
				case 7:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. The digital channel B is used for input", i_ReturnValue);
				break;
				
				case 8:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d. Digital Output Memory OFF", i_ReturnValue);
				break;
				
				default:
				printf ("\nCMD_XPCI3009_SetDigitalIOChlOff channel %c error", pc_ChannelArray [b_ChannelCpt]);
				printf ("\nError = %d", i_ReturnValue);
				break;
				} // switch (i_ReturnValue)
			}

		/* Set the digital I/O output memory off */
		i_ReturnValue = ioctl (fd,CMD_XPCI3009_SetDigitalIOMemoryOff, b_ModuleNbr);

		/* Test the return value */
		switch (i_ReturnValue)
			{
			case 0:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff OK");
			break;
			
			case 1:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff error");
			printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
			break;
			
			case 2:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff error");
			printf ("\nError = %d. The module parameter is wrong", i_ReturnValue);
			break;
			
			case 3:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff error");
			printf ("\nError = %d. The module is not a digital I/O module", i_ReturnValue);
			break;
			
			case 4:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff error");
			printf ("\nError = %d. Digital I/O not initialised", i_ReturnValue);
			break;
			
			default:
			printf ("\nCMD_XPCI3009_SetDigitalIOMemoryOff error");
			printf ("\nError = %d", i_ReturnValue);
			break;
			} // switch (i_ReturnValue)
	}

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

int main(int argc, char** argv)
{

	int * xpci3009_card_fd;
	unsigned int xpci3009_card_number = 0;
	{
		xpci3009_card_number = apci_find_boards("xpci3009",&xpci3009_card_fd);
		
		printf("total: %d cards\n",xpci3009_card_number);
	}	
	
	{
		int i;
		for (i=0;i< xpci3009_card_number; i++)
		{
			printf("\n+++++++++++++++++++++++++++++++++++++\nrunning test on device of minor number %d\n+++++++++++++++++++++++++++++++++++++\n\n\n",i);			
			/* Compare logic sample */
			sample (xpci3009_card_fd[i]);
		}
	}

	

	return 0;
}
//--------------------------------------------------------------------------------
