/** @file sample_apci1710_compare.c
 
   This demonstrates how to use compare logic 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 <apci1710.h>

#include "sample_apci1710_common.h"


static uint8_t gb_CompareInterrupt; /* Interrupt flag */
static int gi_fd; /* Global file handle on the board to use */

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


/**
 * @brief apci1710 user interrupt routine for compare logic
 * @param dummy Dummy parameter
 */
void v_apci1710_Signal (int dummy)
{
    uint32_t ul_ArgArray[3];
    int i_ReturnValue = 0;
    
        i_ReturnValue = ioctl (gi_fd,CMD_APCI1710_TestInterrupt, ul_ArgArray);
            
        if (i_ReturnValue < 0) {
            perror("ioctl");
        }
        else
            {
            printf ("\nAn interrupt occured:");
            printf ("\nModule = %i", ul_ArgArray[0]);        
            printf ("\nInterrupt mask = %u", ul_ArgArray[1]);            
            }
            
        i_ReturnValue = ioctl (gi_fd,CMD_APCI1710_SetDigitalChlOn, (uint8_t)ul_ArgArray[0]);    
        
        /* Test the return value */
        switch (i_ReturnValue)
            {
            case 0:
            printf ("\nCMD_APCI1710_SetDigitalChlOn OK");
            break;

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

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

            case 3:
            printf ("\nCMD_APCI1710_SetDigitalChlOn error");
            printf ("\nError = %d. Counter not initialised see function CMD_APCI1710_InitCounter", i_ReturnValue);
            break;

            default:
            printf ("\nCMD_APCI1710_SetDigitalChlOn error");
            printf ("\nError = %d.", i_ReturnValue);
            perror("\nioctl");                    
            break;
            } // switch (i_ReturnValue)    
            
        gb_CompareInterrupt = 1;            
                
}

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

/**
 * @brief Sample function to demonstrate the compare logic
 * @param fd File descriptor of the opened APCI-1710 device
 */
