/** @file sample_apcie1532_digital_io.c
 
   This sample demonstartes how to use digital input / output in user mode.
 
   @par CREATION  
   @author Krauth Julien
   @date   08.01.09
   
   @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 <sys/sysmacros.h> /* major() minor() */

#include <signal.h> /* For signal */

#include <apcie1532.h>

#include "findboards.h"

/* This global variable is used to stop each single samples */
unsigned char stop;

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

/** Move the consol cursor on the specified point.
*
* @param x	Horizontal position of the cursor.
* @param y	Vertical position of the cursor.
*
* retval 0 No error.
*/
int gotoxy(int x, int y)
{
	char essq[100]; // String variable to hold the escape sequence
	char xstr[100]; // Strings to hold the x and y coordinates
	char ystr[100]; // Escape sequences must be built with characters

	// Convert the screen coordinates to strings
	sprintf(xstr, "%d", x);
	sprintf(ystr, "%d", y);

	// Build the escape sequence (vertical move)
	essq[0] = '\0';
	strcat(essq, "\033[");
	strcat(essq, ystr);

	// Described in man terminfo as vpa=\\E[%p1%dd
	// Vertical position absolute
	strcat(essq, "d");

	// Horizontal move
	// Horizontal position absolute
	strcat(essq, "\033[");
	strcat(essq, xstr);

	// Described in man terminfo as hpa=\\E[%p1%dG
	strcat(essq, "G");

	// Execute the escape sequence
	// This will move the cursor to x, y
	printf("%s", essq);

	return 0;
}

//--------------------------------------------------------------------------------
/** this function look up for cards in the /proc/sys/apcie1532/ 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 apcie1532_find_cards(int ** cards)
{
	return apci_find_boards("apcie1532", cards);
}

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

/** Test APCIE-1532 digital input.
*
* @param [in]	fd	File descriptor of the borad to use.
*
* @retval 0	No error.
* @retval 1	Error.
*/
int apcie1532_test_digital_input (int fd)
{
	uint32_t PortState = 0;

	/* Clean the screen before display input status */
	system("clear");

	while (!stop)
	{
		/* Read all digital input state */
		printf ("CMD_APCIE1532_Read16DigitalInputs\n");
		if ( ioctl (fd,CMD_APCIE1532_Read16DigitalInputs,&PortState) < 0 )
		{
			perror("ioctl");
			exit(1);
		}

		/* Set the cursor on screen top */
		gotoxy (0,0);
		printf ("\n+--------------------------------------------------------------------------------------+");
		printf ("\n| DIGITAL INPUTS STATES                                                                |");
		printf ("\n+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+------+");
		printf ("\n| 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9  | 8  | 7  | 6  | 5  | 4  | 3  | 2  | 1  | Hex  |");
		printf ("\n+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+------+");
		printf ("\n|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s| %4x |",
				(PortState & 32768)?"ON":"OFF",
				(PortState & 16384)?"ON":"OFF",
				(PortState & 8192)?"ON":"OFF",
				(PortState & 4096)?"ON":"OFF",
				(PortState & 2048)?"ON":"OFF",
				(PortState & 1024)?"ON":"OFF",
				(PortState & 512)?"ON":"OFF",
				(PortState & 256)?"ON":"OFF",		
				(PortState & 128)?"ON":"OFF",
				(PortState & 64)?"ON":"OFF",
				(PortState & 32)?"ON":"OFF",
				(PortState & 16)?"ON":"OFF",
				(PortState & 8)?"ON":"OFF",
				(PortState & 4)?"ON":"OFF",
				(PortState & 2)?"ON":"OFF",
				(PortState & 1)?"ON":"OFF",
				PortState);
		printf ("\n+--------------------------------------------------------------------------------------+");
		printf ("\n");
		printf ("\n");
		printf ("ctrl + c for the next test\n");
		printf ("\n");
	}

	return 0;
}

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

