/** @file sample_apcie2200_digital_io.c
 
   This sample demonstartes how to use digital output watchdog in user mode.
 
   @par CREATION  
   @author Krauth Julien
   @date   28.01.2010
   
   @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 Rheinmuenster
   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 <apcie2200.h>

#include "findboards.h"
#include "input.h"

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

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

/** Exit callback function.
 *
 * This function is called on Ctrl+c key combination.
 * It set the stop flag status.
 */
static void v_ControlExit (int notused)
{
      ucStopFlag = 1;
      printf("Sample abort.\n");
}

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

/** Test APCIE-2200 watchdog with digital output.
*
* @param [in]	fd	File descriptor of the board to use.
*
* @retval 0	No error.
* @retval 1	Error.
*/
int apcie2200_test_watchdog_with_digital_output (int fd)
{
	uint32_t PortState = 0;
	uint32_t nbrOfOutputs = 0;
	int sec = 1;
	struct
	{
		uint32_t ressourceType;
		uint32_t mode;
		uint32_t timeBaseUnit;
		uint32_t timeBaseValue;
		uint32_t irq;
	} param;

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

	printf ("Number of digital outputs: %i\n", nbrOfOutputs);

	/* 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_APCIE2200_SetDigitalOutputMemoryOn\n");
	if ( ioctl (fd,CMD_APCIE2200_SetDigitalOutputMemoryOn,NULL) < 0 )
	{
		perror("ioctl");
		exit(1);
	}

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

	usleep (250000);


	PortState = ((1 << nbrOfOutputs) - 1);

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

	/* Initialize the watchdog */

	/* Watchdog set on 3 seconds */
	param.ressourceType = 0;
	param.mode = 2;
	param.timeBaseUnit = 3;
	param.timeBaseValue = 3;
	param.irq = 0;

	if (ioctl (fd, CMD_APCIE2200_TimerWatchdogInitAndStart, &param) != 0)
		perror("ioctl");

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

	printf ("Sleep 10 seconds, the watchdog should occurred after 3 seconds (if it is not trigger by a set digital output or a software trigger).\n");

        for (; ((sec <= 10) && (ucStopFlag == 0)); sec++)
	{
		printf ("Elapsed time: %i sec.\n", sec);
		sleep (1);

		switch (sec)
		{
			case 2:
				printf ("CMD_APCIE2200_TimerWatchdogTrigger\n");
				if (ioctl (fd, CMD_APCIE2200_TimerWatchdogTrigger, param.ressourceType) != 0)
					perror("ioctl");
			break;

			case 4:
				printf ("CMD_APCIE2200_TimerWatchdogTrigger\n");
				if (ioctl (fd, CMD_APCIE2200_TimerWatchdogTrigger, param.ressourceType) != 0)
					perror("ioctl");
			break;
		}
	}

	printf("CMD_APCIE2200_TimerWatchdogStopAndRelease\n");
	if (ioctl (fd, CMD_APCIE2200_TimerWatchdogStopAndRelease, param.ressourceType) != 0)
		perror("ioctl");

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

	return 0;
}

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

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

	int apcie2200_card_fd;

	if (argc < 2 )
	{
                printf("Not enough arguments\n");
                printf("Usage: %s /dev/apcie2200_[0..15]\n", argv[0]);
		exit(1);
	}

	if ( ( apcie2200_card_fd = open(argv[1], O_RDWR)) == -1 )
	{
		perror("open");
		exit(1);
	}

	{
		struct stat file_stat;
		if ( fstat(apcie2200_card_fd,&file_stat) )
		{
			perror("fstat");
			exit(1);
		}
		if (!S_ISCHR(file_stat.st_mode))
		{
			/* should never happen !*/
			printf("file %s is not a character device\n",argv[1]);
			printf("failed");
			exit(1);
		}
		printf("%s, major:%d minor:%d \n",argv[1], major(file_stat.st_rdev),minor(file_stat.st_rdev));
	}

        ucStopFlag=0;
        signal(SIGINT, v_ControlExit);

	{
            printf( "\n+++++++++++++++++++++++++++++++++++++++++++++++++++"
                    "\nRunning watchdog test on device %s (Ctrl+C to stop)"
                    "\n+++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n",
                    argv[1]);

            apcie2200_test_watchdog_with_digital_output (apcie2200_card_fd);
	}

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