.

     

MPI Application Template
template.c
 

UsrLim1.c -- User Limit to watch an input bit and set an output bit.
/* UsrLim1.c */

/* Copyright(c) 1991-2006 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.
 */

/*

:User Limit to watch an input bit and set an output bit.

This sample code shows how to configure the XMP controller's User Limits
 to compare an input bit to a specific pattern.  If the pattern matches,
 then the specified output bit is activated and a User Event is generated
 to the host.


The XMP-Series controller "User Limit" feature allows the user to program a
 the result of two logical condition to generate an event to the host.  Also,
 a "User Limit" can be configured to write an "output" to any XMP memory
 location, using an AND mask and OR mask.

Here is the "User Limit" block structure:

typedef struct {
    MPIXmpLimitType         Type;
    void                    *SourceAddress;
    long                    Mask;
    MPIXmpGenericValue      LimitValue;
} MPIXmpLimitCondition;

typedef struct {
    long                    AndMask;
    long                    OrMask;
    long                    *OutputPtr;
    long                    Enabled;
} MPIXmpLimitOutput;

typedef struct {
    MPIXmpLimitCondition    Condition[MPIXmpLimitConditions];
    MPIXmpStatus            Status;
    MPIXmpLogic             Logic;
    MPIXmpLimitOutput       Output;
    long                    Count;
    long                    State;
} MPIXmpLimitData;


MPIXmpLimitTypes are the operators that are used for the User Limit's
 Condition[0] and Condition[1].  They are found in xmp.h.

*SourceAddress is a pointer to an XMP memory location.

Mask is ANDed with the value located at the *SourceAddress.

LimitValue is compared with the masked value located at *SourceAddress,
 using the Type operator.

Status defines the status bit used to generate an event to the host.

MPIXmpLogic is the logic applied between the two condition block outputs,
 Condition[0] and Condition[1]:

 MPIXmpLogicNEVER
    Does NOT evaluate Condition[0], Condition[1].  No event is generated.

 MPIXmpLogicSINGLE
    Only evaluates Condition[0].  Event is generated if Condition[0] is TRUE.

 MPIXmpLogicOR
    Evaluates Condition[0], Condition[1].  Event is generated if (Condition[0]
    OR Condition[1]) = TRUE.

 MPIXmpLogicAND
    Evaluates Condition[0], Condition[1].  Event is generated if (Condition[0]
    AND Condition[1]) = TRUE.

The other MPIXmpLogic enums in xmp.h are for internal use only.

*OutputPtr is a pointer to an XMP memory location.

AndMask is ANDed, and OrMask is ORed with the value located at
 *OutputPtr when the resultant MPIXmpLogic applied Condition[0] and
 Condition[1] are TRUE.

Count and State are for internal use only.  Do not write these values.
  The MPI method, mpiMotorEventConfigSet(...) will not write these values.


The XMP supports up to 16 User Limits per motor.  The User Limit processing
 occurs in the firmware background task.  For maximum efficiency, the XMP only
 processes the User Limits (in order 0, 1, 2, etc.), up to the largest User
 Limit number that has (motorEventConfig.Logic ! = MPIXmpLogicNEVER).

For example:
 If UserLimit 0 (motor 0) is configured for MPIXmpLogicSINGLE, then the XMP will
    only process the first UserLimit for each motor.
 If UserLimit 3 (motor 0) is configured for MPIXmpLogicSINGLE, then the XMP will
    process UserLimits number 0, 1, 2, and 3 for each motor.

It's best to use the lower numbered UserLimits for maximum efficiency.  When
 finished using UserLimits, it's a good idea to set the Logic to
 MPIXmpLogicNEVER.

Warning!  This is a sample program to assist in the integration of an
 MEI 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 "sqNodeLib.h"

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    UsrLim1Main

argMainRENAME(main, UsrLim1)
#endif


/* Motor I/O Configurations */
#define INPUT_BIT       (MPIMotorGeneralIo2)    /* index to input bit #2 */
#define INPUT_MASK      (0x4)                /* mask for input bit #2 */
#define ACTIVE_STATE    (FALSE)                     /* trigger on active or inactive */