/** Test APCIE-1532 digital output.
*
* @param [in]	fd	File descriptor of the borad to use.
*
* @retval 0	No error.
* @retval 1	Error.
*/
int apcie1532_test_digital_output (int fd)
{
	uint32_t PortState = 0;
	int i = 0;

	/* Set the digital output memory on.<br>
	 * When digital output memory is activated,<br>
	 * the previous output state is hold when one<br>
	 * or more output states are set.
	 */
	printf ("CMD_APCIE1532_SetDigitalOutputMemoryOn\n");
	if ( ioctl (fd,CMD_APCIE1532_SetDigitalOutputMemoryOn,NULL) < 0 )
	{
		perror("ioctl");
		exit(1);
	}

	printf ("\n");
	printf ("\n");

	while (!stop)
	{
		usleep (250000);

		if (i < 16)
		{
			PortState = 1 << i;

			printf ("CMD_APCIE1532_Set16DigitalOutputsOn\n");
			if ( ioctl (fd,CMD_APCIE1532_Set16DigitalOutputsOn,PortState) < 0 )
			{
				perror("ioctl");
				exit(1);
			}
		}

		if (i > 15)
		{
			PortState = 1 << (i-16);

			printf ("CMD_APCIE1532_Set16DigitalOutputsOff\n");
			if ( ioctl (fd,CMD_APCIE1532_Set16DigitalOutputsOff,PortState) < 0 )
			{
				perror("ioctl");
				exit(1);
			}
		}

		printf ("CMD_APCIE1532_Get16DigitalOutputStatus\n");
		if ( ioctl (fd,CMD_APCIE1532_Get16DigitalOutputStatus,&PortState) < 0 )
		{
			perror("ioctl");
			exit(1);
		}

		gotoxy (0,0);
		printf ("\n+--------------------------------------------------------------------------------------+");
		printf ("\n| DIGITAL OUTPUTS STATES                                                               |");
		printf ("\n+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+------+");
		printf ("\n| 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9  | 8  | 7  | 6  | 5  | 4  | 3  | 2  | 1  | Hex  |");
		printf ("\n+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+------+");
		printf ("\n|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s|%4s| %4x |",
				(PortState & 32768)?"ON":"OFF",
				(PortState & 16384)?"ON":"OFF",
				(PortState & 8192)?"ON":"OFF",
				(PortState & 4096)?"ON":"OFF",
				(PortState & 2048)?"ON":"OFF",
				(PortState & 1024)?"ON":"OFF",
				(PortState & 512)?"ON":"OFF",
				(PortState & 256)?"ON":"OFF",		
				(PortState & 128)?"ON":"OFF",
				(PortState & 64)?"ON":"OFF",
				(PortState & 32)?"ON":"OFF",
				(PortState & 16)?"ON":"OFF",
				(PortState & 8)?"ON":"OFF",
				(PortState & 4)?"ON":"OFF",
				(PortState & 2)?"ON":"OFF",
				(PortState & 1)?"ON":"OFF",
				PortState);
		printf ("\n+--------------------------------------------------------------------------------------+");
		printf ("\n");
		printf ("\n");
		
		if ( i == 31 )
			i = 0;
		else
			i++;		
	}

	printf ("\n");

	/* Set the digital output memory off */
	printf ("CMD_APCIE1532_SetDigitalOutputMemoryOff\n");
	if ( ioctl (fd,CMD_APCIE1532_SetDigitalOutputMemoryOff,NULL) < 0 )
	{
		perror("ioctl");
		exit(1);
	}

	return 0;
}

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

void v_ControlExit (int i)
{
	stop=1;
}

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

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

	int * apcie1532_card_fd;
	unsigned int apcie1532_card_number = 0;
	{
		apcie1532_card_number = apcie1532_find_cards(&apcie1532_card_fd);
		if( apcie1532_card_number == -1 )
		{
			exit(1);
		}
		printf("total: %d cards\n",apcie1532_card_number);
	}

	if( apcie1532_card_number == 0 )
		exit(0);

	signal(SIGINT,v_ControlExit);
	stop = 0;
	system("clear");

	{
		int i;
		for (i=0;i< apcie1532_card_number; i++)
		{
			printf("\n\nRunning digital input test on device of minor number %d\n\n\n\n",i);
			apcie1532_test_digital_input (apcie1532_card_fd[i]);
			system("clear");
			stop = 0;

			printf("\n\nRunning digital output test on device of minor number %d\n\n\n\n",i);
			apcie1532_test_digital_output (apcie1532_card_fd[i]);
		}
	}


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