void sample (int fd)
{
    uint8_t b_ModuleNbr = 0;
    int i_ReturnValue = 0;
    uint32_t ul_CounterValue = 0;
    uint8_t i = 0;
    uint8_t b_ArgArray[6];
    uint32_t ui_ArgArray[2];
    int oflags = 0;
        
        gi_fd = fd;
        gb_CompareInterrupt = 0;

        /* Initialise the incremental counter */
        b_ArgArray[0] = b_ModuleNbr;            // The module to use (0 to 3).
        b_ArgArray[1] = APCI1710_32BIT_COUNTER;    // Selection form counter range.
        b_ArgArray[2] = APCI1710_SIMPLE_MODE;    // First counter operating mode.
        b_ArgArray[3] = APCI1710_HYSTERESIS_ON;    // First counter option.
        b_ArgArray[4] = APCI1710_SIMPLE_MODE;    // Second counter operating mode.
        b_ArgArray[5] = APCI1710_HYSTERESIS_ON;    // Second counter option.
                            
        i_ReturnValue = ioctl (fd,CMD_APCI1710_InitCounter, b_ArgArray);

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

            /* Install the user interrupt routine */
            i_ReturnValue = ioctl (fd,CMD_APCI1710_SetBoardIntRoutine);           

            /* Test the return value */
            switch (i_ReturnValue)
                {
                case 0:
                printf ("\nCMD_APCI1710_SetBoardIntRoutine OK");
                
                /* request asynchronous SIGIO */
                printf("\nrequest asynchronous SIGIO");
                
                if (signal(SIGIO, &v_apci1710_Signal) == SIG_ERR)
                    {
                    perror("signal");
                    }
                    
                if (fcntl(fd, F_SETOWN, getpid()) == -1)
                {
                perror("fcntl");
                }

                oflags = fcntl(fd, F_GETFL);
                if ( fcntl(fd, F_SETFL, oflags | FASYNC) == -1)
                    {
                    perror("fcntl");
                    }

                /* Clear the counter */
                i_ReturnValue = ioctl (fd,CMD_APCI1710_ClearCounterValue, b_ModuleNbr);

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

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

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

                    case 3:
                    printf ("\nCMD_APCI1710_ClearCounterValue error");
                    printf ("\nError = %d. Counter not initialised", i_ReturnValue);
                    break;

                    default:
                    printf ("\nCMD_APCI1710_ClearCounterValue error");
                    printf ("\nError = %d.", i_ReturnValue);
                    perror("\nioctl");                    
                    break;
                    } // switch (i_ReturnValue)

                /* Initialise the compare logic */
                ui_ArgArray[0] = b_ModuleNbr;    // The module to use (0 to 3).
                ui_ArgArray[1] = 1000;            // 32-Bit compare value.
                
                i_ReturnValue = ioctl (fd,CMD_APCI1710_InitCompareLogic, ui_ArgArray);

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

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

                    case 2:
                    printf ("\nCMD_APCI1710_InitCompareLogic error");
                    printf ("\nError = %d. No counter module found", i_ReturnValue);
                    break;

                    case 3:
                    printf ("\nCMD_APCI1710_InitCompareLogic error");
                    printf ("\nError = %d. Counter not initialised", i_ReturnValue);
                    break;

                    default:
                    printf ("\nCMD_APCI1710_InitCompareLogic error");
                    printf ("\nError = %d.", i_ReturnValue);
                    perror("\nioctl");                        
                    break;
                    } // switch (i_ReturnValue)

                /* Enable the compare logic */
                i_ReturnValue = ioctl (fd,CMD_APCI1710_EnableCompareLogic, b_ModuleNbr);

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

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

                    case 2:
                    printf ("\nCMD_APCI1710_EnableCompareLogic error");
                    printf ("\nError = %d. No counter module found", i_ReturnValue);
                    break;

                    case 3:
                    printf ("\nCMD_APCI1710_EnableCompareLogic error");
                    printf ("\nError = %d. Counter not initialised", i_ReturnValue);
                    break;

                    case 4:
                    printf ("\nCMD_APCI1710_EnableCompareLogic error");
                    printf ("\nError = %d. Compare logic not initialised", i_ReturnValue);
                    break;

                    case 5:
                    printf ("\nCMD_APCI1710_EnableCompareLogic error");
                    printf ("\nError = %d. Interrupt function not initialised", i_ReturnValue);
                    perror("\nioctl");                        
                    break;
                    } // switch (i_ReturnValue)

                printf ("\n\n");

                do
                    {
                    /* Read the 32-Bit counter */
                    ul_CounterValue = b_ModuleNbr; /* Pass the module number (0 to 3) */
                    
                    i_ReturnValue = ioctl (fd,CMD_APCI1710_Read32BitCounterValue, &ul_CounterValue);

                    /* Test the return value */
                    switch (i_ReturnValue)
                        {
                        case 0:
                        break;

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

                        case 2:
                        printf ("\nCMD_Read32BitCounterValue for the first counter error");
                        printf ("\nError = %d. No counter module found", i_ReturnValue);
                        break;

                        case 3:
                        printf ("\nCMD_Read32BitCounterValue for the first counter error");
                        printf ("\nError = %d. Counter not initialised", i_ReturnValue);
                        break;

                        default:
                        printf ("\nCMD_Read32BitCounterValue for the first counter error");
                        printf ("\nError = %d.", i_ReturnValue);
                        perror("\nioctl");                            
                        break;
                        } // switch (i_ReturnValue)

                    /* 
                     * Wait the interrupt signal.
                     * Print the 32-Bit counter value. 
                     */          
                    if (gb_CompareInterrupt) {
                        
                        i_ReturnValue = ioctl (gi_fd,CMD_APCI1710_SetDigitalChlOff, b_ModuleNbr);
                                
                        /* Test the return value */
                        switch (i_ReturnValue)
                            {
                            case 0:
                            printf ("\nCMD_APCI1710_SetDigitalChlOff OK");
                            break;
                
                            case 1:
                            printf ("\nCMD_APCI1710_SetDigitalChlOff error");
                            printf ("\nError = %d. The handle parameter of the board is wrong", i_ReturnValue);
                            break;
                
                            case 2:
                            printf ("\nCMD_APCI1710_SetDigitalChlOff error");
                            printf ("\nError = %d. The selected module number parameter is wrong", i_ReturnValue);
                            break;
                
                            case 3:
                            printf ("\nCMD_APCI1710_SetDigitalChlOff error");
                            printf ("\nError = %d. Counter not initialised see function CMD_APCI1710_InitCounter", i_ReturnValue);
                            break;
                
                            default:
                            printf ("\nCMD_APCI1710_SetDigitalChlOff error");
                            printf ("\nError = %d.", i_ReturnValue);
                            perror("\nioctl");                    
                            break;
                            } // switch (i_ReturnValue)    
                                    
                        gb_CompareInterrupt = 0;
                    }
                    else
                        printf ("\nCounter value from module %d  = %u", b_ModuleNbr, ul_CounterValue);
                        
                    sleep (1);
                    }
                while (i++ < 10);                       

                /* Disable the compare logic */
                i_ReturnValue = ioctl (fd,CMD_APCI1710_DisableCompareLogic, b_ModuleNbr);                

                /* Test the return value */

                switch (i_ReturnValue)
                    {
                    case 0:
                    printf ("\nCMD_DisableCompareLogic OK");
                    break;

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

                    case 2:
                    printf ("\nCMD_DisableCompareLogic error");
                    printf ("\nError = %d. No counter module found", i_ReturnValue);
                    break;

                    case 3:
                    printf ("\nCMD_DisableCompareLogic error");
                    printf ("\nError = %d. Counter not initialised", i_ReturnValue);
                    break;

                    case 4:
                    printf ("\nCMD_DisableCompareLogic error");
                    printf ("\nError = %d. Compare logic not initialised", i_ReturnValue);
                    break;
                    
                    default:
                    printf ("\nCMD_DisableCompareLogic error");
                    printf ("\nError = %d.", i_ReturnValue);
                    perror("\nioctl");                            
                    break;                    
                    } // switch (i_ReturnValue)

                /* Reset the board interrupt routine */
                i_ReturnValue = ioctl (fd,CMD_APCI1710_ResetBoardIntRoutine);

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

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

                    case 2:
                    printf ("\nCMD_ResetBoardIntRoutine error");
                    printf ("\nError = %d. No Interrupt function initialised", i_ReturnValue);
                    break;

                    default:
                    printf ("\nCMD_ResetBoardIntRoutine error");
                    printf ("\nError = %d.", i_ReturnValue);
                    perror("\nioctl");                    
                    break;
                    } // switch (i_ReturnValue)
                break;

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

                case 2:
                printf ("\nCMD_APCI1710_SetBoardIntRoutine error");
                printf ("\nError = %d. Interrupt already installed", i_ReturnValue);
                break;

                default:
                printf ("\nCMD_APCI1710_SetBoardIntRoutine error");
                printf ("\nError = %d.", i_ReturnValue);
                perror("\nioctl");                
                break;
                } // switch (i_ReturnValue)
            break;

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

            case 2:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The module is not a counter module", i_ReturnValue);
            break;

            case 3:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The selected counter range is wrong", i_ReturnValue);
            break;

            case 4:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The selected first counter operating mode is wrong", i_ReturnValue);
            break;

            case 5:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The selected first counter operating option is wrong", i_ReturnValue);
            break;

            case 6:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The selected second counter operating mode is wrong", i_ReturnValue);
            break;

            case 7:
            printf ("\nCMD_APCI1710_InitCounter error");
            printf ("\nError = %d. The selected second counter operating option is wrong", i_ReturnValue);
            break;

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

            printf ("\nProgram concluded.");
}

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


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

    int * apci1710_card_fd;
    unsigned int apci1710_card_number = 0;
    {
        apci1710_card_number = apci1710_find_cards(&apci1710_card_fd);
        
        printf("total: %d cards\n",apci1710_card_number);
    }    
    
    {
        int i;
        for (i=0;i< apci1710_card_number; i++)
        {
            printf("\n+++++++++++++++++++++++++++++++++++++\nrunning test on device of minor number %d\n+++++++++++++++++++++++++++++++++++++\n\n\n",i);

            /* Compare logic sample */
            sample (apci1710_card_fd[i]);    
        }
    }

    

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