adc1.c -- Read the Analog to Digital converter.
/* adc1.c */

/* Copyright(c) 1991-2002 by Motion Engineering, Inc.  All rights reserved.
 *
 * This software  contains proprietary and  confidential information  of
 * Motion Engineering Inc., and its suppliers.  Except as may be set forth
 * in the license agreement under which  this software is supplied, use,
 * disclosure, or  reproduction is prohibited without the prior express
 * written consent of Motion Engineering, Inc.
 */

#if defined(MEI_RCS)
static const char MEIAppRCS[] =
    "$Header: /MainTree/XMPLib/XMP/app/adc1.c 10    8/01/01 2:08p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    adc1Main

argMainRENAME(main, adc1)
#endif

/*

:Read the Analog to Digital converter.

This sample code demonstrates how to read digital values from the A/D (analog
 to digital) converter.  The values are stored into a buffer and the average
 of the values stored in the buffer is displayed.

Warning!  This is a sample program to assist in the integration of the
 XMP motion controller with your application.  It may not contain all
 of the logic and safety features that your application requires.
*/

#include <stdlib.h>
#include <stdio.h>

#include "stdmpi.h"
#include "stdmei.h"

#include "apputil.h"


#define ADC_COUNT   (1)
#define ADC_NUMBER  (0)
#define ADC_RANGE   (10.0)  /* 10.0, 5.0, 2.5, or 1.25 volts */
#define ADC_INPUT   (MEIAdcMuxANALOG_IN_0)

#define BUFFER_SIZE (1000)


/* Perform basic command line parsing. (-control -server -port -trace) */
void basicParsing(int                    argc,
                  char                  *argv[],
                  MPIControlType        *controlType,
                  MPIControlAddress     *controlAddress)
{
    long argIndex;

    /* Parse command line for Control type and address */
    argIndex = argControl(argc, argv, controlType, controlAddress);

    /* Check for unknown/invalid command line arguments */
    if (argIndex < argc) {
        fprintf(stderr,"usage: %s %s\n", argv[0], ArgUSAGE);
        exit(MPIMessageARG_INVALID);
    }
}


/* Create and initialize MPI objects */
void programInit(MPIControl         *control,
                 MPIControlType      controlType,
                 MPIControlAddress  *controlAddress,
                 MPIAdc             *adc,
                 long                adcNumber)
{
    long            returnValue;


    /* Create motion controller object */
    *control =
        mpiControlCreate(controlType,
                         controlAddress);
    msgCHECK(mpiControlValidate(*control));

    /* Initialize motion controller */
    returnValue =
        mpiControlInit(*control);
    msgCHECK(returnValue);

    /* Create adc object */
    *adc =
        mpiAdcCreate(*control,
                     adcNumber);
    msgCHECK(mpiAdcValidate(*adc));
}


/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl  *control,
                    MPIAdc      *adc)
{
    long    returnValue;


    /* Delete adc object */
    returnValue =
        mpiAdcDelete(*adc);
    msgCHECK(returnValue);

    /* Delete motion controller object */
    returnValue =
        mpiControlDelete(*control);
    msgCHECK(returnValue);
}


/* Enable adcs */
void enableAdcs(MPIControl  control,
                long        adcCount)
{
    MPIControlConfig    controlConfig;
    long                returnValue;


    /* Read controller configuration */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    controlConfig.adcCount = adcCount;

    /* Write controller configuration */
    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);
}


/* Configure adc object */
void adcConfigure(MPIAdc    adc,
                  MEIAdcMux input,
                  double    range)
{
    MPIAdcConfig    adcConfig;
    MEIAdcConfig    adcConfigXmp;
    long            returnValue;


    /* Read adc configuration */
    returnValue =
        mpiAdcConfigGet(adc,
                        &adcConfig,
                        &adcConfigXmp);
    msgCHECK(returnValue);

    /* Set voltage range */
    adcConfig.range = range;

    /* Set voltage input */
    adcConfigXmp.mux = input;

    /* Write adc configuration */
    returnValue =
        mpiAdcConfigSet(adc,
                        &adcConfig,
                        &adcConfigXmp);
    msgCHECK(returnValue);
}


/* Display ADC input values */
void displayAdcInput(MPIAdc  adc,
                     long   *buffer,
                     long    bufferSize)
{
#define DISPLAY_REFRESH (50)    /* To avoid console flicker */

    MPIAdcConfig    adcConfig;

    double  adcRange;
    double  adcMean;
    double  sumBuffer   = 0.0;
    long    bufferIndex = 0;
    long    averageSize = 0;
    long    returnValue;


    fprintf(stderr, "Press any key to quit...\n\n");

    /* Read adc configuration */
    returnValue =
        mpiAdcConfigGet(adc,
                        &adcConfig,
                        NULL);
    msgCHECK(returnValue);

    /* Set voltage range */
    adcRange = adcConfig.range;

    while (meiPlatformKey(MPIWaitPOLL) < 0) {

        /* Read ADC input value */
        returnValue =
            mpiAdcInput(adc,
                        (unsigned long*)&buffer[bufferIndex]);
        msgCHECK(returnValue);

        sumBuffer+=buffer[bufferIndex];
        bufferIndex++;
        bufferIndex%=bufferSize;

        if (averageSize < bufferSize) {
            averageSize++;
            adcMean = sumBuffer / averageSize;
        }
        else {
            adcMean = sumBuffer / averageSize;
            sumBuffer-=buffer[bufferIndex];
        }

        if (bufferIndex%DISPLAY_REFRESH == 0) {

            /* Display mean adc input value */
            fprintf(stderr,
                    "Mean of the last %d ADC reads = %lf Volts.   \r",
                    averageSize,
                    adcMean * adcRange / 32767.0);
        }

        /* Wait one controller sample */
        meiControlSampleWait(mpiAdcControl(adc),
                             1);
    }

    fprintf(stderr, "\n\n");

#undef DISPLAY_REFRESH
}


int main(int     argc,
         char   *argv[])
{
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIAdc              adc;

    long    adcBuffer[BUFFER_SIZE];


    /* Perform basic command line parsing. (-control -server -port -trace) */
    basicParsing(argc,
                 argv,
                 &controlType,
                 &controlAddress);

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                &adc,
                ADC_NUMBER);

    /* Enable adcs */
    enableAdcs(control,
               ADC_COUNT);

    /* Configure adc object */
    adcConfigure(adc,
                 ADC_INPUT,
                 ADC_RANGE);

    /* Display ADC input values */
    displayAdcInput(adc,
                    adcBuffer,
                    BUFFER_SIZE);

    /* Perform certain cleanup actions and delete MPI objects */
    programCleanup(&control,
                   &adc);

	return (MPIMessageOK);
}