/*
 * watchdog.c
 *
 *  Created on: Nov 8, 2010
 *      Author: Jordan ROSE
 *
 *  This sample show how to use the watchdog functionality of the xpci3009 board.
 */

#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>
#include <errno.h>
#include <limits.h>

#include <xpci3009.h>

#include "errorlib.h"
#include "findboards.h"
#include "errormsg.h"
#include "input.h"

int global_fd = 0;
//--------------------------------------------------------------------------------
void xpci3009_signal(int a)
{
	int i_ioctlReturn = 0;
	{
		uint32_t dw_ArgTable[1 + ADDIDATA_MAX_AI + 1 + ADDIDATA_MAX_INTERRUPT_ANALOG_INPUT_VALUE];

		memset(dw_ArgTable, 0 , sizeof (dw_ArgTable));

		while (0xfffffffe != dw_ArgTable[0])
			{
			i_ioctlReturn = ioctl (global_fd,CMD_xpci3009_TestInterrupt, dw_ArgTable);
				if (i_ioctlReturn < 0)
				{
					perror("ioctl");
					exit(1);
				}
				else
				{
					if ( i_ioctlReturn > 0 )
					{
						printf("An error occur. Code: %d\n", i_ioctlReturn);
						exit(1);
					}
				}
			// Test if FIFO Empty
			if 	(0xfffffffe != dw_ArgTable[0])
				{
				   // Test if watchdog 1 interrupt
				   if (dw_ArgTable[0] == 0x2000)
						{
						printf("Watchdog 1 interrupt \n");
						}

				   // Test if watchdog 2 interrupt
				   if (dw_ArgTable[0] == 0x4000)
						{
						printf("Watchdog 2 interrupt \n");
						}
				   } // end of if      (0xfffffffe != dw_ArgTable[0])
			else
				{
				// Test if FIFO Full
				if 	((0xffffffff != dw_ArgTable[0]) && (0xfffffffe != dw_ArgTable[0]))
					{
					printf("\ndw_InterruptSource : %x\n",  dw_ArgTable[0] );
					break;
					}
				}
			} // end of while (0xfffffffe != dw_ArgTable[0])
		}
}


//--------------------------------------------------------------------------------
// This function enable to use the watchdog
// @param fd : the file descriptor to the device
// @return 0 on success, other value on error
int do_test ( int fd )
{
	// ----------------------------------------------
	// Variables
	int ret = 0;
	int watchdog_index = 0;
	int time_unit = 0;
	int reload = 0;
	uint32_t init_arg[3] = {0};
	uint8_t interrupt_arg[2] = {0};
	uint32_t read_value_arg[2] = {0};
	uint32_t init_output[2] = {0};
	// ----------------------------------------------

	global_fd = fd;

	{
			printf("\n=> Requesting SIGIO notification\n");
			if (signal(SIGIO,&xpci3009_signal) == SIG_ERR)
			{
				perror("signal");
			}
			if (fcntl(fd, F_SETOWN, getpid()) == -1)
			{
				perror("fcntl");
			}
			{
				int oflags = fcntl(fd, F_GETFL);
				if ( fcntl(fd, F_SETFL, oflags | FASYNC) == -1)
				{
					perror("fcntl");
				}
			}
	}



	printf("This sample put 10V on the analog output 0. Then, at the end of the watchdog, the value is set to 0 by the watchdog. \n");

	printf("Enter the watchdog you want to test: \n");
	watchdog_index = get_integer(0, 1); // There is 2 watchdog on this board

	printf("Enter the time unit ( 0: nanosecond, 1: microsecond, 2: millisecond, 3: second) : \n");
	time_unit = get_integer(0,3);

	printf("Enter the time : \n");
	reload = get_integer(1, 1000);

	printf("Initialization of the watchdog \n");
	init_arg[0] = watchdog_index;
	init_arg[1] = time_unit;
	init_arg[2] = reload;
	ret = ioctl( fd , CMD_xpci3009_InitWatchdog, init_arg);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_InitWatchdog error : %d \n", ret );
		exit(1);
	}

	printf("Enable the interruption \n");
	interrupt_arg[0] = watchdog_index;
	interrupt_arg[1] = ADDIDATA_ENABLE;
	ret = ioctl( fd , CMD_xpci3009_EnableDisableWatchdogInterrupt, interrupt_arg);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_EnableDisableWatchdogInterrupt error : %d \n", ret );
		exit(1);
	}

	printf("Start the watchdog \n");
	ret = ioctl( fd , CMD_xpci3009_StartWatchdog, &watchdog_index);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_StartWatchdog error : %d \n", ret );
		exit(1);
	}

	// We have to trigger the watchdog one time to start it
	printf("Trigger the watchdog \n");
	ret = ioctl( fd , CMD_xpci3009_TriggerWatchdog, &watchdog_index);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_TriggerWatchdog error : %d \n", ret );
		exit(1);
	}

	// Set a analog input
	printf("Set the value of the analog input 0 \n");
	init_output[0] = 0; // channel 0
	init_output[1] = 0; // polarity bipolar
	ret = ioctl ( fd, CMD_xpci3009_InitAnalogOutput, init_output);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_InitAnalogOutput error : %d \n",ret );
		exit(1);
	}

	init_output[0] = 0; // Channel 0
	init_output[1] = 4095; // Value
	ret = ioctl ( fd, CMD_xpci3009_WriteAnalogOutputValue, init_output);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_WriteAnalogOutputValue error : %d \n",ret );
		exit(1);
	}

	// Watchdog...
	printf("Loop \n");
	read_value_arg[1] = 1;
	while ( read_value_arg[1] != 0)
	{
		read_value_arg[0] = watchdog_index;
		read_value_arg[1] = 0;
		ret = ioctl( fd , CMD_xpci3009_ReadWatchdogValue, read_value_arg);
		if ( ret != 0 )
		{
			printf("CMD_xpci3009_ReadWatchdogValue error : %d \n", ret );
			exit(1);
		}
		printf("Value of the watchdog : %d \n", read_value_arg[1]);
	}

	printf("Sleep 2 seconds \n");
	sleep(2);

	printf("Disable the interruption \n");
	interrupt_arg[0] = watchdog_index;
	interrupt_arg[1] = ADDIDATA_DISABLE;
	ret = ioctl( fd , CMD_xpci3009_EnableDisableWatchdogInterrupt, interrupt_arg);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_EnableDisableWatchdogInterrupt error : %d \n", ret );
		exit(1);
	}

	printf("Release the watchdog \n");
	ret = ioctl( fd , CMD_xpci3009_ReleaseWatchdog, &watchdog_index);
	if ( ret != 0 )
	{
		printf("CMD_xpci3009_ReleaseWatchdog error : %d \n", ret );
		exit(1);
	}

	return 0;
}

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

//--------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	int * fd = NULL;
	unsigned int number_of_boards = 0;
	int i = 0;

	// This is the first function to call in order to get the board handler
	number_of_boards = xpci3009_find_cards(&fd);
	printf("Number of boards in the computer: %d \n",number_of_boards);

	for ( i = 0 ; i < number_of_boards ; i++ )
	{
		do_test(fd[i]);
	}

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


