/** @file sample_apci1711_ssi.c
 
   This demonstarte how to use the incremental counter in user mode.
 
   @par CREATION  
   @author Laaziz ElBakali 
   @date   30.11.2015
   
   @par VERSION
   @verbatim
   $LastChangedRevision:$
   $LastChangedDate:$
   @endverbatim   
   
   @par LICENCE
   @verbatim
    Copyright (C) 2013  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 <stdarg.h>

#include <apci1710.h>

#include "sample_apci1710_common.h"

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

/**
 * @brief Read an integer from stdin within a specific range
 * @param minValue Minimum accepted value
 * @param maxValue Maximum accepted value
 * @param description Description message shown to the user
 * @return The read integer value
 */
uint32_t readInteger(uint32_t minValue, uint32_t maxValue, char *description, ...)
{
    va_list args;
    uint32_t readValue;

    va_start(args, description);
    do
    {
        vfprintf(stdout, description, args);
        fprintf(stdout, " ");
        fflush(stdout);
        scanf("%u", &readValue);
    }
    while (readValue < minValue || readValue > maxValue);
    return readValue;
}

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

/**
 * @brief SSI sample for APCI-1710 module
 * @param fd File descriptor of the opened APCI-1710 device
 */
static int sample (int fd)
{ 
    int ret = 0;
    int i = 0;
    //unsigned long irqstate;

    uint8_t b_ModulNbr = 0; /* The first module */
    uint8_t b_SelectedSSI = 0;
    
    uint8_t b_SSIProfile = 25;
    uint8_t b_PositionTurnLength = 12;
    uint8_t b_TurnCptLength = 12;

    uint8_t b_PCIInputClock = APCI1710_33MHZ;
    uint32_t ul_SSIOutputClock = 150000;
    uint8_t b_SSICountingMode = APCI1710_GRAY_MODE ; //APCI1710_BINARY_MODE;

    //uint32_t ul_Position = 0;
    //uint32_t ul_TurnCpt = 0;

    uint32_t argArray[18];

    /* get the module index */
    b_ModulNbr = (uint8_t)readInteger(0, 3, "Enter the index of the module that you want to use (0->3)");

    /* get the selected SSI */
    b_SelectedSSI = (uint8_t)readInteger(0, 3, "Enter the index of the Selected SSI that you want to use (0->2)");
    
    /* copy the parameters in the interface array */
    argArray[0] = (uint32_t) b_ModulNbr;
    argArray[1] = b_SSIProfile;
    argArray[2] = b_PositionTurnLength;
    argArray[3] = b_TurnCptLength;
    argArray[4] = b_PCIInputClock;
    argArray[5] = ul_SSIOutputClock;
    argArray[6] = b_SSICountingMode;

    /* initialize */
    ret = ioctl(fd, CMD_APCI1710_InitSSI, argArray);
    
    switch (ret)
    {
        case 0:
            printf ("\ni_APCI1710_InitSSI OK");
        break;

        case 1:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The handle parameter of the board is wrong", ret);
        break;
        
        case 2:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The module parameter is wrong", ret);
        break;
        
        case 3:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The module is not a SSI module", ret);
        break;
        
        case 4:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected SSI profile length is wrong", ret);
        break;
        
        case 5:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected SSI position data length is wrong", ret);
        break;
        
        case 6:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected SSI turn counter data length is wrong", ret);
        break;
        
        case 7:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected PCI input clock is wrong", ret);
        break;
        
        case 8:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected SSI output clock is wrong", ret);
        break;
        
        case 9:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d. The selected SSI counting mode parameter is wrong", ret);
        break;
        
        default:
            printf ("\ni_APCI1710_InitSSI error");
            printf ("\nError = %d.", ret);
        break;
    }

    if (!ret)
    {
        
        for (i=0; i<99; i++)
        {
            memset(argArray, 0, sizeof(argArray));
            
            /* get the data */
            argArray[0] =(uint32_t) b_ModulNbr;
            argArray[1] =(uint32_t) b_SelectedSSI;
            ret = ioctl(fd, CMD_APCI1710_Read1SSIValue, argArray);
    
            switch (ret)
            {
                case 0 :
                    printf ("\n%i) Counter value = %10u Counter position = %10u", i, argArray[0], argArray[1]);// argArray[2], argArray[3]
                    break;
                
                case 1:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d. The handle parameter of the board is wrong", ret);
                    break;
                
                case 2:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d. The module parameter is wrong", ret);
                    break;
                
                case 3:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d. The module is not a SSI module", ret);
                    break;
                
                case 4:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d. SSI not initialised", ret);
                    break;
                
                case 5:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d. The selected SSI is wrong", ret);
                    break;
                
                default:
                    printf ("\ni_APCI1710_Read1SSIValue error");
                    printf ("\nError = %d.", ret);
                    break;
            }
            
            sleep(1);
        }
    }
    
    return 0;
}

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

    /* Use the first APCI-1710 */
    sample(apci1710_card_fd[0]);

    printf("\n");
    return 0;
}

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


