/** 
 *  Authors: N. Gissler
 *  Creation: 02.12.2014
 *  $LastChangedDate: 2014-12-15 16:34:39 +0100 (Mon, 15 Dec 2014) $
 *  $LastChangedRevision: 1328 $
 *
 *  Copyright (C) 2014 ADDI-DATA GmbH
 *
 *  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
 **/

/***********************************************/
#include <signal.h>
#include <apci3120.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <apci3120-events.h>
#include "../lib/apci3120Lib.h"
/***********************************************/

#define NB_READ 100
#define MAX_CHANNEL_NBR 16


/***********************************************/

int main(int argc, char *argv[])
{
    int          ret, i, j;
    uint8_t      boardCount;
    unsigned int boardIndex  = (unsigned int)-1;
    unsigned int arg[MAX_CHANNEL_NBR * 3 + 2] = {0};
    long long unsigned int average[MAX_CHANNEL_NBR] = {0}; 
    uint8_t nbrChannels = 0;
  
    // Find how many boards are available 
    ret = i_APCI3120_GetNumberOfBoards(&boardCount);
    if (ret != 0)
    {
        fprintf(stderr, "i_APCI3120_GetNumberOfBoards: error %d\n", ret);
        return 1;
    }
    printf("Found %d board%s.\n", boardCount, boardCount > 1 ? "s" : "");
    if (boardCount == 0)
        return 2;

    // Ask which board should be used 
    do
    {
        char inputBuffer[32];
        fprintf(stdout, "Select the board you would like to use (0 to %d): ", boardCount - 1);
        fflush(stdout);
        if (fgets(inputBuffer, sizeof(inputBuffer), stdin) != NULL && strlen(inputBuffer) > 1)
            boardIndex = (unsigned int)atoi(inputBuffer);
    } while (boardIndex >= boardCount);
    
    // Set all parameters

/* Explanation about how to fill the structure arg
unsigned int arg[16*3 + 2]; // do not change it
Number of channel to read (1 - 16)
  arg[0]  = 16   
How to fill the rest of the argument depends of how many channels are selected.

For example, if you have selected 16 (all) channels, here how the struct is filled :
  arg[0]  = 16   
List of channels to read. Put 0 to not read the selected channel 
  arg[1]  = 0   
  arg[2]  = 1
  ...
  arg[15] = 14
  arg[16] = 15
Set the gain for each channel
  arg[17] = APCI3120_1_GAIN;     // gain x1 for channel 1
  arg[18] = APCI3120_1_GAIN;     // gain x1 for channel 2
  ... 
  arg[31] = APCI3120_1_GAIN;     // gain x1 for channel 15
  arg[32] = APCI3120_1_GAIN;     // gain x1 for channel 16
Set the polarity for each channel
  arg[33] = APCI3120_1_BIPOLAR;  // polarity for channel 1
  arg[34] = APCI3120_1_BIPOLAR;  // polarity for channel 2
  ...
  arg[47] = APCI3120_1_BIPOLAR;  // polarity for channel 15
  arg[48] = APCI3120_1_BIPOLAR;  // polarity for channel 16
Set the conversion time (identical for all channel), from 10 to 32767 us
  arg[49] = 10;

If you select 10 channels only :
  arg[0]  = 10   
List of channels to read. Put 0 to not read the selected channel 
  arg[1]  = 0   
  arg[2]  = 1
  ...
  arg[9]  = 8
  arg[10] = 9
Set the gain for each channel
  arg[11] = APCI3120_1_GAIN;     // gain x1 for channel 1
  arg[12] = APCI3120_1_GAIN;     // gain x1 for channel 2
  ... 
  arg[19] = APCI3120_1_GAIN;     // gain x1 for channel 9
  arg[20] = APCI3120_1_GAIN;     // gain x1 for channel 10
Set the polarity for each channel
  arg[21] = APCI3120_1_BIPOLAR;  // polarity for channel 1
  arg[22] = APCI3120_1_BIPOLAR;  // polarity for channel 2
  ...
  arg[29] = APCI3120_1_BIPOLAR;  // polarity for channel 9
  arg[30] = APCI3120_1_BIPOLAR;  // polarity for channel 10
Set the conversion time (identical for all channel), from 10 to 32767 us
  arg[31] = 10;

Look at the loops below


*/
    nbrChannels = 16;

    for (j = 0; j < NB_READ; j++) 
    {
      arg[0] = nbrChannels; // Number of channel to read

      // List of channels to read, here channel 0 to 15 
      for (i = 1; i < arg[0] + 1; i++)
        arg[i] = i - 1;
      
      // Set the gain for each channel 
      for (i = arg[0] + 1; i < arg[0] * 2 + 1; i++)
        arg[i] = APCI3120_1_GAIN;

      // Set the polarity for each channel 
      for (i = arg[0] * 2 + 1; i < arg[0] * 3 + 1; i++)
        arg[i] = APCI3120_BIPOLAR;

      // Set the converting time (it is the same for each channel) it can be of 10 up to 32767 us
      arg[arg[0] * 3 + 1] = 100;

      // Print all parameters once
      if (j == 0)
      { 
        fprintf(stdout, "Parameters are :\n");
        for (i = 0; i < 50; i++)
          fprintf(stdout, "arg[%d] = %d\n", i, arg[i]);
      }

      ret = i_APCI3120_ReadMoreAnalogInputs(boardIndex, arg);
      if (ret != 0)
      { fprintf(stderr, "i_APCI3120_ReadMoreAnalogInputs error %d\n", ret); goto end; } 
      
      for (i = 0; i < nbrChannels; i++)
        average[i] += arg[i];  
      
      usleep(2000);
    } 


    
    // display averaged value per channel
    for (i = 0; i < nbrChannels; i++)
    {
      average[i] = average[i] / NB_READ;
      // gain x1 : full_scale = 10
      fprintf(stdout, "Channel %d, averaged value : %llu  ( %f V)\n", i, average[i], computeVoltage(average[i], 10));  
    }   
    fprintf(stdout, "As stated in the documentation, Due to the very high impedance of the analog inputs, the measurement result is undefined, i.e. variable at inputs that are not connected (open). To minimise interfering factors, all the inputs that are not required should be connected with “Analog input GND” (see pin assignment of the documentation).");

end:
  return ret;
}
