record3.c -- Interrupt-driven display of data recorder records from specified axis (default 0)
/* record3.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/record3.c 12    7/23/01 2:36p Kevinh $";
#endif

/*

:Interrupt-driven display of data recorder records from specified axis (default 0)

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"

#if defined(ARG_MAIN_RENAME)
#define main    record3Main

argMainRENAME(main, record3)
#endif

/* Command line arguments and defaults */
long    period      = 0;    /* every sample */
long    recordCount = 100;
long    fullCount   = -1;

Arg argList[] = {
    {   "-period",  ArgTypeLONG,    &period,        },
    {   "-records", ArgTypeLONG,    &recordCount,   },
    {   "-full",    ArgTypeLONG,    &fullCount,     },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;                /* motion controller handle */
    MPIAxis     axis[MEIXmpMAX_Axes];   /* axis handles */
    MPIRecorder recorder;               /* data recorder handle */
    MPINotify   notify;                 /* event notification handle */
    MPIEventMgr eventMgr;               /* event manager handle */

    MPIEventMask    eventMask;

    Service     service;    /* service thread */

    long        axisCount;
    long        axisNumber[MEIXmpMAX_Axes]; /* axis numbers */

    MPIRecorderStatus   recorderStatus;
    MPIRecorderRecord   *record;
    register MEIRecorderRecord  *recordPtr;

    long    returnValue;    /* return value from library */

    long    index;

    long    recordingDone;

    long    recordIndex;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

    argIndex =
        argControl(argc,
                   argv,
                   &controlType,
                   &controlAddress);

    /* Parse command line for application-specific arguments */
    while (argIndex < argc) {
        long    argIndexNew;

        argIndexNew = argSet(argList, argIndex, argc, argv);

        if (argIndexNew <= argIndex) {
            argIndex = argIndexNew;
            break;
        }
        else {
            argIndex = argIndexNew;
        }
    }

    if (argIndex >= argc) {
        axisCount       = 1;
        axisNumber[0]   = 0;
    }
    else {
        axisCount = argc - argIndex;

        if (axisCount > MEIXmpMAX_Axes) {
            axisCount = MEIXmpMAX_Axes;
        }

        for (index = 0; index < axisCount; index++) {
            axisNumber[index] = meiPlatformAtol(argv[argIndex++]);
            meiASSERT((axisNumber[index] >= 0) &&
                      (axisNumber[index] < MEIXmpMAX_Axes));
        }
    }

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-period (%d)]\n"
                           "\t\t[-records (%d)]\n"
                           "\t\t[-full (%d)]\n"
                           "\t\t[axisNumber ...]\n",
                           argv[0],
                           ArgUSAGE,
                           period,
                           recordCount,
                           fullCount);
        exit(MPIMessageARG_INVALID);
    }

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

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

    for (index = 0; index < axisCount; index++) {
        axis[index] =
            mpiAxisCreate(control,
                          axisNumber[index]);
        msgCHECK(mpiAxisValidate(axis[index]));
    }


    /* Create and configure recorder object */
    recorder =
        mpiRecorderCreate(control);
    msgCHECK(mpiRecorderValidate(recorder));

    returnValue =
        mpiRecorderRecordConfig(recorder,
                                (MPIRecorderRecordType)MEIRecorderRecordTypeAXIS,
                                axisCount,
                                axis);
    msgCHECK(returnValue);

    returnValue =
        mpiRecorderStatus(recorder,
                          &recorderStatus,
                          NULL);
    msgCHECK(returnValue);

    if (fullCount < 0) {
        fullCount =
            recorderStatus.recordCountMax -
                (recorderStatus.recordCountMax / 4);
    }

    /* Allocate memory for record buffer */
    record =
        (MPIRecorderRecord *)meiPlatformAlloc(sizeof(*record) *
                                              recordCount);
    meiASSERT(record != NULL);

    /* Request notification of all events from recorder */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskRECORDER(eventMask);    /* macro */
    returnValue =
        mpiRecorderEventNotifySet(recorder,
                                  eventMask,
                                  NULL);
    msgCHECK(returnValue);

    /* Create event notification object for recorder */
    notify =
        mpiNotifyCreate(eventMask,
                        recorder);
    msgCHECK(mpiNotifyValidate(notify));

    /* Create event manager object */
    eventMgr =
        mpiEventMgrCreate(control);
    msgCHECK(mpiEventMgrValidate(eventMgr));

    /* Add notify to event manager's list */
    returnValue =
        mpiEventMgrNotifyAppend(eventMgr,
                                notify);
    msgCHECK(returnValue);

    /* Create service thread */
    service =
        serviceCreate(eventMgr,
                      -1,   /* default (max) priority */
                      -1);  /* -1 => enable interrupts */
    meiASSERT(service != NULL);

    /* Start Recorder and wait for Event */
    returnValue =
        mpiRecorderStart(recorder,
                         recordCount,
                         period,    /* period (milliseconds) */
                         fullCount);
    msgCHECK(returnValue);

    recordPtr = (MEIRecorderRecord *)record;
    recordingDone = FALSE;
    while (recordingDone == FALSE) {
        MPIEventStatus  eventStatus;

        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        switch (eventStatus.type) {
            case MPIEventTypeRECORDER_FULL:
            case MPIEventTypeRECORDER_DONE: {
                long    countGet;

                returnValue =
                    mpiRecorderRecordGet(recorder,
                                         recordCount,
                                         (MPIRecorderRecord *)recordPtr,
                                         &countGet);
                msgCHECK(returnValue);

                recordPtr += countGet;

                if (eventStatus.type == MPIEventTypeRECORDER_DONE) {
                    recordingDone = TRUE;
                }
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }
    }

    returnValue = mpiRecorderStop(recorder);
    meiASSERT(returnValue == MPIRecorderMessageSTOPPED);

    /* Ouput all records to console */
    for (recordIndex = 0,
            recordPtr = (MEIRecorderRecord *)record;
         recordIndex < recordCount;
         recordIndex++,
             recordPtr++) {
        printf("record[%d]:\n",
                recordIndex);

        for (index = 0; index < axisCount; index++) {
            printf("axis %d sample %d\tcommand %d\tactual %d\tdac %.4f\n",
                    axisNumber[index],
                    recordPtr->axis[index].sample,
                    recordPtr->axis[index].command,
                    recordPtr->axis[index].actual,
                    recordPtr->axis[index].dac);
        }
    }

    /* Delete recorder */
    returnValue = mpiRecorderDelete(recorder);
    msgCHECK(returnValue);

    /* Free recorder buffer */
    returnValue =
        meiPlatformFree(record,
                        (sizeof(*record) * recordCount));
    meiASSERT(returnValue == MPIMessageOK);

    /* Delete remaining objects */
    for (index = 0; index < axisCount; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

    returnValue = serviceDelete(service);
    msgCHECK(returnValue);

    returnValue = mpiEventMgrDelete(eventMgr);
    msgCHECK(returnValue);

    returnValue = mpiNotifyDelete(notify);
    msgCHECK(returnValue);

    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return ((int)returnValue);
}