/** @file sample_apci1710_latch_Counter_Value_Status_Clear.c
 
   This demonstrates how to use read the latchvalue and latchstatus without interruption in user mode.
   Used function :

    InitCounter
    InitExternalStrobe
     LatchCounter
     ReadLatchRegisterValue
    ReadLatchRegisterStatus
     ClearCounterValue

   @par CREATION  
   @author Addi - data
   @date   29.04.2016
   
   @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 <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>

#include <apci1710.h>

#include "sample_apci1710_common.h"

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

/**
 * @brief Incremental counter sample for APCI-1710 module
 * @param fd Device file descriptor
 */
void sample (int fd)
{
    uint8_t b_ModuleNbr = 0;
    int     i_ReturnValue = 0;
    uint8_t i = 0;
    uint32_t ui_ArgArray[6];

    uint8_t b_LatchReg = 0;             // 0: First last register 1: Second latch register.
    uint8_t b_ExternalStrobe = 0;         // 0:external pulse A, 1: external pulse B
    uint8_t b_ExternalStrobeLevel = 1 ; // Level of the external pulse 0: external latch is generated at 0, 1: external latch is generated at 1

    /* Initialize the incremental counter */
    ui_ArgArray[0] = b_ModuleNbr;                // The module to use (0 to 3).
    ui_ArgArray[1] = APCI1710_32BIT_COUNTER;    // Selection form counter range.
    ui_ArgArray[2] = APCI1710_SIMPLE_MODE;        // First counter operating mode.
    ui_ArgArray[3] = APCI1710_HYSTERESIS_ON;    // First counter option.
    ui_ArgArray[4] = APCI1710_SIMPLE_MODE;        // Second counter operating mode.
    ui_ArgArray[5] = APCI1710_HYSTERESIS_ON;    // Second counter option.
                            
    i_ReturnValue = ioctl (fd,CMD_APCI1710_InitCounter, ui_ArgArray);
    /* Test the return value */
    switch (i_ReturnValue)
    {
        case 0:
            printf ("\nCMD_APCI1710_InitCounter OK");

            /* Initialize the latches*/
            ui_ArgArray[0] = b_ModuleNbr;        // The module to use (0 to 3).
            ui_ArgArray[1] = b_ExternalStrobe;
            ui_ArgArray[2] = b_ExternalStrobeLevel;

            i_ReturnValue = ioctl (fd,CMD_APCI1710_InitExternalStrobe, ui_ArgArray);

            /* Test the return value */
            if (i_ReturnValue < 0)
                perror("\nioctl");
            else
            {
                switch (i_ReturnValue)
                {
                    case 0:
                    printf ("\nAPCI1710_InitExternalStrobe OK");
                    break;

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

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

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

                    case 4:
                    printf ("\nCMD_APCI1710_InitExternalStrobe error");
                    printf ("\nError = %d. The selected external pulse is wrong.", i_ReturnValue);
                    break;

                    case 5:
                    printf ("\nCMD_APCI1710_InitExternalStrobe error");
                    printf ("\nError = %d. The external pulse level is wrong    ", i_ReturnValue);
                    break;

                    default:
                    printf ("\nAPCI1710_InitExternalStrobe");
                    printf ("\nError = %d.", i_ReturnValue);
                    break;
                }
            }

            /* Initialize the incremental counter input filter */
            ui_ArgArray[0] = b_ModuleNbr;    // The module to use (0 to 3).
            ui_ArgArray[1] = 7;            // Filter duration (0: disabled, n : 50 + (50 * n) nanoseconds, 800 ns max) : 50 + 7 X 50 = 400 ns

            i_ReturnValue = ioctl (fd,CMD_APCI1710_SetInputFilterEFG, ui_ArgArray);

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

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

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

                case 3:
                    printf ("\nCMD_APCI1710_SetInputFilterEFG rerror");
                    printf ("\nError = %d. Counter not initialized", i_ReturnValue);
                    break;

                case 4:
                    printf ("\nCMD_APCI1710_SetInputFilterEFG error");
                    printf ("\nError = %d. incremental counter is not SC3x or SC9x.", i_ReturnValue);
                    break;

                case 5:
                    printf ("\nCMD_APCI1710_SetInputFilterEFG error");
                    printf ("\nError = %d. The selected filter value is wrong", i_ReturnValue);
                    break;

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



            /*Latch the counter */
            ui_ArgArray[0] = b_ModuleNbr;        // The module to use (0 to 3).
            ui_ArgArray[1] = b_LatchReg;        // 0: First last register 1: Second latch register.

            i_ReturnValue = ioctl (fd,CMD_APCI1710_LatchCounter, ui_ArgArray);

            /* Test the return value */
            if (i_ReturnValue < 0)
                perror("\nioctl");
            else
            {
                switch (i_ReturnValue)
                {
                    case 0:
                    printf ("\nAPCI1710_LatchCounter OK");
                    break;

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

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

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

                    case 4:
                    printf ("\nCMD_APCI1710_LatchCounter error");
                    printf ("\nError = %d. The selected latch register parameter is wrong.", i_ReturnValue);
                    break;

                    default:
                    printf ("\nAPCI1710_LatchCounter");
                    printf ("\nError = %d.", i_ReturnValue);
                    break;
                }
            }



            /* 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;
                }


            /*Latch the counter */
            ui_ArgArray[0] = b_ModuleNbr;        // The module to use (0 to 3).
            ui_ArgArray[1] = b_LatchReg;        // 0: First last register 1: Second latch register.

            i_ReturnValue = ioctl (fd,CMD_APCI1710_LatchCounter, ui_ArgArray);
            /* Test the return value */
            if (i_ReturnValue < 0)
                perror("\nioctl");
            else
            {
                switch (i_ReturnValue)
                {
                    case 0:
                    printf ("\nAPCI1710_LatchCounter OK");
                    break;

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

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

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

                    case 4:
                    printf ("\nCMD_APCI1710_LatchCounter error");
                    printf ("\nError = %d. The selected latch register parameter is wrong.", i_ReturnValue);
                    break;

                    default:
                    printf ("\nAPCI1710_LatchCounter");
                    printf ("\nError = %d.", i_ReturnValue);
                    break;
                }
            }


            printf ("\n\n");

            do
                {

                int i_ReturnValue = 0;

                uint32_t ul_ArgArray[2];
                uint8_t b_LatchReg = 0;      // 0: First last register 1: Second latch register.

                ul_ArgArray[0]= 0 ;          //first module
                ul_ArgArray[1]= b_LatchReg ; // first last register

                //  Read Latch Register Status
                i_ReturnValue = ioctl (fd,CMD_APCI1710_ReadLatchRegisterStatus, ul_ArgArray);

                /* Test the return value */
                if (i_ReturnValue < 0)
                    perror("\nioctl");
                else
                {
                    switch (i_ReturnValue)
                    {
                        case 0:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterStatus OK");
                        break;

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

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

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

                        case 4:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterStatus error");
                        printf ("\nError = %d. The selected latch register parameter is wrong", i_ReturnValue);
                        break;

                        default:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterStatus");
                        printf ("\nError = %d.", i_ReturnValue);
                        break;
                    }
                }

                printf ("\nLatch Register status from Register %d  = %u", b_LatchReg, ul_ArgArray[0]);

                // Read the value of the register
                ul_ArgArray[0]= 0 ;             //first module
                ul_ArgArray[1]= b_LatchReg ;     // first last register

                // Read Latch Register Value
                i_ReturnValue = ioctl (fd,CMD_APCI1710_ReadLatchRegisterValue, ul_ArgArray);

                /* Test the return value */
                if (i_ReturnValue < 0)
                    perror("\nioctl");
                else
                {
                    switch (i_ReturnValue)
                    {
                        case 0:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterValue OK");
                        break;

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

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

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

                        case 4:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterValue error");
                        printf ("\nError = %d. The selected latch register parameter is wrong", i_ReturnValue);
                        break;

                        default:
                        printf ("\nCMD_APCI1710_ReadLatchRegisterValue");
                        printf ("\nError = %d.", i_ReturnValue);
                        break;
                    }
                }

                printf ("\nLatch Register value from Register %d  = %u", b_LatchReg, ul_ArgArray[0]);


                sleep (1); // 1
                }
            while (i++ < 30);
            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.\n");
}

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

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);

            /* latch interrupt sample */
            sample (apci1710_card_fd[i]);    
        }
    }

    

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