#define OUTPUT_BIT      (MPIMotorGeneralIo1)    /* index to output bit #1 */
#define OUTPUT_MASK     (0x1)                /* mask for output bit #1 */

/* User Limit Event configuration */
#define EVENT_TYPE      (MPIEventTypeLIMIT_USER0)   /* 0, 1, 2...7 */

/* Notify Wait Timeout */
#define CYCLE_TIME          (100)                   /* msec */

/* Command line arguments and defaults */
long            motorNumber     = 0;

Arg argList[] = {
    {   "-motor",   ArgTypeLONG,    &motorNumber,   },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Function Prototypes */
long XcvrUserLimitSet(MPIMotor motor,
                      long inputMask,
                      long inputActiveState,
                      long outputMask,
                      MPIEventType eventType);


int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIAxis     axis;       /* axis object */
    MPIMotion   motion;     /* motion object */
    MPIMotor    motor;      /* motor object */
    MPINotify   notify;     /* event notification object */
    MPIEventMgr eventMgr;   /* event manager handle */

    MPIEventMask    eventMask;

    MPIMotorConfig  motorConfigXmp;  /* XMP motor I/O configuration */

    long    motionNumber;   /* motion supervisor number */
    long    axisNumber;
    long    returnValue;    /* return value from library */

    Service service;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

    /* Parse command line for Control type and address */
    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (motorNumber >= MPIXmpMAX_Motors)) {
        mpiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MPIXmpMAX_Axes - 1,
                            MPIXmpMAX_MSs - 1,
                            MPIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Use a one to one relationship between motor, axis, and motion */
    motionNumber = motorNumber;
    axisNumber = motorNumber;

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

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

    /* Create motor object for motorNumber */
    motor =
        mpiMotorCreate(control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(motor));

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

    /* Create motion object, appending the axis object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axis);
    msgCHECK(mpiMotionValidate(motion));

    /* Request notification of ALL events from motion */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    mpiEventMaskALL(eventMask);

    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

    /* Create event notification object for motion */
    notify =
        mpiNotifyCreate(eventMask,
                        motion);
    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 */
    mpiAssert(service != NULL);

    /* Configure the specified INPUT_BIT */
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    motorConfigXmp.Io[INPUT_BIT].Type = MPIMotorIoTypeINPUT ;

    returnValue =
        mpiMotorConfigSet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    /* Configure the specified OUTPUT_BIT */
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    motorConfigXmp.Io[OUTPUT_BIT].Type = MPIMotorIoTypeOUTPUT;

    returnValue =
        mpiMotorConfigSet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    /* Configure User Limit */
    returnValue =
        XcvrUserLimitSet(motor,
                         INPUT_MASK,
                         ACTIVE_STATE,
                         OUTPUT_MASK,
                         EVENT_TYPE);
    msgCHECK(returnValue);

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

    /* Loop repeatedly */
    while (mpiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MPIEventStatusInfo  *info;

        /* Wait for events */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               (MPIWait)CYCLE_TIME);

        if (returnValue == MPIMessageTIMEOUT) {     /* ignore timeouts */
            returnValue = MPIMessageOK;
        }
        else {
            msgCHECK(returnValue);

            info = (MPIEventStatusInfo *)eventStatus.info;

            switch (eventStatus.type) {
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER0: {
                    printf("\nUser Limit #0, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER1: {
                    printf("\nUser Limit #1, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER2: {
                    printf("\nUser Limit #2, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER3: {
                    printf("\nUser Limit #3, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER4: {
                    printf("\nUser Limit #4, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER5: {
                    printf("\nUser Limit #5, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER6: {
                    printf("\nUser Limit #6, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
                /* User Limit Event from motor source */
                case MPIEventTypeLIMIT_USER7: {
                    printf("\nUser Limit #7, type %d source 0x%x info 0x%x",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }

                default: {
                    printf("mpiNotifyEventWait() returns 0x%x\n"
                        "\teventStatus: type %d source 0x%x info 0x%x\n",
                        returnValue,
                        eventStatus.type,
                        eventStatus.source,
                        eventStatus.info[0]);
                    break;
                }
            }
        }
    }

    printf("\n");

    /* Delete objects */
    returnValue = serviceDelete(service);
    msgCHECK(returnValue);

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

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

    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axis);
    msgCHECK(returnValue);

    returnValue = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


long XcvrUserLimitSet(MPIMotor motor,
                      long inputMask,
                      long inputActiveState,
                      long outputMask,
                      MPIEventType eventType)
{
    MPIControl          control;

    MPIXmpData          *firmware;


    MPIMotorLimitConfig motorEventConfig;
    MPIXmpStatus        status;

    long                returnValue;
    long                motorIndex;
    MPIEventMask        resetMask;

    /* Determine motor number */
    returnValue =
        mpiMotorNumber(motor,
                       &motorIndex);

    /* Determine control handle */
    if(returnValue == MPIMessageOK) {
        control = mpiMotorControl(motor);
        returnValue = mpiControlValidate(control);
    }

    /* Get pointer to XMP firmware */
    if(returnValue == MPIMessageOK) {
        returnValue =
            mpiControlMemory(control,
                             (void **)&firmware,
                             NULL);
    }

    mpiEventMaskCLEAR(resetMask);

    if (returnValue == MPIMessageOK) {
        switch (eventType) {
            case MPIEventTypeLIMIT_USER0: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER0);
                break;
            }
            case MPIEventTypeLIMIT_USER1: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER1);
                break;
            }
            case MPIEventTypeLIMIT_USER2: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER2);
                break;
            }
            case MPIEventTypeLIMIT_USER3: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER3);
                break;
            }
            case MPIEventTypeLIMIT_USER4: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER4);
                break;
            }
            case MPIEventTypeLIMIT_USER5: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER5);
                break;
            }
            case MPIEventTypeLIMIT_USER6: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER6);
                break;
            }
            case MPIEventTypeLIMIT_USER7: {
                status = MPIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MPIEventTypeLIMIT_USER7);
                break;
            }
            default:
                printf("\nError, invalid event type\n");
                break;
        }

        returnValue =
            mpiMotorEventConfigGet(motor,
                                   (MPIEventType)eventType,
                                   NULL,
                                   &motorEventConfig);
    }

    if (returnValue == MPIMessageOK) {
        /* Set up the Condition[0] block.  The operator between the value in
            the SourceAddress (masked by the Mask), and LimitValue.l, is
            MPIXmpLimitTypeBIT_CMP (equals).  Thus, when the value in
            SourceAddress equals the value in LimitValue.l, then the
            Condition[0] block is TRUE.
        */
        motorEventConfig.Condition[0].Type = MPIXmpLimitTypeBIT_CMP;
        motorEventConfig.Condition[0].SourceAddress =
            &firmware->Motor[motorIndex].IO.GeneralIn.IO;   /* General purpose motor input address */
        motorEventConfig.Condition[0].Mask = inputMask;     /* AND mask */
        motorEventConfig.Condition[0].LimitValue.g32.l =
            inputActiveState ? inputMask : 0x0;             /* expected value */

        /* Set up the Condition[1] block.  The operator is MPIXmpLimitTypeFALSE.
            Therefore, the Condition[1] block is always FALSE.
        */
        motorEventConfig.Condition[1].Type = MPIXmpLimitTypeFALSE;
        motorEventConfig.Condition[1].SourceAddress = NULL;
        motorEventConfig.Condition[1].Mask = 0;
        motorEventConfig.Condition[1].LimitValue.g32.l = 0;

        motorEventConfig.Status = status;
        /* Determine logic result from Condition[0] only */
        motorEventConfig.Logic  = MPIXmpLogicSINGLE;

        motorEventConfig.Output.OutputPtr =
            &firmware->Motor[motorIndex].IO.MotorOutput; /* General purpose motor output address */
        motorEventConfig.Output.AndMask = 0xffffffff;
        motorEventConfig.Output.OrMask = outputMask;
        motorEventConfig.Output.Enabled = TRUE;

        returnValue =
            mpiMotorEventConfigSet(motor,
                                   (MPIEventType)eventType,
                                   NULL,
                                   &motorEventConfig);
    }

    /* Reset event in case conditions have already been satisfied */
    if (returnValue == MPIMessageOK) {
        returnValue =
                mpiMotorEventReset(motor,
                                   resetMask);
    }

    return returnValue;
}


      
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2009 Motion Engineering