quickStart1.c -- Simple point to point motion program for Quick Start procedure.
/* quickStart1.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/quickStart1.c 6     8/01/01 2:08p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    motion1Main

argMainRENAME(main, motion1)
#endif

/*

:Simple point to point motion program for Quick Start procedure.

This is a simple program to demonstrate how to start a trapezoidal profile
 motion on a single axis.  There is a minimal error checking in this sample.

This program presumes the controller is configured so the motors can move
 safely.

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 MOTION_NUMBER   (0)
#define AXIS_NUMBER     (0)

#define END_POSITION    (1000)
#define VELOCITY        (1000)
#define ACCELERATION    (5000)
#define DECELERATION    (5000)


/* 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,
                 MPIMotion          *motion,
                 long                motionNumber,
                 MPIAxis            *axis,
                 long                axisNumber)
{
    long            returnValue;


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

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

    /* Create axis object */
    *axis =
        mpiAxisCreate(*control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(*axis));

    /* Create motion supervisor object with axis */
    *motion =
        mpiMotionCreate(*control,
                        motionNumber,       /* motion supervisor number */
                        *axis);             /* axis object handle */
    msgCHECK(mpiMotionValidate(*motion));
}


/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl      *control,
                    MPIMotion       *motion,
                    MPIAxis         *axis)
{
    long    returnValue;


    /* Delete motion supervisor object */
    returnValue =
        mpiMotionDelete(*motion);
    msgCHECK(returnValue);

    /* Delete axis object */
    returnValue =
        mpiAxisDelete(*axis);
    msgCHECK(returnValue);

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


/* Display positions while waiting for the motion to be done */
void displayPositionsUntilMotionDone(MPIMotion   motion)
{
    MPIStatus   status;
    double      actual;
    double      command;
    long        motionDone;
    long        returnValue;


    /* Poll status until motion done */
    motionDone = FALSE;
    while (motionDone == FALSE) {

        /* Get the motion supervisor status */
        returnValue =
            mpiMotionStatus(motion,
                            &status,
                            NULL);
        msgCHECK(returnValue);

        /* Display position */
        mpiMotionPositionGet(motion,
                             &actual,
                             &command);
        msgCHECK(returnValue);
        printf("Axis[0] Positions: Cmd %11.3lf\tAct %11.3lf\r",
            command,
            actual);

        switch (status.state) {
            case MPIStateSTOPPING:
            case MPIStateMOVING: {
                /* Sleep for 20ms and give up control to other threads */
                meiPlatformSleep(20);
                break;
            }
            case MPIStateIDLE:
            case MPIStateERROR:
            case MPIStateSTOPPING_ERROR: {
                /* Motion is done */
                motionDone = TRUE;
                break;
            }
            default: {
                /* Unknown State */
                fprintf(stderr, "Unknown state from mpiMotionStatus.\n");
                msgCHECK(MPIMessageFATAL_ERROR);
                break;
            }
        }
    }
}


/* Perform a trapezoidal move */
void trapMove(MPIMotion      motion,
              MPITrajectory *trajectory,
              double         position)
{
    MPIMotionParams     params;         /* Motion parameters */
    MPIStatus           status;         /* Status handle */

    long returnValue;


    params.trapezoidal.trajectory   = trajectory;
    params.trapezoidal.position     = &position;

    /* Read motion status */
    returnValue =
        mpiMotionStatus(motion,
                        &status,
                        NULL);
    msgCHECK(returnValue);

    switch (status.state)
    {
        case MPIStateIDLE: {
            /* Start motion */
            returnValue =
                mpiMotionStart(motion,
                               MPIMotionTypeTRAPEZOIDAL,
                               &params);
            msgCHECK(returnValue);

            break;
        }
        case MPIStateSTOPPING:
        case MPIStateMOVING: {
            /* Modify the executing motion profile */
            returnValue =
                mpiMotionModify(motion,
                                MPIMotionTypeTRAPEZOIDAL,
                                &params);
            msgCHECK(returnValue);
            break;
        }
        case MPIStateERROR: {
            /* Error State */
            msgCHECK(MPIMotionMessageERROR);
            break;
        }
        default: {
            /* Unknown State */
            fprintf(stderr, "Unknown state from mpiMotionStatus.\n");
            msgCHECK(MPIMessageFATAL_ERROR);
            break;
        }
    }
}


/* setup move parameters, poll until motion done, start move */
void commandMoves(MPIMotion  motion,
                  double     endPosition,
                  double     velocity,
                  double     acceleration,
                  double     deceleration)
{
    MPITrajectory   trajectory;     /* trajectory information */
    double          command;        /* command position */
    double          position;       /* target position  */

    long            returnValue;    /* MPI return value */


    /* Set up trajectory information */
    trajectory.velocity     = velocity;
    trajectory.acceleration = acceleration;
    trajectory.deceleration = deceleration;

    printf("Press any key to exit...\n\n");

    /* Loop until the user presses a key */
    while (meiPlatformKey(MPIWaitPOLL) < 0) {
        /* Get command position */
        returnValue =
            mpiMotionPositionGet(motion,
                                 NULL,
                                 &command);
        msgCHECK(returnValue);

        if (command != 0.0) {
            position = 0.0;

        }
        else    {
            position = endPosition;
        }

        /* Perform a trapezoidal move */
        trapMove(motion,
                 &trajectory,
                 position);

        /* Display positions while waiting for the motion to be done */
        displayPositionsUntilMotionDone(motion);
    }
    printf("\n");
}


int main(int    argc,
         char   *argv[])
{
    MPIControl          control;    /* motion controller object handle */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotion           motion;     /* motion object handle */
    MPIAxis             axis;       /* axis object handle */


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

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                &motion,
                MOTION_NUMBER,
                &axis,
                AXIS_NUMBER);

    /* Command some moves */
    commandMoves(motion,
                 END_POSITION,
                 VELOCITY,
                 ACCELERATION,
                 DECELERATION);

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

    return MPIMessageOK;
}