MEI's On-line Documentation System

Copyright © 2002 Motion Engineering
Copyright Notice
 Questions or comments about our
site? Please contact supportfeedback.
last updated: 18Mar2002


Motion Engineering, Inc. | Copyright Notice© 1995-2001

Legal Notice

COPYRIGHT

Copyright Motion Engineering, Inc., 1995-2002. All Rights Reserved.

CONTENT AND LIABILITY DISCLAIMER

MEI shall not be responsible for any errors or omissions contained at this Web Site, and reserves the right to make changes without notice. Accordingly, all MEI and third party information is provided "AS IS."

MEI DISCLAIMS ALL WARRANTIES WITH REGARD TO THE INFORMATION (INCLUDING ANY SOFTWARE) PROVIDED, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU.

In no event shall MEI be liable for any damages whatsoever, and in particular MEI shall not be liable for special, indirect, consequential, or incidental damages, or damages for lost profits, loss of revenue, or loss of use, arising out of or related to the MEI Web Site or the information contained in it, whether such damages arise in contract, negligence, tort, under statute, in equity, at law or otherwise.

This Web Site contains proprietary and confidential information of Motion Engineering, Inc., and is protected by federal copyright law. The contents of the Web Site may not be disclosed to third parties, translated, copied, or duplicated in any form, in whole or in part, without the express written permission of Motion Engineering, Inc.


How to use this Site

We have taken great strides to make the transition from a static, paper-type format to a dynamic, web-based format. We believe that this site will substantially improve your ability to navigate through our documentation. Finding the right information has never been faster or easier. But, before you can fully take advantage of the features on this site, there are a few things that you need to know that will help you optimize your time and effort.

System Recommendations

It is recommended that you use a version of Microsoft Internet Explorer (IE) 5.0+ browser to view this site. Although you will be able to view the pages with alternate browsers like Netscape Communicator, we have optimized our site for IE. You can download the latest version of Internet Explorer for FREE at http://www.microsoft.com/windows/ie/.

Site Architecture: Software | Sample Applications | Hardware | Utilities | PDF / Notes
Printing | Searching

Site Architecture

This site has been organized into five core sections (manuals): Software, Sample Applications, Hardware, Utilities, and PDFs / Notes. Each core section may have up to four subsections, which will appear as clickable tabs below the main header. The Tech E-mail tab will appear on each section (except for PDF / Notes). This will link to a form page that will allow you to email our Technical Support team at MEI, provided that an Internet connection is available. Each core section (except for PDF / Notes) will have a "Download PDF" icon to the right of the subsection tabs. This icon will either be a direct link to its pdf version, or a link to a page that will list various pdfs of that particular section. (The PDF / Notes section is a compilation of all pdfs.) At any time, you may click on the MEI logo to return to the start page.

Software

The Software section replaces the Software Reference Manual. This is where you can find information about each object, and look up various data types and methods. The tabs allow you to search by Object, Data Type, or Method. By its nature, this section is a comprised of several navigational tools; therefore, it does not have a keyword search like its Hardware and Utilities counterparts. The MPI Library Basics section is a valueable resource for users that are new to the MPI library and its object-oriented programming. These links will help any user become familiar with MEI's nomenclature and structure so that the reading and writing of code becomes more intuitive. The Topics and Sercos sections provide additional information on more advanced topics and Sercos-specific issues.

The Search by Object page, also lists all of the objects that makeup our MPI Library. You can click on any Object and it will take you to that Object's home page. Each object home page will have a description of that object, and a functional breakdown of all the Methods, Data Types, Constants, and Macros.

The Search by Data Type and Search by Method pages provide conditional pulldowns. Each of the 180+ data types and 510+ methods have their own description page, which includes the structure, a brief description, returns, and other relevant links. You can reach these pages by one of two routes. The example below shows 2 different ways of getting to mpiCompareFlashConfigGet.

Sample Applications

The Sample Applications section replaces the Sample Applications Manual. This is a collection of several C-coded applications that demonstrate various functions. This is a good resource to use when you are writing your own application. There are two different ways of finding a specific application.

  • Application Index - lists the applications alphabetically by their filename.
  • Select by Function - lists the applications according to the type of function they demonstrate.
To view an application, simply click on it and you will be taken to an html version of the code. You can copy and paste code directly from these pages into your own code.

Hardware

The Hardware section replaces the Hardware Installation Manual. This section details the proper installation of an XMP controller. Many users find it useful to have a printed copy of this section. You can always print out a copy of the Hardware Intallation Manual by using the pdf version. This section has provides three ways of finding information. You may browse through the pages using the Table of Contents, perform a Keyword Search, or look up a word in the Index.

Utilities

The Utilities section replaces the XMP Software and Utilities Guide. Each chapter explains how to use each of our Utility tools: Motion Console, Motion Scope, VM3, and XMP Configuration Utility. A Keyword Search that searches within the Utilities section is also available.

PDF / Notes

The PDF/Notes section is a compilation of all the pdfs that are available of the documentation. The pdfs are divided into the following sections: Manuals, Release Notes, and Application Notes. This page also includes a few PowerPoint (ppt) presentations and an HTML Help file of our website.

To access a pdf, simply click on the icon. If you are using a pdf-supported browser, the selected pdf will open inside a new browser window.

To access a ppt, simply click on the icon. If you are using IE, the ppt will open inside a new browser window. If you are using Netscape, you will be prompted to open the file in PowerPoint. Likewise, if you prefer viewing the ppt presentations within PowerPoint, you may save the file and open it within PowerPoint.

To Save the file, right click on the icon, select Save Target As and save the file to a desired location like the Desktop. Open the file in PowerPoint.

The HTML Help file is extremely useful for software programmers who frequently use MSDN as a resource when writing code. The HTML Help file (support_motioneng.chm) can be used as a standalone file, or it can be integrated with MSDN. This is the best way to perform global searches of the documentation. Also, this will allow you to select an MEI-specific term like MPIMotorConfig in MS Visual Studio, hit F1, and the documentation for that data type will appear within MSDN! For more information about how to integrate MEI's documentation with MSDN, click here.

Printing

It is recommended that you use the pdfs for most print jobs. Although you can print pages from the browser, you will get the most consistent and reliable results from the pdf versions. If you do print within the browser window, it is important to click in the area of the page you want to print. Since the site uses frames in its design, you may accidentally print the wrong frame. To ensure that you print the appropriate frame, simply click inside the main body frame (on the text you want to print) to tell the browser which frame you want to print and go File > Print. The quality of a print job is NOT affected by whether or not you print using the browser's print feature or Acrobat Reader's print feature. Both print jobs will yield the same results.

Searching

The Hardware and Utilities sections have search engines that are specific to their section. Although there is currently no global search on the website, you can perform effective global searches by using the HTML Help files. See the section on HTML Help.


Integration with MSDN

Integrate MEI's
HTML Help file with the MSDN library!

Why should I integrate with MSDN?

Many software programmers who author code using MS Visual Studio are accustomed to using the MSDN library as one of their main resource tools. By integrating MEI's HTML Help with MSDN, you will be able to perform global searches and use the F1 button within MS Visual Studio for MEI-specific terms.

How do I integrate with MSDN?

    Step 1
    Download a freeware program from the web called MSDN Integration Utility. Go to http://www.codeproject.com/winhelp/msdnintegrator.asp and click on the MSDN Integration Utility link.

    If you have not already downloaded the necessary MEI's HTML Help files (support_motioneng.chi and support_motioneng.chm), go to http://support.motioneng.com/pdf_notes/main_frame.html and download them to your computer.

    Step 2
    Click on the MSDNIntegrator.exe file. The following window should appear.

Step 3
Locate the support_motioneng.chi and support_motioneng.chm files. Insert a Title for the new library that you're adding to MSDN, and insert a Unique Identifier for the library.

Step 4
Click the Integrate with MSDN button.

Step 5
Open the MSDN Library. You should now see MEI's On-line Documentation library as an option.
CONGRATULATIONS! You have successfully integrated MEI's On-line Documentation into MSDN!


MotionEng-Tech. Support

 this site requires frames to be enabled


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);
}


adc2.c -- Determine scale and offset calibration for Analog to Digital converter input.
/* adc2.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/adc2.c 5     8/01/01 2:08p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    adc2Main

argMainRENAME(main, adc2)
#endif

/*

:Determine scale and offset calibration for Analog to Digital converter input.

This sample code demonstrates how to determine calibration factors for
 an ADC input channel.  This sample requires an external source to generate
 the analog voltage into an ADC channel.

The calibration factors are determined by sampling two known voltages.
 The default voltages are 5 volts and -5 volts.  Other voltages can be set by
 changing the definitions of the #define's LINE_VOLTAGE_1 and LINE_VOLTAGE_2.
 This default input lines are Analog_IN_0 and Analog_IN_1.  These can be changed
 by changing the definitions of the #define's LINE_INPUT_1 and LINE_INPUT_2.

ATTENTION: The uncertanties of the input voltage lines should also be specified
 for an accurate analysis.  The smaller these uncertainties, the better analysis
 you will receive.  The default values are 0.01 Volts and can be specified by
 changing the #define's LINE_VOLTAGE_UNCERTAINTY_1 and
 LINE_VOLTAGE_UNCERTAINTY_2.

Using the ADC values, voltage values, and uncertainties, displayAdcAnalysis()
 determines the linear "scale" factor (m) and the "offset" (b).  These
 calibration factors can be applied to future ADC value conversions in
 application code, to improve the ADC accuracy and analysis of the values read.

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 <math.h>

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

#include "apputil.h"

#define ADC_COUNT       (8)

#define ADC_RANGE                   (10.0)  /* 10.0, 5.0, 2.5, or 1.25 volts */
#define LINE_VOLTAGE_1              (5.00)
#define LINE_VOLTAGE_2              (-5.00)
#define LINE_VOLTAGE_UNCERTAINTY_1  (0.01)
#define LINE_VOLTAGE_UNCERTAINTY_2  (0.01)

#define LINE_INPUT_1        (MEIAdcMuxANALOG_IN_0)
#define LINE_INPUT_2        (MEIAdcMuxANALOG_IN_1)

#define SAMPLES     (1000)  /* Samples per input line */

/* 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                adcCount)
{
    long index;
    long returnValue;

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

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

    /* Create adc objects */
    for (index = 0; index < adcCount; index++) {
        adc[index] =
            mpiAdcCreate(*control,
                         index);
        msgCHECK(mpiAdcValidate(adc[index]));
    }
}

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

    /* Delete adc objects */
    for (index = 0; index < adcCount; index++) {
        returnValue =
            mpiAdcDelete(adc[index]);
        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);
}

/* Calculate stastical input information */
void getAdcInputInfo(MPIAdc *adc,
                     long    adcCount,
                     long    samples,
                     double *inputMean,
                     double *inputVar)
{
    MPIAdcConfig    adcConfig;

    double sumInput   = 0.0;
    double sumInputSq = 0.0;

    long input;
    long index;
    long returnValue;

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

    for (index=0; index<samples; index++) {

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

        /* Record input information */
        sumInput+=input;
        sumInputSq+=input * 1.0 * input;

        if (index%adcCount == 0) {
            /* Wait one controller sample */
            meiControlSampleWait(mpiAdcControl(adc[0]),
                                 1);
        }
    }

    /* Calculate stastical input information */
    *inputMean = sumInput / samples;
    *inputVar = (sumInputSq - (sumInput*sumInput)/samples)/(samples-1);
}

/* Display ADC analysis */
void displayAdcAnalysis(double *lineVoltage,
                        double *lineUncertainty,
                        double *inputMean,
                        double *inputVar)
{
    double b;
    double bStdDev;
    double m;
    double mStdDev;
    double deltaInput;
    double deltaInputSq;

    deltaInput = inputMean[1] - inputMean[0];
    deltaInputSq = deltaInput * deltaInput;

    b = (lineVoltage[0]*inputMean[1] - lineVoltage[1]*inputMean[0]) /
            deltaInput;

    m = (lineVoltage[1] - lineVoltage[0]) / deltaInput;

    bStdDev = sqrt(
        ((b - lineVoltage[1])*(b - lineVoltage[1])*inputVar[0] +
            (b - lineVoltage[0])*(b - lineVoltage[0])*inputVar[1] +
            inputMean[0]*inputMean[0]*lineUncertainty[1]*lineUncertainty[1] +
            inputMean[1]*inputMean[1]*lineUncertainty[0]*lineUncertainty[0]) /
        deltaInputSq);

    mStdDev = sqrt(
        (m*m*(inputVar[0] + inputVar[1]) +
            lineUncertainty[0]*lineUncertainty[0] +
            lineUncertainty[1]*lineUncertainty[1]) /
        deltaInputSq);

    printf("Voltage = m * (ADC input) + b\n\n"
           " m = %le +/- %le \t(Volts/ADC_UNIT)\n"
           " b = %le +/- %le \t(Volts)\n\n",
           m, mStdDev,
           b, bStdDev);
}

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

    double  inputMean[2];
    double  inputVar[2];
    double  lineVoltage[2]  =
        {LINE_VOLTAGE_1, LINE_VOLTAGE_2};
    double  lineUncertainty[2] =
        {LINE_VOLTAGE_UNCERTAINTY_1, LINE_VOLTAGE_UNCERTAINTY_2};

    long    index;

    /* 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_COUNT);

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

    /* Configure adc objects to read LINE_INPUT_1 */
    for (index = 0; index < ADC_COUNT; index++) {
        adcConfigure(adc[index],
                     LINE_INPUT_1,
                     ADC_RANGE);
    }

    /* Delay so that adc object can read values from  LINE_INPUT_1 */
    meiPlatformSleep(1);

    /* Calculate stastical input information for LINE_INPUT_1 */
    getAdcInputInfo(adc,
                    ADC_COUNT,
                    SAMPLES,
                    &inputMean[0],
                    &inputVar[0]);

    /* Configure adc objects to read LINE_INPUT_2 */
    for (index = 0; index < ADC_COUNT; index++) {
        adcConfigure(adc[index],
                     LINE_INPUT_2,
                     ADC_RANGE);
    }

    /* Delay so that adc object can read values from  LINE_INPUT_1 */
    meiPlatformSleep(1);

    /* Calculate stastical input information for LINE_INPUT_2 */
    getAdcInputInfo(adc,
                    ADC_COUNT,
                    SAMPLES,
                    &inputMean[1],
                    &inputVar[1]);

    /* Display ADC analysis */
    displayAdcAnalysis(lineVoltage,
                       lineUncertainty,
                       inputMean,
                       inputVar);

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

    return (MPIMessageOK);
}


adcFBak.c -- Set up an axis to use analog (ADC) position feedback
/* adcfbak.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.
 */

/*

:Set up an axis to use analog (ADC) position feedback

  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    adcfbakMain

argMainRENAME(main, adcfbak)
#endif

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

Arg argList[] = {
    {   "-adc", ArgTypeLONG,    &adcNumber, },

    {   NULL,   ArgTypeINVALID, NULL,   }
};

#define ADC_COUNT           (1)     /* Configure controller to read 'n' ADCs */
#define ADC_BUFFER_SIZE     (100000)
#define ADC_RANGE           (10.0)  /* 10.0, 5.0, 2.5, or 1.25 volts */

#define AXIS_NUMBER         (0)

long
    axisAnalogFeedbackSet(MPIAxis   axis,
                              long      adcNumber);

int
    main(int    argc,
         char   *argv[])
{

    long    returnValue;
    long    argIndex;

    MPIControl          control;        /* Motion controller handle */
    MPIControlConfig    controlConfig;  /* Controller configuration */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIAxis             axis;
    MPIAdc              adc;
    MPIAdcConfig        adcConfig;

    /* 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) ||
        (adcNumber >= MEIXmpMAX_ADCs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-adc # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_ADCs - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* 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,
                      AXIS_NUMBER);     /* axis number */
    msgCHECK(mpiAxisValidate(axis));

    /* Set the number of ADCs */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    controlConfig.adcCount = ADC_COUNT;     /* Enable 'n' ADCs */

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

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

    /* Configure the ADC */
    returnValue =
        mpiAdcConfigGet(adc,
                        &adcConfig,
                        NULL);
    msgCHECK(returnValue);

    adcConfig.range = ADC_RANGE;    /* Voltage range */

    printf("\nADC Voltage Range: +/- %3.1lf volts\n",
            adcConfig.range);

    returnValue =
        mpiAdcConfigSet(adc,
                        &adcConfig,
                        NULL);
    msgCHECK(returnValue);

    returnValue =
        axisAnalogFeedbackSet(axis,
                              adcNumber);

    /* Delete the Adc handle */
    returnValue = mpiAdcDelete(adc);
    msgCHECK(returnValue);

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

    /* Delete the Control handle */
    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return (returnValue);
}

long
    axisAnalogFeedbackSet(MPIAxis   axis,
                              long  adcNumber)
{
    MPIControl      control;
    MEIXmpData      *firmware;
    MPIAxisConfig   axisConfig;         /* axis configuration MPI */
    MEIAxisConfig   axisConfigXmp;      /* axis configuration XMP */

    long        returnValue;

    control = mpiAxisControl(axis);
    msgCHECK(mpiControlValidate(control));

    /* Get pointer to XMP firmware */
    returnValue =
        mpiControlMemory(control,
                         &firmware,
                         NULL);

    /* Configure axes: Gantry front end */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);

    axisConfigXmp.APos[0].Ptr    = &firmware->ADC[adcNumber].Input;

    /* Set axis configuration */
    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);
    return (returnValue);
}


ampFlt1.c -- Configure the amp fault input.
/* ampflt1.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/ampflt1.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Configure the amp fault input.

The program will configure the amp fault input for a motor.

  A motor's amp fault input has four items to configure:

  1) Event Action   (any MPIAction such as MPIActionE_STOP)
  2) Event Trigger  (a trigger polarity, active HIGH or LOW)
  3) Direction Flag (TRUE will cause the command direction of motion to
                     qualify the events,    FALSE will ignore direction,
                     based solely on the limit input state)
  4) Duration       (requires the limit condition to exist for
                     a programmable number of seconds before an
                     event will occur)

The duration configuration provides filtering of the amp fault input by requiring the input to
remain active for the defined duration.  This will effectively keep the amp fault from activating prematurely
due to electrical noise on the amp fault input.

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  ACTIVE_HIGH    (1)
#define  ACTIVE_LOW     (0)

#if defined(ARG_MAIN_RENAME)
#define main    ampflt1Main

argMainRENAME(main, ampflt1)
#endif

/* Command line arguments and defaults */
long            axisNumber      = 0;
long            motionNumber    = 0;
long            motorNumber     = 0;
float           ampfaultduration= (float)5.0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-motor",   ArgTypeLONG,    &motorNumber,   },
    {   "-duration",ArgTypeFLOAT,   &ampfaultduration,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

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

    Service service;

    MEIXmpData  *firmware;

    MPIMotorEventConfig eventConfig;

    long    messageCount;

    long    returnValue;    /* return value from library */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIEventMask        eventMask;

    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) ||
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motorNumber  >= MEIXmpMAX_Motors) ||
        (ampfaultduration  < 0)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-duration # (>0)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle. */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Get pointer to XMP firmware */
    returnValue =
        mpiControlMemory(control,
                         (void**)&firmware,
                         (void**)NULL);
    msgCHECK(returnValue);

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

    /* Create motor object using axisNumber on controller */
    motor =
        mpiMotorCreate(control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(motor));

    /* Create motion supervisor object using MS number */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axis);
    msgCHECK(mpiMotionValidate(motion));

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    meiEventMaskALL(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 */
    meiASSERT(service != NULL);

    /* Get configuration for ampfault event */
    returnValue =
        mpiMotorEventConfigGet(motor,
                               MPIEventTypeAMP_FAULT,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Event Action, configure to ABORT on Amp Fault Input */
    eventConfig.action = MPIActionABORT;

    /* Event trigger, set trigger level to Active Low */
    eventConfig.trigger.polarity = ACTIVE_LOW;

    /* Direction Flag, do not use commanded velocity direction as a trigger qualifier */
    eventConfig.direction = FALSE;

    /* Duration, wait ampfaultduration seconds before triggering */
    eventConfig.duration = ampfaultduration;

    returnValue =
        mpiMotorEventConfigSet(motor,
                               MPIEventTypeAMP_FAULT,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    meiPlatformConsole("amp fault duration and polarity configured: wait for events.\n");

    messageCount = 0;

    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus  eventStatus;

        long    motorNumber;

        /* Wait for event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        messageCount++;

        motorNumber = ((MEIEventStatusInfo *)eventStatus.info)->type.number;

        printf("Event! (%d) Type = %d \n",
               messageCount,
               eventStatus.type);

        switch (eventStatus.type) {
            case MPIEventTypeAMP_FAULT: {

                printf("Amp Fault has occurred on motor # %d\n",motorNumber);
                printf("Resetting...\n");

                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                meiASSERT(returnValue == MPIMessageOK);

                break;
            }
            default: {
                break;
            }
        }
    }

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

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

    returnValue = mpiAxisDelete(axis);
    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);
}


anticol1.c -- Program Sequencer aborts axes prior to a collision (anti-collision protection)
/* anticol1.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/Anticol1.c 6     7/23/01 2:36p Kevinh $";
#endif

/*

:Program Sequencer aborts axes prior to a collision (anti-collision protection)

This sample program provides anti-collision protection for two axes that move
 along the same physical space.  The program creates a program sequencer that
 will continually monitor the relative actual positions of two axes.  When the
 relative positions get closer than a defined tolerance (defined at the top of
 the program as DIFFERENCE_TOLEARNCE) the axes will be aborted by the program
 sequencer.

The XMP program sequencer controls the execution of a single command or a
 series of commands on the XMP controller.  The program sequencer provides the
 ability to execute programs directly on the XMP controller without host
 intervention.  Examples of individual commands that can be executed by the
 program sequencer are motion, looping, conditional branching, computation,
 reading and writing of memory, time delays, waiting for conditions, setting
 inputs/outputs, and generation of events.  This rich command set provides
 capability similar to, and beyond, that provided by Programmable Logic
 Controller (PLC) programs.

From anticol1c.c (8/1/1999)

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    anticol1Main

argMainRENAME(main, anticol1)
#endif

#define AXIS_COUNT              (2)
#define DIFFERENCE_TOLERANCE    (7000)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
long            sequenceNumber  = 0;
long            differenceTolerance = DIFFERENCE_TOLERANCE;

Arg argList[] = {
    {   "-axis",        ArgTypeLONG,    &axisNumber[0],         },
    {   "-motion",      ArgTypeLONG,    &motionNumber,          },
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,        },
    {   "-tolerance",   ArgTypeLONG,    &differenceTolerance,   },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

                        /* COMPUTE + BRANCH + BRANCH + ABORT = 4 */
MPICommand  CommandTable[4];
#define COMMAND_COUNT   (sizeof(CommandTable) / sizeof(MPICommand))

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIMotion   motion;             /* motion handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handles */
    MPISequence sequence;           /* sequence handle */

    MPICommandParams    commandParams;  /* command parameters */

    long    returnValue;    /* return value from library */

    long    commandIndex;   /* CommandTable[] index */
    long    index;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MEIXmpData          *firmware;
    MEIPlatform         platform;   /* platform handle */
    MEIXmpBufferData    *xmpBufferData;
    long                *addressActPos1;
    long                *addressActPos2;
    long                address;
    long                *allocPointer;
    long                difference;
    long                *addressDifferenceStored;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0]  > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber   >= MEIXmpMAX_MSs) ||
        (sequenceNumber >= MEIXmpMAX_PSs) ||
        (differenceTolerance < 0)){

        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[-tolerance # ( larger than 0)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_PSs - 1);

        exit(MPIMessageARG_INVALID);
    }

    axisNumber[1] = axisNumber[0] + 1;

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

    /* Initialize motion controller */
    returnValue = mpiControlInit(control);
    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiControlInit() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(1);
    }

    /* Get pointer to XMP firmware */
    returnValue =
        mpiControlMemory(control,
                         &firmware,
                         &xmpBufferData);
    msgCHECK(returnValue);

    platform =
        meiControlPlatform(control);
    msgCHECK(meiPlatformValidate(platform));

    /*Pointer into xmp memory space.  Pointer to the user buffer  */
    returnValue =
        mpiControlMemoryAlloc(control,
                              MPIControlMemoryTypeUSER,
                              sizeof(long),
                              &allocPointer);
    msgCHECK(returnValue);

    returnValue =
            meiPlatformMemoryToFirmware(platform,
                                        allocPointer,
                                        (void **)&address);
    msgCHECK(returnValue);

    meiPlatformConsole("address of allocPointer (user buffer) is 0x%x\n",address);

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

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

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

    /* Create motion axis list */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

    /* Write the axis list to the motion supervisor on the board */
    returnValue =
        mpiMotionAction(motion,
                        MEIActionMAP);

    msgCHECK(returnValue);

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          -1);
    msgCHECK(mpiSequenceValidate(sequence));

    /* CommandTable[commandIndex] */
    commandIndex = 0;

    /* Get the address for the first axis's actual position register */
    addressActPos1 = &firmware->Axis[axisNumber[0]].ActualPosition;

    /* Get the address for the second axis's actual position register */
    addressActPos2 = &firmware->Axis[axisNumber[1]].ActualPosition;

    returnValue =
            meiPlatformMemoryToFirmware(platform,
                                        addressActPos1,
                                        (void **)&address);
    msgCHECK(returnValue);

    meiPlatformConsole("addressActPos1 is 0x%x\n",address);

    returnValue =
            meiPlatformMemoryToFirmware(platform,
                                        addressActPos2,
                                        (void **)&address);
    msgCHECK(returnValue);
    meiPlatformConsole("addressActPos2 is 0x%x\n",address);

    /* 1st. Command  */
    /* Take the difference of the two actual positions and store them in the user buffer */
    addressDifferenceStored = allocPointer;

    commandParams.compute.dst.l         = addressDifferenceStored;
    commandParams.compute.expr.address.l    = addressActPos1;
    commandParams.compute.expr.oper     = MPICommandOperatorSUBTRACT;
    commandParams.compute.expr.by.ref.l = addressActPos2;

    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeCOMPUTE_REF,
                         &commandParams,
                         "First");
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /*  2nd Command */
    /*  Compare the position differences to the position diference tolerance */
    /*  Perform abort if test is true */

    commandParams.branch.label              = "ABORT";
    commandParams.branch.expr.address.l     = addressDifferenceStored;
    commandParams.branch.expr.oper          = MPICommandOperatorLESS;
    commandParams.branch.expr.by.value.l    = differenceTolerance;

    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* 3rd. Command */
    /* Branch to the first command of the sequence */
    commandParams.branch.label      = "First";  /* First command */
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* 4th. command */
    /* Abort the axes that are part of motion supervisor motion */

    commandParams.motion.motionCommand  = MPICommandMotionABORT;
    commandParams.motion.motion     = motion;

    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeMOTION,
                         &commandParams,
                         "ABORT");
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Create sequence command list */
    returnValue =
        mpiSequenceCommandListSet(sequence,
                                  commandIndex,
                                  CommandTable);
    msgCHECK(returnValue);

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);

    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(2);
    }

    meiPlatformConsole("Press any key to stop sequence\n");
    meiPlatformKey(MPIWaitFOREVER);

    returnValue =
            mpiControlMemoryGet(control,
                                &difference,
                                allocPointer,
                                sizeof(long));
    msgCHECK(returnValue);

    meiPlatformConsole("Axis Position difference is %ld\n",difference);

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

    returnValue =
        mpiControlMemoryFree(control,
                             MPIControlMemoryTypeUSER,
                             sizeof(long),
                             allocPointer);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


capture1.c -- Perform a velocity move and capture position based on Home or Index pulse.
/* capture1.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/capture1.c 10    7/18/01 9:32a Kevinh $"
#endif

#if defined(ARG_MAIN_RENAME)
#define main    capture1Main

argMainRENAME(main, capture1)
#endif

/*

:Perform a velocity move and capture position based on Home or Index pulse.

This sample application demonstrates use of the Capture feature on the XMP.
First, a velocity move is commanded on an Axis.  A capture is then configured
to trigger on either a Home sensor or index pulse.

Each motion block supports 10 capture registers.   The default configuration
 is two capture registers per motor -- while the last two (8,9) on each motion
 block are reserved for the Auxiliary Encoder (not supported).   The capture
 registers are default mapped as follows... 0 & 1 for Motor0, 2 & 3 for Motor1,
 10 & 11 for Motor4, etc.  The first Capture for each motor latches the default
 (primary) encoder input, and the second capture latches the AUX encoder
 input. The equation used below calculates the Capture number for the primary
 motor feedback given the default capture mapping.

    captureNumber = ((motorNumber / MEIXmpMotorsPerBlock) * MEIXmpMaxLatches) +
                    ((motorNumber % MEIXmpMotorsPerBlock) * CapturesPerMotor);

This program presumes the tuning parameters(PID, PIV, etc.) for your
stage(or tool, or machine) have already been set.  That is, the tuning
parameters need to be established prior to running this program so the
stage can move in a stable manner.  Please use the Tuning Guidelines if
these values haven't been determined.

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 CapturesPerMotor    (2) /* Default Capture configuration */

/* User Settings */
#define ACTIVE_FALLING_EDGE     (0)
#define ACTIVE_RAISING_EDGE     (1)

#define MOTORNUM            (0) /* Number of motors */

/* Motion Parameters */
#define VELOCITY    (5000.0)    /* Move velocity */
#define ACCEL       (10000.0)   /* Move acceleration*/

/* Capture Parameters */
#define CAPTURE_EDGE        (ACTIVE_FALLING_EDGE) /* Capture on falling edge */

/* CAPTURE_TRIGGER can be MEIMotorInputHOME or MEIMotorInputINDEX */
#define CAPTURE_TRIGGER     (MEIMotorInputHOME)   /* Capture on home pulse */

/* 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);
    }
}

/* Calculate default capture number for axisNumber */
long captureNumber(long     motorNumber)
{
    return  ((motorNumber/MEIXmpMotorsPerBlock) * MEIXmpMaxLatches) +
            ((motorNumber % MEIXmpMotorsPerBlock) * CapturesPerMotor);
}

/* Create and initialize MPI objects */
void programInit(MPIControl         *control,
                 MPIControlType      controlType,
                 MPIControlAddress  *controlAddress,
                 MPIMotion          *motion,
                 long                motionNumber,
                 MPIAxis            *axis,
                 long                axisNumber,
                 MPIMotor           *motor,
                 long                motorNumber,
                 MPICapture         *capture,
                 long                captureNumber)
{
    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,
                        *axis);
    msgCHECK(mpiMotionValidate(*motion));

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

    /* Create capture object */
    *capture =
        mpiCaptureCreate(*control,
                         captureNumber);
    msgCHECK(mpiCaptureValidate(*capture));
}

/*
   Configure capture object.

   edge: 0 for falling edge, 1 for rising edge
*/
void configureCapture(MPICapture    capture,
                      MEIMotorInput trigger,
                      long          edge)
{
    MPICaptureConfig    captureConfig;
    long                returnValue;

    /* Disable capture */
    returnValue =
        mpiCaptureArm(capture,
                      FALSE);
    msgCHECK(returnValue);

    /* Read caputre configuration */
    returnValue =
        mpiCaptureConfigGet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);

    /* Set capture parameters */
    captureConfig.trigger.mask    = trigger;
    captureConfig.trigger.pattern = edge ? trigger : 0;

    /* Write capture configuration */
    returnValue =
        mpiCaptureConfigSet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);
}

/* Disable Home Event action */
void disableHomeEvent(MPIMotor      motor,
                      MPICapture    capture)
{
    MPIMotorEventConfig eventConfig;
    long                returnValue;

    returnValue =
        mpiMotorEventConfigGet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    eventConfig.action = MPIActionNONE;     /* No action   */
    eventConfig.trigger.polarity = TRUE;    /* Active high */

    returnValue =
        mpiMotorEventConfigSet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Arm the capture */
    returnValue =
        mpiCaptureArm(capture,
                      TRUE);
    msgCHECK(returnValue);
}

/* Perform a Velocity move */
void velocityMove(MPITrajectory     *trajectory,
                  MPIMotionParams   *params,
                  MPIMotion         *motion)
{
    long    returnValue;

    /* Setup motion parameters */
    trajectory->velocity = VELOCITY;
    trajectory->acceleration = ACCEL;
    trajectory->deceleration = ACCEL; /* Not used for velocity move */
    trajectory->jerkPercent = 0.0;    /* Not used for velocity move */
    params->velocity.trajectory = trajectory;

    /* Start a velocity move */
    returnValue =
        mpiMotionStart(*motion,
                       MPIMotionTypeVELOCITY,
                       params);
    msgCHECK(returnValue);
}

/* Poll capture status and update display */
void pollForCaptureAndUpdateDisplay(MPICapture      *capture,
                                    MPIMotor        *motor,
                                    MEIMotorInput    trigger)
{
    MPICaptureStatus    captureStatus;
    MPIMotorIo          io;
    long                caputuresCounted = 0;
    long                returnValue;

    /* State Machine - Poll capture status, update display, etc. */
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        returnValue =
            mpiCaptureStatus(*capture,
                             &captureStatus,
                             NULL);
        msgCHECK(returnValue);

        /* Display Home and Capture state */
        returnValue =
            mpiMotorIoGet(*motor,
                          &io);
        msgCHECK(returnValue);

        printf("\rI/O state:%d  CaptureState:%d  ",
               !(!(io.input & trigger)),    /* input bit */
               captureStatus.state);        /* (1=ARMED, 2=CAPTURED) */

        if (captureStatus.state == MPICaptureStateCAPTURED) {
            caputuresCounted++;

            printf("Latched Position = %.0lf  # of captures = %d\n\n",
                   captureStatus.latch[0],
                   caputuresCounted);

            /* Re-arm position capture */
            returnValue =
                mpiCaptureArm(*capture,
                              TRUE);
            msgCHECK(returnValue);
        }
    }
}

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

    /* Delete capture object */
    returnValue =
        mpiCaptureDelete(*capture);
    msgCHECK(returnValue);

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(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);
}

int main(int    argc,
         char   *argv[])
{

    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotion           motion;
    MPIAxis             axis;
    MPIMotor            motor;
    MPICapture          capture;
    MPITrajectory       trajectory;
    MPIMotionParams     params;

    long    returnValue;                /* Return value from library */
    long    motorNumber = MOTORNUM;
    long    motionNumber = motorNumber;
    long    axisNumber = motorNumber;

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

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                &motion,
                motionNumber,
                &axis,
                axisNumber,
                &motor,
                motorNumber,
                &capture,
                captureNumber(motorNumber));

    /* Configure capture  */
    configureCapture(capture,
                     CAPTURE_TRIGGER,
                     CAPTURE_EDGE);

    /* Disable Home Event action */
    disableHomeEvent(motor,
                     capture);

    /* Perform a Velocity move */
    velocityMove(&trajectory,
                 &params,
                 &motion);

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

    /* Poll capture status and update display */
    pollForCaptureAndUpdateDisplay(&capture,
                                   &motor,
                                   CAPTURE_TRIGGER);

    printf("\nStopping.\n");

    /* Stop motion on axis */
    returnValue =
        mpiMotionAction(motion,
                        MPIActionSTOP);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


coffee.c -- Read XMP firmware signature
/* coffee.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/coffee.c 10    7/23/01 2:36p Kevinh $";
#endif

/*

:Read XMP firmware signature

This sample application reads the firmware signature and other controller
ID registers including:  Signature, Disable, SoftwareID, and Option.

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    coffeeMain

argMainRENAME(main, coffee)
#endif

unsigned long MEIMemory[64];

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* Motion controller handle */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    void    *memory;        /* Control memory */

    long    returnValue;    /* Return value from library */
    long    argIndex;

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

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n",
                           argv[0],
                           ArgUSAGE);
        exit(MPIMessagePARAM_INVALID);
    }

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

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

    returnValue =
        mpiControlMemory(control,
                         &memory,
                         NULL);
    msgCHECK(returnValue);

    /* Read and Print the Controller firmware signature */
    returnValue =
        mpiControlMemoryGet(control,
                            MEIMemory,
                            memory,
                            sizeof(MEIMemory));
    msgCHECK(returnValue);

    fprintf(stderr, "Sharc memory: 0x0%08x 0x%08x 0x%08x 0x%08x\n",
                    MEIMemory[0],
                    MEIMemory[1],
                    MEIMemory[2],
                    MEIMemory[3]);

    /* Delete objects */
    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return ((int)returnValue);
}


comp.c -- Configure Axis Compensation Tables
/* comp.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/comp.c 10    7/23/01 2:36p Kevinh $";
#endif

/*

:Configure Axis Compensation Tables

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 <string.h>
#include <ctype.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    compMain

argMainRENAME(main, comp)
#endif

#define COMP_FILENAME   "comp.txt"

MEIXmpCompensator   Comp;

long    CompTable[MEIXmpCompTableSize];

long    loadCompTable(MPIControl        control,
                      long              index,
                      MEIXmpCompensator *comp);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */

    char    *fileName;
    FILE    *fp;
    long    compIndex;
    long    compIndexOld;
    long    controlIndex;
    long    tableIndex;
    long    tableCount = 0;
    char    buffer[256];

    long    returnValue;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

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

    fileName =
        (argIndex >= argc)
                ? COMP_FILENAME
                : argv[argIndex++];

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[fileName (%s)]",
                           argv[0],
                           ArgUSAGE,
                           COMP_FILENAME);
        exit(0);
    }

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

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

    fp = fopen(fileName, "r");

    if (fp == NULL) {
        fprintf(stderr,
                "%s: file not found.\n",
                fileName);
        exit(2);
    }

    compIndex = 0;
    compIndexOld = -1;

    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        long    inAxis;
        long    outAxis;
        long    minPosition;
        long    deltaPosition;
        long    compPoints;
        long    dimension;

        char    *ptr;

        if (compIndex > compIndexOld) {
            Comp.Dimension                  = -1;
            Comp.OutAxis                    = -1;
            Comp.Control[0].InAxis          = -1;
            Comp.Control[0].DeltaPosition   = -1;
            Comp.Control[0].CompPoints      = -1;
            Comp.Control[1].InAxis          = -1;
            Comp.Control[1].DeltaPosition   = -1;
            Comp.Control[1].CompPoints      = -1;
            tableCount = 0;

            memset(CompTable, 0, sizeof(CompTable));
            Comp.CompTable = CompTable;

            compIndexOld = compIndex;
        }

        for (ptr = buffer; *ptr != '\0'; ptr++) {
            char    byte = *ptr;

            if (islower(byte)) {
                *ptr = (char)toupper(byte);
            }
        }

        if (sscanf(buffer, "#DIMENSION  = %d", &dimension) == 1) {
            Comp.Dimension = dimension;
            continue;
        }

        if (sscanf(buffer, "#INAXIS[%d]  = %d",&controlIndex, &inAxis) == 2) {
            Comp.Control[controlIndex].InAxis = inAxis;
            continue;
        }

        if (sscanf(buffer, "#OUTAXIS  = %d", &outAxis) == 1) {
            Comp.OutAxis = outAxis;
            continue;
        }

        if (sscanf(buffer, "#MINPOSITION[%d]  = %d",&controlIndex, &minPosition) == 2) {
            Comp.Control[controlIndex].MinPosition = minPosition;
            continue;
        }

        if (sscanf(buffer, "#DELTAPOSITION[%d]  = %d",&controlIndex, &deltaPosition) == 2) {
            Comp.Control[controlIndex].DeltaPosition = deltaPosition;
            continue;
        }

        if (sscanf(buffer, "#COMPPOINTS[%d]  = %d",&controlIndex, &compPoints) == 2) {
            Comp.Control[controlIndex].CompPoints = compPoints;
            continue;
        }

        if (sscanf(buffer, "#POSITION[%d]", &tableIndex) == 1) {
            long    index;
            long    calc_x;

            if (Comp.Dimension == 1) {
                Comp.Control[1].CompPoints = 1;
                Comp.Control[1].InAxis          = 0;
                Comp.Control[1].DeltaPosition   = 0;
            }

            /* Do some error checking. */
            if (compIndex >= MEIXmpMAX_Compensators) {
                fprintf(stderr,
                        "Too many compensators. Max = %d.\n",
                        MEIXmpMAX_Compensators);
                break;
            }

            if (Comp.OutAxis < 0) {
                fprintf(stderr,
                        "No #OutAxis statement.\n");
                break;
            }

            if (Comp.Dimension < 0) {
                fprintf(stderr,
                        "No #Dimension statement.\n");
                break;
            }

            for (controlIndex = 0; controlIndex < Comp.Dimension; controlIndex++) {
                if (Comp.Control[controlIndex].InAxis < 0) {
                    fprintf(stderr,
                            "No #InAxis[%d] statement.\n",
                            controlIndex);
                    break;
                }

                if (Comp.Control[controlIndex].CompPoints < 0) {
                    fprintf(stderr,
                            "No #CompPoints[%d] statement.\n",
                            controlIndex);
                    break;
                }

                if (Comp.Control[controlIndex].DeltaPosition < 0) {
                    fprintf(stderr,
                            "Delta Position[%d] (%d) is invalid.\n",
                            controlIndex,
                            Comp.Control[controlIndex].DeltaPosition);
                    break;
                }
            }
            if ((Comp.Control[0].CompPoints * Comp.Control[1].CompPoints)
                    > MEIXmpCompTableSize) {
                fprintf(stderr,
                        "Too many compensation points. Max = %d.\n",
                        MEIXmpCompTableSize);
                break;
            }

            if (tableIndex >= Comp.Control[1].CompPoints) {
                fprintf(stderr,
                        "Compensation table number (%d) out of range [0-%d].\n",
                        tableIndex,
                        Comp.Control[1].CompPoints);
                break;
            }

            calc_x = Comp.Control[0].MinPosition;

            index = 0;

            while (index < Comp.Control[0].CompPoints) {
                long    x;
                long    y;
                long    tableOffset;

                if (fgets(buffer, sizeof(buffer), fp) == NULL) {
                    fprintf(stderr,
                            "Unexpected end-of-file\n");
                    break;
                }

                if (sscanf(buffer, "%d %d", &x, &y) == 2) {
                    if (x != calc_x) {
                        fprintf(stderr,
                                "Table out of order, expected position = %d, read %d\n",
                                calc_x,
                                x);
                        break;
                    }
                    tableOffset = index + tableIndex * Comp.Control[0].CompPoints;
                    Comp.CompTable[tableOffset] = y;
                    calc_x += Comp.Control[0].DeltaPosition;
                    index++;
                }
            }

            if (index < Comp.Control[0].CompPoints) {
                fprintf(stderr,
                        "Compensation table number (%d) too small.\n",
                        tableIndex);
                break;
            }
            else {
                tableCount++;
                fprintf(stderr,
                        "Compensation Table %d read.\n",
                        tableIndex);
            }

            if (tableCount >= Comp.Control[1].CompPoints) {
                returnValue =
                    loadCompTable(control,
                                  compIndex,
                                  &Comp);

                fprintf(stderr,
                        "Compensator %d is %sconfigured.\n",
                        compIndex,
                        (returnValue == MPIMessageOK)
                                    ? ""
                                    : "NOT ");

                compIndex++;
            }
        }
    }

    fclose(fp);

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

    return ((int)returnValue);
}

long loadCompTable(MPIControl           control,
                   long                 index,
                   MEIXmpCompensator    *comp)
{
    MPIControlConfig    controlConfig;
    MEIControlConfig    controlConfigXmp;

    long    returnValue;

    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            &controlConfigXmp);

    if (returnValue == MPIMessageOK) {
        if (controlConfigXmp.Compensator[index].CompTable != NULL) {

            fprintf(stderr,
                    "Warning: controlConfigXmp.Compensator[%d] is already in use\n",
                    index);
        }

        controlConfigXmp.compensatorCount = index + 1;
        controlConfigXmp.Compensator[index] = *comp;

        if (index > 0) {
            long *prev_dest;
            long prev_size;

            prev_dest = controlConfigXmp.Compensator[index - 1].CompTable;
            prev_size = controlConfigXmp.Compensator[index - 1].Control[0].CompPoints *
               controlConfigXmp.Compensator[index-1].Control[1].CompPoints;

            controlConfigXmp.Compensator[index].CompTable = &prev_dest[prev_size];
        }
        else {
            controlConfigXmp.Compensator[index].CompTable =
                controlConfigXmp.CompensationTable;
        }

        meiASSERT(&controlConfigXmp.CompensationTable[MEIXmpCompTableSize] >=
                  &controlConfigXmp.Compensator[index].CompTable[
                            controlConfigXmp.Compensator[index].Control[0].CompPoints *
                            controlConfigXmp.Compensator[index].Control[1].CompPoints]);

        memcpy(controlConfigXmp.Compensator[index].CompTable,
               comp->CompTable,
               controlConfigXmp.Compensator[index].Control[0].CompPoints *
               controlConfigXmp.Compensator[index].Control[1].CompPoints *
                    sizeof(long));

        returnValue =
            mpiControlConfigSet(control,
                                &controlConfig,
                                &controlConfigXmp);
    }

    return (returnValue);
}


compare1.c -- Compare an encoder counter and set an XCVR output when the condition is TRUE.
/* compare1.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/compare1.c 7     7/23/01 2:36p Kevinh $"
#endif

/*

:Compare an encoder counter and set an XCVR output when the condition is TRUE.

Each motion block supports 10 compare registers.   The default configuration
 is two compare registers per motor -- while the last two (8,9) on each motion
 block are reserved for the Auxiliary Encoder (not supported).   The compare
 registers are default mapped as follows.... 0 & 1 for Motor0, 2 & 3 for Motor1,
 10 & 11 for Motor4, etc.  The first Compare for each motor uses the default
 (primary) encoder input for position compare, the second uses the AUX encoder
 input. The equation used below calculates the Compare number for the primary
 motor feedback given the default compare mapping.

    compareNumber = ((motorNumber / MEIXmpMotorsPerBlock) * MEIXmpMaxComparePositions) +
                    ((motorNumber % MEIXmpMotorsPerBlock) * ComparesPerMotor);

A compare register is loaded with a position compare value, a compare operator
 (MPICommandOperatorGREATER or MPICommandOperatorLESS_OR_EQUAL), and an output
 state (sets the Motor's XCVR_C TRUE or FALSE when the compare state is true).

A compare's status can be polled, it does not generate an event.  If the
 compare register's state equals MPICompareStateCOMPARED, the compare
 position is stored and the compare register is ready for re-arming.

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    compare1Main

argMainRENAME(main, compare1)
#endif

#define MOTOR           (4)
#define COMPARE_POS     (15000)
#define ComparesPerMotor    (2) /* Default Compare configuration */

/* XCVR Settings */
#define TRANSCEIVER_CONFIG  (MEIMotorTransceiverConfigCOMPARE) /* XCVR will output Compare logic */
#define TRANSCEIVER_ID      (MEIMotorTransceiverIdC)  /* Must be XCVR_C for Compare */
#define TRANSCEIVER_MASK    (MEIMotorTransceiverMaskC) /* same as above */

int
    main(int    argc,
         char   *argv[])
{
    MPIControl          control;        /* motion controller object */
    MPIAxis             axis;           /* axis object */
    MPIMotor            motor;          /* motor object */
    MEIMotorConfig      motorConfigXmp;  /* contains transceiver configuration */
    MPIMotorIo          io;
    MPICompare          compare;        /* compare object */

    MPICompareParams    compareParams;  /* compare parameters */
    MPICompareStatus    compareStatus;  /* compare status */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    returnValue;        /* return value from library */
    long    argIndex;
    long    motorNumber;
    long    compareNumber;
    double  origin;
    double  actualPosition;

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

    motorNumber =
        (argIndex >= argc)
                ? MOTOR
                : meiPlatformAtol(argv[argIndex++]);

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[motor# (0)]\n",
                            argv[0],
                            ArgUSAGE);
        exit(0);
    }

    /* Calculate default compare number for axisNumber */
    compareNumber = ((motorNumber/MEIXmpMotorsPerBlock) * MEIXmpMaxComparePositions) +
                    ((motorNumber % MEIXmpMotorsPerBlock) * ComparesPerMotor);

    /* 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,
                      motorNumber);
    msgCHECK(mpiAxisValidate(axis));

    /* Read the Axis' Origin */
    returnValue =
        mpiAxisOriginGet(axis,
                         &origin);
    msgCHECK(returnValue);

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

    /* Configure selected transceiver */
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    motorConfigXmp.Transceiver[TRANSCEIVER_ID].Config = TRANSCEIVER_CONFIG;

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

    /* Create compare object for compareNumber */
    compare =
        mpiCompareCreate(control,
                         compareNumber);
    msgCHECK(mpiCompareValidate(compare));

    /* Disable compare */
    returnValue =
        mpiCompareArm(compare,
                      FALSE);
    msgCHECK(returnValue);

    /* Set compare parameters */

    /* remember to use the Axis' Origin when calculating the Compare position */
    compareParams.position = (long) (COMPARE_POS + origin);

    /* Configures state of the XCVR output, when Compare is valid */
    compareParams.outputState = TRUE;

    /*
        commandOperator must be MPICommandOperatorGREATER
        or MPICommandOperatorLESS_OR_EQUAL -- anything else is INVALID
     */
    compareParams.commandOperator = MPICommandOperatorGREATER;

    /* Load params */
    returnValue =
        mpiCompareLoad(compare,
                       &compareParams,
                       NULL);
    msgCHECK(returnValue);

    /* Arm the compare */
    returnValue =
        mpiCompareArm(compare,
                      TRUE);
    msgCHECK(returnValue);

    /* State Machine - Poll compare status, update display, etc */
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        returnValue =
            mpiCompareStatus(compare,
                             &compareStatus,
                             NULL);
        msgCHECK(returnValue);

        /* Display XCVR, Compare state and Axis' actual position */
        returnValue =
            mpiMotorIoGet(motor,
                          &io);
        msgCHECK(returnValue);

        returnValue =
            mpiAxisActualPositionGet(axis,
                                     &actualPosition);
        msgCHECK(returnValue);

        printf("\rXCVR_C:0x%x  State:0x%x  ActualPosition:%.0lf",
                io.input & TRANSCEIVER_MASK,    /* XCVR bit, read as input -- input from FPGA */
                compareStatus.state,            /* value of Compare bit (1=ARMED, 2=COMPARED) */
                actualPosition);

        if (compareStatus.state == MPICompareStateCOMPARED) {
            printf("  Compared Position:%.0lf\r",
                    (double) (compareStatus.position[compareNumber % MEIXmpMaxComparePositions] - origin));

            /* Re-arm position compare */
            returnValue =
                mpiCompareArm(compare,
                              TRUE);
            msgCHECK(returnValue);
        }
        else {
            /* clear any previous positions from the display... */
            printf("                             ");
        }
    }

    /* Disarm position compare */
    returnValue =
        mpiCompareArm(compare,
                      FALSE);
    msgCHECK(returnValue);

    /* Delete objects */

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

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

    returnValue = mpiCompareDelete(compare);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


encfltcfg.c -- Configure encoder fault settings for a motor.
/* encfltcfg.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/encfltcfg.c 1     2/05/02 11:33a Erikb $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    limitsw1Main
argMainRENAME(main, limitsw1)
#endif

/*

:Configure encoder fault settings for a motor.

Encoder faults are set with an action, duration, and trigger.

  The action is one of the following:

    MPIActionSTOP,
    MPIActionE_STOP,
    MPIActionE_STOP_ABORT,
    MPIActionABORT,

The duration is in seconds. Keep in mind that the resolution of this setting
  is one servo sample period (1/sample rate).

The trigger sets three switches.
    MPIMotorEncoderFaultMaskBW_DET,		Broken wire switch
    MPIMotorEncoderFaultMaskILL_DET,	Illegal state switch
    MPIMotorEncoderFaultMaskABS_ERR,	Absolute encoder error switch

Broken wires occur when the positive and negative halves of an encoder signal
  pull together. An example would be when A+ and A- are at the same voltage
  because one of the A wires is disconnected.

Illegal state occurs when the A and B channel change level within 40 nsec.

Absolute encoder errors occur when there is a communication error on an
  absolute encoder. The details of this will vary with different types of
  absolute encoders.

Events are configured using MPIMotorEventConfigGet/Set(...).

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 MOTOR           (0)
#define EVENT_DURATION  (0.010)     /* seconds */

/* 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);
    }
}

void encoderFaultConfigure(MPIMotor        motor,
                           MPIAction       action,
                           double          duration)
{
    MPIMotorEventConfig eventConfig;
    long returnValue;

    /* Get the current limit configuration */
    returnValue =
        mpiMotorEventConfigGet(motor,
                               MPIEventTypeENCODER_FAULT,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

      /* Wait duration seconds before triggering */
    eventConfig.duration = (float) duration;

    /* Configure motor to perform action upon limit */
    eventConfig.action = action;

    /* Turn on all encoder fault types */
    eventConfig.trigger.mask = 	MPIMotorEncoderFaultMaskBW_DET |
        MPIMotorEncoderFaultMaskILL_DET |
        MPIMotorEncoderFaultMaskABS_ERR;

    /* Set the new limit configuration */
    returnValue =
        mpiMotorEventConfigSet(motor,
                               MPIEventTypeENCODER_FAULT,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);
}

/* Create and initialize MPI objects */
void programInit(MPIControl         *control,
                 MPIControlType      controlType,
                 MPIControlAddress  *controlAddress,
                 MPIMotor           *motor,
                 long                motorNumber)
{
    long returnValue;

    /* Obtain a Control handle */
    *control =
        mpiControlCreate(controlType,
                         controlAddress);
    msgCHECK(mpiControlValidate(*control));

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

    /* Obtain a Motor handle */
    *motor =
        mpiMotorCreate(*control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(*motor));
}

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

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(returnValue);

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

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

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

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

    /* Change the ENCODER_FAULT configuration */
    encoderFaultConfigure(motor,
                        MPIActionABORT,             /* ABORT on limit  */
                        EVENT_DURATION);

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

    return MPIMessageOK;
}


encoder.c -- Continuous display of motor actual position while switching the
/* encoder.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/encoder.c 8     7/23/01 2:36p Kevinh $";
#endif

/*

:Continuous display of motor actual position while switching the
 encoder polarity when a key is pressed.

 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 <string.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    encoderMain

argMainRENAME(main, encoder)
#endif

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

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

typedef struct _Context *Context;

typedef struct _Context {
    MPIControl  control;
    MPIAxis     axis;
    MPIMotor    motor;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIMotorConfig  motorConfig;

    long    axisNumber;
    long    motorNumber;

    long    encoderPhase;
} _Context;

long    contextCreate(Context   contextData,
                      long      argc,
                      char      *argv[]);
long    contextDelete(Context   contextData);

void    positionDisplay(double  position);
double  positionGet(Context contextData);

Static _Context ContextObject;

int
    main(int    argc,
         char   *argv[])
{
    Context context;

    long    returnValue;

    context = &ContextObject;

    returnValue =
        contextCreate(context,
                      argc,
                      argv);

    /* Disable amplifier */
    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiMotorAmpEnableSet(context->motor,
                                 FALSE);
    }

    while (returnValue == MPIMessageOK) {
        long    key;

        printf("\nMove the motor and note the direction; it should be %s.\n",
                (context->motorConfig.encoderPhase == 0)
                                ? "normal"
                                : "reversed");

        printf("Press a key to change the encoder phasing, ESC to quit.\n");

        while ((key = meiPlatformKey(MPIWaitPOLL)) <= 0) {
            positionDisplay(positionGet(context));
        }

        if (key == 0x1b) {
            break;
        }

        context->motorConfig.encoderPhase = (context->motorConfig.encoderPhase == 0);

        returnValue =
            mpiMotorConfigSet(context->motor,
                              &context->motorConfig,
                              NULL);
    }

    returnValue = contextDelete(context);
    meiASSERT(returnValue == MPIMessageOK);

    return ((int)returnValue);
}

long
    contextCreate(Context   context,
                  long      argc,
                  char      *argv[])
{
    long    returnValue;

    long    argIndex;

    memset(context, 0, sizeof(*context));

    /* Parse command line for Control type and address */
    argIndex =
        argControl(argc,
                   argv,
                   &context->controlType,
                   &context->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) ||
        (axisNumber  >= MEIXmpMAX_Axes) ||
        (motorNumber >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

    context->motorNumber = motorNumber;

    context->axisNumber =
        (axisNumber < 0)
            ? motorNumber
            : axisNumber;

    context->control =
        mpiControlCreate(context->controlType,
                         &context->controlAddress);
    msgCHECK(mpiControlValidate(context->control));

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

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

    /* Create motor object */
    context->motor =
        mpiMotorCreate(context->control,
                       context->motorNumber);
    msgCHECK(mpiMotorValidate(context->motor));

    returnValue =
        mpiMotorConfigGet(context->motor,
                          &context->motorConfig,
                          NULL);
    msgCHECK(returnValue);

    context->encoderPhase = context->motorConfig.encoderPhase;

    return (returnValue);
}

long
    contextDelete(Context   context)
{
    long    returnValue = MPIMessageOK;

    if (context->motor != MPIHandleVOID) {
        /* Set to original configuration */
        context->motorConfig.encoderPhase = context->encoderPhase;

        returnValue =
            mpiMotorConfigSet(context->motor,
                              &context->motorConfig,
                              NULL);

        if (returnValue == MPIMessageOK) {
            returnValue = mpiMotorDelete(context->motor);

            if (returnValue == MPIMessageOK) {
                context->motor = MPIHandleVOID;
            }
        }
    }

    if (returnValue == MPIMessageOK) {
        if (context->axis != MPIHandleVOID) {
            returnValue = mpiAxisDelete(context->axis);

            if (returnValue == MPIMessageOK) {
                context->axis = MPIHandleVOID;
            }
        }
    }

    if (returnValue == MPIMessageOK) {
        if (context->control != MPIHandleVOID) {
            returnValue = mpiControlDelete(context->control);

            if (returnValue == MPIMessageOK) {
                context->control = MPIHandleVOID;
            }
        }
    }

    return (returnValue);
}

void
    positionDisplay(double  position)
{
    printf("Actual Position: %8.0lf\r",
            position);
}

double
    positionGet(Context context)
{
    long    returnValue;

    double  actualPos;

    returnValue =
        mpiAxisActualPositionGet(context->axis,
                                 &actualPos);
    msgCHECK(returnValue);

    return (actualPos);
}


event1.c -- Perform a repeated two-axis motion while polling an event manager.
/* event1.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/event1.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a repeated two-axis motion while polling an event manager.

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    event1Main

argMainRENAME(main, event1)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  20000.0,    },
    { 0.0,      0.0,        },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
};

/* motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

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

    MPIEventMask    eventMask;

    long    returnValue;    /* return value from library */

    long    index;

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create X axis object using axis number X_AXIS on controller */
    axisX =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axisX));

    /* Create Y axis object using axis number Y_AXIS on controller */
    axisY =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axisY));

    /* Create motion object using MS number */
    /* Append X axis to motion */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axisX);
    msgCHECK(mpiMotionValidate(motion));

    /* Append Y axis to motion */
    returnValue =
        mpiMotionAxisAppend(motion,
                            axisY);
    msgCHECK(returnValue);

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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));

    /* Flush any existing events */
    returnValue =
        mpiEventMgrFlush(eventMgr);
    msgCHECK(returnValue);

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

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

    /* Loop repeatedly */
    index = 0;
    while ((returnValue == MPIMessageOK) &&
           (meiPlatformKey(MPIWaitPOLL) <= 0)) {
        MPIMotionParams motionParams;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Start motion */
        returnValue =
            mpiMotionStart(motion,
                           motionType,
                           &motionParams);

        switch (returnValue) {
            case MPIMotionMessageERROR: {
                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                msgCHECK(returnValue);

                /* Wait for reset to take effect */
                meiPlatformSleep(2);

                /* FALL THROUGH */
            }
            case MPIMotionMessageNOT_READY: {
                returnValue = MPIMessageOK;
                continue;
            }
            case MPIMotionMessageMOVING: {
                returnValue = MPIMessageOK;
                break;
            }
            case MPIMessageOK:
            default: {
                break;
            }
        }

        /* Collect motion events */
        while (TRUE) {
            MPIEventStatus  eventStatus;

            /* Obtain firmware event(s) (if any) */
            returnValue =
                mpiEventMgrService(eventMgr,
                                   MPIHandleVOID);
            msgCHECK(returnValue);

            /* Poll for motion event */
            returnValue =
                mpiNotifyEventWait(notify,
                                   &eventStatus,
                                   MPIWaitPOLL);

            if (returnValue == MPIMessageOK) {
                if (eventStatus.type == MPIEventTypeMOTION_DONE) {
                    break;
                }
            }
            else {
                meiASSERT(returnValue == MPIMessageTIMEOUT);
            }
        }

        if (++index >= MOTION_COUNT) {
            index = 0;
        }
    }

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

    returnValue = mpiAxisDelete(axisY);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisX);
    msgCHECK(returnValue);

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

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

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

    return ((int)returnValue);
}


event3.c -- Perform a repeated single-axis motion using command-line-specified axis (default 0).
/* event3.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/event3.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a repeated single-axis motion using command-line-specified axis (default 0).

Wait for events to be distributed by the event manager in a separate service thread.
 Check status after motion complete, warn of inPosition not set.

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    event3Main

argMainRENAME(main, event3)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            axisNumber      = 0;
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0, },
    { 0.0, },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel */
        { 10000.0,      100000.0,   100000.0,   },
    },
    {   /* velocity     accel       decel */
        { 10000.0,      100000.0,   100000.0,   },
    },
};

/* motion parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

long
    motionDone(MPIMotion    motion,
               MPIStatus    *status);

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

    MPIEventMask    eventMask;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    Service service;

    long    returnValue;    /* return value from library */

    long    index;

    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) ||
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

    /* Create axis object using axisNumber on controller*/
    axisList[0] =
        mpiAxisCreate(control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(axisList[0]));

    /* Create motion supervisor object using MS number */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Create 1-axis motion coordinate system */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axisList);
    msgCHECK(returnValue);

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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 */
    meiASSERT(service != NULL);

    /* Loop repeatedly */
    index = 0;
    while ((returnValue == MPIMessageOK) &&
           (meiPlatformKey(MPIWaitPOLL) <= 0)) {
        MPIMotionParams motionParams;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Start motion */
        returnValue =
            mpiMotionStart(motion,
                           motionType,
                           &motionParams);

        fprintf(stderr,
                "mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                motion,
                motionType,
                &motionParams,
                returnValue,
                mpiMessage(returnValue, NULL));

        switch (returnValue) {
            case MPIMotionMessageERROR: {
                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                fprintf(stderr,
                        "mpiMotionAction(0x%x, RESET) returns 0x%x\n",
                        motion,
                        returnValue);
                msgCHECK(returnValue);

                /* FALL THROUGH */
            }
            case MPIMotionMessageNOT_READY: {
                returnValue = MPIMessageOK;
                continue;
            }
            case MPIMotionMessageMOVING: {
                returnValue = MPIMessageOK;
                break;
            }
            case MPIMessageOK:
            default: {
                break;
            }
        }

        /* Collect motion events */
        while (returnValue == MPIMessageOK) {
            MPIEventStatus  eventStatus;

            /* Wait for motion event */
            returnValue =
                mpiNotifyEventWait(notify,
                                   &eventStatus,
                                   MPIWaitFOREVER);

            fprintf(stderr,
                    "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                    "\teventStatus: type %d source 0x%x info 0x%x\n",
                    notify,
                    &eventStatus,
                    MPIWaitFOREVER,
                    returnValue,
                    eventStatus.type,
                    eventStatus.source,
                    eventStatus.info[0]);

            if (returnValue == MPIMessageOK) {
                if (eventStatus.type == MPIEventTypeMOTION_DONE) {
                    break;
                }
            }
            else {
                break;
            }
        }

        if (returnValue == MPIMessageOK) {
            MPIStatus   status;

            returnValue =
                motionDone(motion,
                           &status);

            if ((returnValue == MPIMessageOK) &&
                (status.state == MPIStateERROR)) {
                if ((status.action == MPIActionABORT) ||
                    (status.action == MPIActionE_STOP_ABORT)) {
                    double  position[AXIS_COUNT];

                    returnValue =
                        mpiMotionPositionGet(motion,
                                             position,  /* actual */
                                             NULL);     /* command */
                    msgCHECK(returnValue);

                    returnValue =
                        mpiMotionPositionSet(motion,
                                             NULL,      /* actual */
                                             position); /* command */
                    msgCHECK(returnValue);
                }

                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                fprintf(stderr,
                        "mpiMotionAction(0x%x, RESET) returns 0x%x\n",
                        motion,
                        returnValue);
                msgCHECK(returnValue);
            }
        }

        putchar('\n');

        if (++index >= MOTION_COUNT) {
            index = 0;
        }
    }

    fprintf(stderr,
            "%s exiting: returnValue 0x%x: %s\n",
            argv[0],
            returnValue,
            mpiMessage(returnValue, NULL));

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axisList[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);
}

long motionDone(MPIMotion motion,
                MPIStatus *status)
{
    long    returnValue;

    double  actual[AXIS_COUNT];
    double  command[AXIS_COUNT];

    returnValue =
        mpiMotionStatus(motion,
                        status,
                        NULL);
    msgCHECK(returnValue);

    printf("MotionDone: status: state %d action %d eventMask 0x%x\n"
           "\tatTarget %d settled %d %s\n",
            status->state,
            status->action,
            status->eventMask,
            status->atTarget,
            status->settled,
            (status->settled == FALSE)
                    ? "=== NOT SETTLED ==="
                    : "");

    returnValue =
        mpiMotionPositionGet(motion,
                             actual,
                             command);
    msgCHECK(returnValue);

    if (returnValue == MPIMessageOK) {
        long    index;

        /* Display axis positions */
        for (index = 0; index < AXIS_COUNT; index++) {
            printf("\taxis[%d]    position: command %11.3lf\tactual %11.3lf\n",
                    index,
                    command[index],
                    actual[index]);
        }
    }

    return (returnValue);
}


EventLog.c -- Event Logging Application
/* EventLog.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/EventLog.c 1    7/18/01 2:45p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    EventLogMain
argMainRENAME(main, EventLog)
#endif

/*

:Event Logging Application

This application logs all events generated by a single controller.  To end
 the application, simply press a key.  To save the output to a file,
 please redirect the output using a pipe (type "EventLog > logOfEvents.txt")

NOTE:  This application does not change any configuration on the controller.
 If the controller is not configured to report events, then this application
 will report nothing.  Please refer to the sample application EventReport.c
 to see how to enable reporting of all events.

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.

The msgCHECK(...) macros used in the following sample code are intended
 to convey our strong belief that ALL error return codes should be checked.
 Actual application code should use specific error handling techniques (other
 than msgCHECKs) best suited to your internal error recovery methods.

*/

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

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

#include "apputil.h"

/* 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,
                 MPIEventMgr        *eventMgr,
                 MPINotify          *notify,
                 Service            *service)
{
    MEIEventMgrServiceConfig    serviceConfig;
    MPIEventMask                eventMask;

    long            returnValue;

    /* Obtain a control handle */
    *control =
        mpiControlCreate(controlType, controlAddress);
    msgCHECK(mpiControlValidate(*control));

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

    /* Obtain a notify handle */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    meiEventMaskALL(eventMask);

    *notify =
        mpiNotifyCreate(eventMask, NULL);
    msgCHECK(mpiNotifyValidate(*notify));

    /* Obtain an eventMgr handle */
    *eventMgr =
        mpiEventMgrCreate(*control);
    msgCHECK(mpiEventMgrValidate(*eventMgr));

    returnValue =
        mpiEventMgrNotifyAppend(*eventMgr, *notify);
    msgCHECK(returnValue);

    /* Retrieve events from all processes */
    returnValue =
        meiEventMgrServiceConfigGet(*eventMgr, &serviceConfig);
    msgCHECK(returnValue);

    serviceConfig.allProcesses = TRUE;

    returnValue =
        meiEventMgrServiceConfigSet(*eventMgr, &serviceConfig);
    msgCHECK(returnValue);

    /* Obtain a service handle */
    *service =
        serviceCreate(*eventMgr, -1, -1);
    meiASSERT(service != NULL);
}

/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl  *control,
                    MPIEventMgr *eventMgr,
                    MPINotify   *notify,
                    Service     *service)
{
    long    returnValue;

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

    *service = NULL;

    /* Delete eventMgr handle */
    returnValue =
        mpiEventMgrDelete(*eventMgr);
    msgCHECK(returnValue);

    *eventMgr = NULL;

    /* Delete notify handle */
    returnValue =
        mpiNotifyDelete(*notify);
    msgCHECK(returnValue);

    *notify = NULL;

    /* Delete control handle */
    returnValue =
        mpiControlDelete(*control);
    msgCHECK(returnValue);

    *control = NULL;
}

/*
    Identifies the source (type and index) of an event
        (from the MPIEventStatus structure)

    This is particularly useful when attempting to identify which axis produced
    an event in a different process or when identifying the axis without
    comparing MPIAxis handles.

    identifyEventSource() will return MPIMessageARG_INVALID if status is NULL or
    if both sourceType and sourceIndex are NULL.  Otherwise, the function will
    succeed and return MPIMessageOK.

    Possible values for sourceType:

    sourceType Value        Event Source Type
    ----------------        -----------------
    MEIXmpSignalID_MOTOR    Motor object
    MEIXmpSignalID_AXIS     Axis
    MEIXmpSignalID_MS       Motion Supervisor
    MEIXmpSignalID_PS       Program Sequencer (Non-user commanded events)
    MEIXmpSignalID_DR       Data Recorder
    MEIXmpSignalID_USER     User Commanded Event in a Program Sequencer

    NOTE: As of Feb 2002, only one Data Recorder exists per controller, so
    when the source is the data recorder, sourceIndex will filled with the
    value of zero.
 */
long identifyEventSource(MPIEventStatus* status,
                         MEIXmpSignalID* sourceType,
                         long* sourceIndex)
{
    if (status==NULL)
    {
        return MPIMessageARG_INVALID;
    }

    if ((sourceType==NULL) && (sourceIndex==NULL))
    {
        return MPIMessageARG_INVALID;
    }

    if (sourceType!=NULL)
    {
        *sourceType =
            ((((MEIEventStatusInfo*)status->info)->signalID) &
                MEIXmpSignalID_MASK);
    }

    if (sourceIndex!=NULL)
    {
        *sourceIndex =
            ((((MEIEventStatusInfo*)status->info)->signalID) &
                MEIXmpSignalID_INDEX) >> 16;
    }

    return MPIMessageOK;
}

/* Display event information */
void reportEvent(MPIEventStatus* status)
{
    MEIXmpSignalID  sourceType;

    long            sourceIndex;
    long            returnValue;

    returnValue =
        identifyEventSource(status, &sourceType, &sourceIndex);
    msgCHECK(returnValue);

    /* Report event source */
    switch (sourceType)
    {
        case MEIXmpSignalID_MOTOR:
            if (sourceIndex<10)
            {
                printf("Motor[%1d]     : ",sourceIndex);
            }
            else
            {
                printf("Motor[%2d]    : ",sourceIndex);
            }
            break;
        case MEIXmpSignalID_AXIS:
            if (sourceIndex<10)
            {
                printf("Axis[%1d]      : ",sourceIndex);
            }
            else
            {
                printf("Axis[%2d]     : ",sourceIndex);
            }
            break;
        case MEIXmpSignalID_MS:
            if (sourceIndex<10)
            {
                printf("Motion[%1d]    : ",sourceIndex);
            }
            else
            {
                printf("Motion[%2d]   : ",sourceIndex);
            }
            break;
        case MEIXmpSignalID_DR:
            printf("Data Recorder : ");
            break;
        case MEIXmpSignalID_PS:
            if (sourceIndex<10)
            {
                printf("Sequence[%1d]  : ",sourceIndex);
            }
            else
            {
                printf("Sequence[%2d] : ",sourceIndex);
            }
            break;
        case MEIXmpSignalID_USER:
            if (sourceIndex<10)
            {
                printf("User (PS[%1d]) : ",sourceIndex);
            }
            else
            {
                printf("User (PS[%2d]): ",sourceIndex);
            }
            break;
        default:
            printf("Unknown Source: ",sourceIndex);
    }

    /* Report event type */
    switch (status->type)
    {
        case MPIEventTypeAMP_FAULT:
            printf("Amplifier Fault      ");
            break;
        case MPIEventTypeHOME:
            printf("Home Event           ");
            break;
        case MPIEventTypeLIMIT_ERROR:
            printf("Position Error Limit ");
            break;
        case MPIEventTypeLIMIT_HW_NEG:
            printf("Negative HW Limit    ");
            break;
        case MPIEventTypeLIMIT_HW_POS:
            printf("Positive HW Limit    ");
            break;
        case MPIEventTypeLIMIT_SW_NEG:
            printf("Negative SW Limit    ");
            break;
        case MPIEventTypeLIMIT_SW_POS:
            printf("Positive SW Limit    ");
            break;
        case MPIEventTypeENCODER_FAULT:
            printf("Encoder Fault        ");
            break;
        case MPIEventTypeMOTION_DONE:
            printf("Motion Done          ");
            break;
        case MPIEventTypeMOTION_AT_VELOCITY:
            printf("Motion at Velocity   ");
            break;
        case MPIEventTypeRECORDER_FULL:
            printf("Data Recorder Full   ");
            break;
        case MPIEventTypeRECORDER_DONE:
            printf("Data Recorder Done   ");
            break;
        case MPIEventTypeEXTERNAL:
            printf("External Event       ");
            break;
        case MEIEventTypeLIMIT_USER0:
            printf("User Limit 0         ");
            break;
        case MEIEventTypeLIMIT_USER1:
            printf("User Limit 1         ");
            break;
        case MEIEventTypeLIMIT_USER2:
            printf("User Limit 2         ");
            break;
        case MEIEventTypeLIMIT_USER3:
            printf("User Limit 3         ");
            break;
        case MEIEventTypeLIMIT_USER4:
            printf("User Limit 4         ");
            break;
        case MEIEventTypeLIMIT_USER5:
            printf("User Limit 5         ");
            break;
        case MEIEventTypeLIMIT_USER6:
            printf("User Limit 6         ");
            break;
        case MEIEventTypeLIMIT_USER7:
            printf("User Limit 7         ");
            break;
        case MEIEventTypeLIMIT_TORQUE:
            printf("Torque Limit         ");
            break;
        case MEIEventTypeMOTION_OUT_OF_FRAMES:
            printf("Motion out of frames ");
            break;
        case MEIEventTypeMOTION_RESERVED0:
            printf("Reserved Event 0     ");
            break;
        case MEIEventTypeIN_POSITION_COARSE:
            printf("In Coarse Position   ");
            break;
        case MEIEventTypeIN_POSITION_FINE:
            printf("Settled              ");
            break;
        case MEIEventTypeAT_TARGET:
            printf("Cmd Pos at Target    ");
            break;
        case MEIEventTypeFRAME:
            printf("Frame Event          ");
            break;
        case MEIEventTypeAXIS_RESERVED0:
            printf("Reserved Event 0     ");
            break;
        case MEIEventTypeAXIS_RESERVED1:
            printf("Reserved Event 1     ");
            break;
        case MEIEventTypePOWER_FAILURE:
            printf("Power Failure        ");
            break;
        default:
            printf("Unknown event        ");
    }

    /* Report event sample */
    printf("Sample %10u ",((MEIEventStatusInfo*)status->info)->data.sampleCounter);

    /* Report additional information */
    switch (sourceType)
    {
        case MEIXmpSignalID_MOTOR:
            printf("Enc Position  %11d\n",
                    ((MEIEventStatusInfo*)status->info)->data.motor.encoderPosition);
            break;
        case MEIXmpSignalID_AXIS:
            printf("Axis Position %11d\n",
                    ((MEIEventStatusInfo*)status->info)->data.axis.actualPosition);
            break;
        default:
            printf("\n");
    }
}

/* Gather and display events */
void reportEventsUntilUserRequestsExit(MPIEventMgr eventMgr, MPINotify notify)
{
    MPIEventStatus  eventStatus;

    long returnValue;

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

    /* Collect motion events */
    while (meiPlatformKey(MPIWaitPOLL) < 0)
    {
        /* Obtain firmware event(s) (if any) */
        returnValue =
            mpiEventMgrService(eventMgr,
                               MPIHandleVOID);
        msgCHECK(returnValue);

        /* Poll for motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               (MPIWait)MPIWaitMSEC*20);

        if (returnValue != MPIMessageTIMEOUT)
        {
            reportEvent(&eventStatus);
        }
    }
}

int main(int     argc,
         char   *argv[])
{
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIEventMgr         eventMgr;
    MPINotify           notify;

    Service             service;

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

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                &eventMgr,
                &notify,
                &service);

    /* Gather and display events */
    reportEventsUntilUserRequestsExit(eventMgr, notify);

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

    return MPIMessageOK;
}


frame1.c -- Simple multi-axis frame generated motion profile
/* frame1.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/frame1.c 4     7/23/01 2:36p Kevinh $";
#endif

/*
:Simple multi-axis frame generated motion profile

The frame is the basic building block to generate trajectory profiles.  Frames
 can be calculated in the host computer or in the controller.  Once downloaded
 into the controller's memory, they are executed sequentially from a FIFO
 buffer.

This sample demonstrates how to generate a simple multi-axis motion profile
 using frames.

The frame structure consists of the following elements:

    MEIXmpMotionType        Mode;       /* MEIXmpMotionTypePATH_OPEN will be used.
    float                   t;          /* Time in samples
    long                    Position;   /* Position in counts
    float                   Velocity;   /* Units are counts per second
    float                   Accel;      /* Units are counts per second^2
    float                   Jerk;
    long                    Control;
    long                    Reserved;

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 <math.h>

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

#include "apputil.h"

#define AXIS_COUNT      (2)

#define DISTANCE        (10000)
#define SAMPLE_TIME     (0.005)
#define TIME_SLICE      (0.12)      /* seconds */
#define ACCEL           (2000)
#define POINT_COUNT     (1000)
#define MAX_VEL         (100)

/* Command line arguments and defaults */
long    axisNumber[AXIS_COUNT] = { 0, 1, };
long    motionNumber    = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl          control;        /* motion controller handle */
    MPIAxis             axis[AXIS_COUNT];       /* axis handle(s) */
    MPIMotion           motion;         /* motion handle */
    MEIMotionParams     params;         /* MPI motion parameters */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPINotify       notify;         /* Event notification handle */
    MPIEventMgr     eventMgr;       /* Event manager handle */
    MPIEventMask    eventMask;
    Service         service;        /* Event manager service handle */
    MEIXmpFrame     frame[AXIS_COUNT*POINT_COUNT];

    long            returnValue;    /* return value from library */
    long            point_index;
    double          x, v, a;
    double          x_start[AXIS_COUNT];
    long            index;
    long            motionDone;
    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Create axis object(s) */
    for (index = 0; index < AXIS_COUNT; index++){
        axis[index] =
            mpiAxisCreate(control,
                          axisNumber[index]);
        msgCHECK(mpiAxisValidate(axis[index]));
    }

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

    /* Get initial command positions */
    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue =
            mpiAxisCommandPositionGet(axis[index],
                                      &x_start[index]);
        msgCHECK(returnValue);
    }

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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);  /* Default sleep (msec) */
    meiASSERT(service != NULL);

    /* initialize motion parameters */
    params.frame.frame = frame;
    params.frame.point.retain = 1;  /* don't flush frame buffer. */
    params.frame.point.emptyCount = -1; /* start E-Stop if number of frames left
                                        to execute is less than this limit. -1 disables */

    /* first frame */
    point_index = 0;
    for (index = 0; index < AXIS_COUNT; index++){
        frame[point_index].Mode = MEIXmpMotionTypeSTART;
        frame[point_index].t = 0.0;
        frame[point_index].Position = 0;
        frame[point_index].Velocity = 0.0;
        frame[point_index].Accel = 0.0;
        frame[point_index].Jerk = 0.0;
        frame[point_index].Control = 0;
        frame[point_index].Reserved = 0;
        point_index++;
    }

    /* initial trajectory values */
    x = 0.0;
    v = 0.0;
    a = ACCEL;

    /* calculate the motion profile frames */
    while (x < DISTANCE) {
        for (index = 0; index < AXIS_COUNT; index++){
            frame[point_index].Mode = MEIXmpMotionTypeS_CURVE;
            frame[point_index].t = TIME_SLICE / SAMPLE_TIME; /* samples */
            frame[point_index].Position = (long)(x + x_start[index]);
            frame[point_index].Velocity = (float)(v * SAMPLE_TIME);
            frame[point_index].Accel = (float)(a * SAMPLE_TIME * SAMPLE_TIME);
            frame[point_index].Jerk = 0.0;
            frame[point_index].Control = 0;
            frame[point_index].Reserved = 0;
            point_index++;
        }

        if (v < MAX_VEL) {
            a = ACCEL;
        }
        else {
            a = 0.0;
        }
        x += v * TIME_SLICE + 0.5 * a * TIME_SLICE * TIME_SLICE;
        v += a * TIME_SLICE;
    }

    /* calculate last frame to set final target conditions exactly */
    for (index = 0; index < AXIS_COUNT; index++){
        frame[point_index].Mode = MEIXmpMotionTypeS_CURVE;
        frame[point_index].t = 2; /* 2 time samples are usually put in this last frame */
        frame[point_index].Position = (long)(x + x_start[index]);
        frame[point_index].Velocity = 0.0;
        frame[point_index].Accel = 0.0;
        frame[point_index].Jerk = 0.0;
        frame[point_index].Control = 0;
        frame[point_index].Reserved = 0;
        point_index++;
    }

    /* null frame (placeholder) */
    for (index = 0; index < AXIS_COUNT; index++){
        frame[point_index].Mode = 0;
        frame[point_index].t = 0.0;
        frame[point_index].Position = (long)(x + x_start[index]);
        frame[point_index].Velocity = 0.0;
        frame[point_index].Accel = 0.0;
        frame[point_index].Jerk = 0.0;
        frame[point_index].Control = 0;
        frame[point_index].Reserved = 0;
        point_index++;
    }

    params.frame.point.final = TRUE;
    params.frame.pointCount = point_index; /* point_index is the total number of frames for all axes */

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       (MPIMotionType)(MEIMotionTypeFRAME),
                       (MPIMotionParams*)(&params));
    fprintf(stderr,
            "mpiMotionStart returns 0x%x: %s\n",
            returnValue,
            mpiMessage(returnValue, NULL));
    msgCHECK(returnValue);

    /* Collect motion events */
    motionDone = FALSE;
    while (motionDone != TRUE) {
        MPIEventStatus  eventStatus;

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

        switch(eventStatus.type) {
            case MPIEventTypeMOTION_DONE: {
                motionDone = TRUE;
                break;
            }
            default: {
                break;
            }
        }

        fprintf(stderr,
                "mpiNotifyEventWait() returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        msgCHECK(returnValue);
    }

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

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

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

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

    for (index = 0; index < AXIS_COUNT; index++){
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

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

    return ((int)returnValue);
}


home1.c -- Simple Homing routine that captures the hardware position, sets the origin
/* home1.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/home1.c 9     7/18/01 9:32a Kevinh $"
#endif

#if defined(ARG_MAIN_RENAME)
#define main    home1Main

argMainRENAME(main, home1)
#endif

/*
:Simple Homing routine that captures the hardware position, sets the origin
  and moves back to home.

home1.c allows the user to trigger his home off an input or index
 pulse, capture the hardware position, set the origin and then move back
 to that home position.

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 CapturesPerMotor    (2) /* Default Capture configuration */

#define ACTIVE_FALLING_EDGE     (0)
#define ACTIVE_RAISING_EDGE     (1)

/* MPI Object numbers */
#define MOTION_NUMBER   (0)
#define AXIS_NUMBER     (0)
#define MOTOR_NUMBER    (0)

/* Motion Parameters */
#define VELOCITY        (5000)  /* Move velocity     */
#define ACCELERATION    (10000) /* Move acceleration */
#define DECELERATION    (10000) /* Move deceleration */

/* Capture Parameters */
#define CAPTURE_EDGE        (ACTIVE_FALLING_EDGE) /* Capture on falling edge */

/* CAPTURE_TRIGGER can be MEIMotorInputHOME or MEIMotorInputINDEX */
#define CAPTURE_TRIGGER     (MEIMotorInputHOME)   /* Capture on home pulse */

/* 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,
                 MPIMotor           *motor,
                 long                motorNumber,
                 MPICapture         *capture,
                 long                captureNumber)
{
    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,
                        *axis);
    msgCHECK(mpiMotionValidate(*motion));

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

    /* Create capture object */
    *capture =
        mpiCaptureCreate(*control,
                         captureNumber);
    msgCHECK(mpiCaptureValidate(*capture));
}

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

    /* Delete capture object */
    returnValue =
        mpiCaptureDelete(*capture);
    msgCHECK(returnValue);

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(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);
}

/* Calculate default capture number for axisNumber */
long captureNumber(long     motorNumber)
{
    return  ((motorNumber/MEIXmpMotorsPerBlock) * MEIXmpMaxLatches) +
            ((motorNumber % MEIXmpMotorsPerBlock) * CapturesPerMotor);
}

/*
   Configure caputure object

   edge: 0 for falling edge, 1 for rising edge
*/
void configureCapture(MPICapture    capture,
                      MEIMotorInput trigger,
                      long          edge)
{
    MPICaptureConfig    captureConfig;
    long                returnValue;

    /* Disable capture */
    returnValue =
        mpiCaptureArm(capture,
                      FALSE);
    msgCHECK(returnValue);

    /* Read caputre configuration */
    returnValue =
        mpiCaptureConfigGet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);

    /* Set capture parameters */
    captureConfig.trigger.mask    = trigger;
    captureConfig.trigger.pattern = edge ? trigger : 0;

    /* Write caputre configuration */
    returnValue =
        mpiCaptureConfigSet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);
}

/* Configure Home Event action */
void configureHomeAction(MPIMotor   motor,
                         MPIAction  action,
                         long       activeHigh)
{
    MPIMotorEventConfig eventConfig;
    MPIEventMask        eventMask;
    long                returnValue;

    /* Read home event configuration */
    returnValue =
        mpiMotorEventConfigGet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Configure Home Event action */
    eventConfig.action = action;
    eventConfig.trigger.polarity = activeHigh;

    /* Write home event configuration */
    returnValue =
        mpiMotorEventConfigSet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Reset Home Event */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskSET(eventMask, MPIEventTypeHOME);
    returnValue =
        mpiMotorEventReset(motor,
                           eventMask);
    msgCHECK(returnValue);
}

/* Command simple trapezoidal motion */
void simpleVelocityMove(MPIMotion   motion,
                        double      velocity,
                        double      acceleration,
                        double      deceleration)
{
    MPIMotionParams params;      /* Motion parameters      */
    MPITrajectory   trajectory;  /* Trajectory information */

    long            returnValue; /* MPI library return value */

    /* Setup trajectory structure */
    trajectory.velocity     = velocity;
    trajectory.acceleration = acceleration;
    trajectory.deceleration = deceleration;
    trajectory.jerkPercent  = 0.0;          /* Trapezoidal profile */

    /* Setup parameters structure */
    params.velocity.trajectory  = &trajectory;

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeVELOCITY,
                       &params);
    msgCHECK(returnValue);
}

/* Command simple trapezoidal motion */
void simpleTrapMove(MPIMotion   motion,
                    double      goalPosition,
                    double      velocity,
                    double      acceleration,
                    double      deceleration)
{
    MPIMotionParams params;      /* Motion parameters      */
    MPITrajectory   trajectory;  /* Trajectory information */

    long            returnValue; /* MPI library return value */

    /* Setup trajectory structure */
    trajectory.velocity     = velocity;
    trajectory.acceleration = acceleration;
    trajectory.deceleration = deceleration;

    /* Setup parameters structure */
    params.trapezoidal.trajectory   = &trajectory;
    params.trapezoidal.position     = &goalPosition;

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);
}

/* Display caputure status while waiting for the motion to be done */
void displayCaptureStatusUntilMotionDone(MPIMotion           motion,
                                         MPICapture          capture,
                                         MPICaptureStatus   *captureStatus)
{
    MPIStatus   status;
    long        motionDone;
    long        returnValue;

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

        /* Get the capture status */
        returnValue =
            mpiCaptureStatus(capture,
                             captureStatus,
                             NULL);
        msgCHECK(returnValue);

        printf("CaptureState:0x%x\r",
                captureStatus->state);

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

        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;
            }
        }
    }
    /* Display latched position */
    printf("\nLatched Home Position = %.0lf\n",
            captureStatus->latch[0]);
}

int main(int     argc,
         char   *argv[])
{
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotion           motion;
    MPIAxis             axis;
    MPIMotor            motor;
    MPICapture          capture;
    MPICaptureStatus    captureStatus;

    long    returnValue;        /* Return value from library */

    /* 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,
                &motor,
                MOTOR_NUMBER,
                &capture,
                captureNumber(MOTOR_NUMBER));

    /* Configure capture */
    configureCapture(capture,
                     CAPTURE_TRIGGER,
                     CAPTURE_EDGE);

    /* Configure Home Event action to stop */
    configureHomeAction(motor,
                        MPIActionSTOP,
                        TRUE);          /* Active High */

    /* Arm the capture */
    returnValue =
        mpiCaptureArm(capture,
                      TRUE);
    msgCHECK(returnValue);

    printf("Looking for home...\n");

    /* Start a velocity move */
    simpleVelocityMove(motion,
                       VELOCITY,
                       ACCELERATION,
                       DECELERATION);

    /* Display caputure status while waiting for the motion to be done */
    displayCaptureStatusUntilMotionDone(motion,
                                        capture,
                                        &captureStatus);

    /* Set origin to home position */
    returnValue =
        mpiAxisOriginSet(axis,
                         captureStatus.latch[0]);
    msgCHECK(returnValue);

    printf("Moving back to origin.\n");

    /* Configure Home Event action to none */
    configureHomeAction(motor,
                        MPIActionNONE,
                        TRUE);

    /* Move back to home */
    simpleTrapMove(motion,
                   0.0,     /* Go back to home position */
                   VELOCITY,
                   ACCELERATION,
                   DECELERATION);

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

    return ((int)returnValue);
}


initFlsh.c -- Controller initialization and automatic firmware download
/* initFlsh.c */

/* Copyright(c) 1991-2002 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 MEIUtilRCS[] =
    "$Header: /MainTree/XMPLib/XMP/app/initFlsh.c 4     7/23/01 2:36p Kevinh $";
#endif

/*

:Controller initialization and automatic firmware download

  ********************************* Warning ***********************************
  This application will overwrite the controller configuration that is saved
  to the Flash memory.  If connected to hardware this could cause motors to
  be enabled or to run away.  Do NOT use without proper knowledge of the system
  *****************************************************************************

This sample code demonstrates how to download Firmware to the XMP-Series
 controller.  The Firmware can also be downloaded using one of the utilities
 provided by MEI.  This sample application requires the user to specify the
 location and filename for a valid, matching Firmware file and optional
 FPGA file(s).  During initialization the controller's firmware version,
 revision, option and user version numbers are checked.  If the controller's
 version doesn't match the expected version, the firmware is downloaded to
 the controller's flash memory.

Note: The flash utility program uses the same code to download firmware to the
 flash memory.

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 <string.h>

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

#include "apputil.h"

/* Set desired Firmware version. these values could be read from a file */
#define FW_VERSION          332
#define FW_REVISION         'A'
#define FW_SUBREVISION      2
#define FW_OPTION           0
#define FW_VERSION_USER     0   /* user configurable */

#if defined(ARG_MAIN_RENAME)
#define main    initFlshMain

argMainRENAME(main, initFlsh)
#endif

#define FIRMWARE    "c:\\xmp332a2.bin"  /* this string could be read from a file */
#define FPGA0       (NULL)              /* specify NULL for default FPGA image */
#define FPGA1       (NULL)
#define FPGA2       (NULL)

long initXmp(MPIControl control, MEIFlashFiles *fileNames);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl          control;

    long    returnValue;
    long    argIndex;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MEIFlashFiles       flashFiles;

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

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

    /* copy file names into structure */
    if (FIRMWARE != NULL) {
        strcpy(flashFiles.binFile, FIRMWARE);
    }
    else {
        flashFiles.binFile[0] = '\0';
    }
    if (FPGA0 != NULL) {
        strcpy(flashFiles.FPGAFile[0], FPGA0);
    }
    else {
        flashFiles.FPGAFile[0][0] = '\0';
    }
    if (FPGA1 != NULL) {
        strcpy(flashFiles.FPGAFile[1], FPGA1);
    }
    else {
        flashFiles.FPGAFile[1][0] = '\0';
    }
    if (FPGA2 != NULL) {
        strcpy(flashFiles.FPGAFile[2], FPGA2);
    }
    else {
        flashFiles.FPGAFile[2][0] = '\0';
    }

    /* Initialize the controller, load flash if firmware is different */
    returnValue =
        initXmp(control,
                &flashFiles);   /* firmware and FPGA file name(s) */
    msgCHECK(returnValue);

    /* Delete object handles */
    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return ((int)returnValue);
}

long versionCheck(MPIControl control)
{
    MPIControlConfig    controlConfig;
    MEIControlVersion   version;

    long returnValue;

    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);

    returnValue =
        meiControlVersionGet(control,
                             &version);

    if ((version.xmp.firmware.version != FW_VERSION)
        || (version.xmp.firmware.revision != FW_REVISION)
        || (version.xmp.firmware.subRevision != FW_SUBREVISION)
        || (version.xmp.firmware.option != FW_OPTION)
        || (controlConfig.userVersion != FW_VERSION_USER)) {

        meiPlatformConsole("ERROR: Controller firmware does not match expected version.\n"
                           " Version:  %d%c%d option:%d user:%d\n"
                           " Expected: %d%c%d option:%d user:%d\n\n",
                           version.xmp.firmware.version,
                           version.xmp.firmware.revision,
                           version.xmp.firmware.subRevision,
                           version.xmp.firmware.option,
                           controlConfig.userVersion,
                           FW_VERSION,
                           FW_REVISION,
                           FW_SUBREVISION,
                           FW_OPTION,
                           FW_VERSION_USER);

        returnValue = MEIControlMessageFIRMWARE_VERSION;
    }

    /* display check result */
    meiPlatformConsole("Firmware Version Check: %s\n", mpiMessage(returnValue, NULL));

    return (returnValue);
}

long firmwareLoad(MPIControl control, MEIFlashFiles *fileNames)
{
    MEIFlash            flash;
    MEIFlashFiles       loadedFiles;
    MEIControlVersion   version;

    long                MB0 = -1;
    long                MB1 = -1;
    long                update20Khz = 0;

    long        returnValue;

    returnValue =
        mpiControlValidate(control);

    if (returnValue == MPIMessageOK) {
        /* fake a valid version so we can still use the MPI routines */
        returnValue =
            meiControlVersionGet(control,
                                 &version);

        if (returnValue == MPIMessageOK) {
            memset(&version.xmp.firmware,
                   0,
                   sizeof(version.xmp.firmware));

            version.xmp.firmware.version = version.mpi.firmware.version;
            version.xmp.firmware.option  = version.mpi.firmware.option;

            returnValue =
                meiControlVersionSet(control,
                                     &version);
        }
    }

    if (returnValue == MPIMessageOK) {
        /* Create Flash object */
        flash =
            meiFlashCreate(control);
        returnValue = meiFlashValidate(flash);
    }

    if (returnValue == MPIMessageOK) {
        meiPlatformConsole("Loading flash memory from \"%s\" ...\n",
                                   fileNames->binFile);
    }

    if (returnValue == MPIMessageOK) {
        /* Load Firmware and FPGAs from file(s) */
        returnValue =
            meiFlashMemoryFromFile(flash,
                                   fileNames,
                                   &loadedFiles);
    }

    if (returnValue == MPIMessageOK) {
        meiPlatformConsole("Code loaded and verified from \"%s\".\n",
                           loadedFiles.binFile);

        meiPlatformConsole("FPGAs loaded and verified from\n"
                            "%s\n"
                            "%s\n"
                            "%s\n\n",
                            loadedFiles.FPGAFile[0],
                            loadedFiles.FPGAFile[1],
                            loadedFiles.FPGAFile[2]);

    }
    else {
        meiPlatformConsole("Can't load flash from \"%s\"\n"
                            "\"%s\"\n"
                            "\"%s\"\n"
                            "\"%s\"\n"
                            "(%s)\n",
                            loadedFiles.binFile,
                            loadedFiles.FPGAFile[0],
                            loadedFiles.FPGAFile[1],
                            loadedFiles.FPGAFile[2],
                            mpiMessage(returnValue, NULL));
    }

    if (returnValue == MPIMessageOK) {
        returnValue = mpiControlReset(control);
        msgCHECK(returnValue);
    }

    if (returnValue == MPIMessageOK) {
        MEIControlSocketInfo socketInfo;
        MEIControlRipTideConfig config;

        returnValue = meiControlSocketInfoGet(control,
                                              &socketInfo);
        msgCHECK(returnValue);

        /* Get default RipTide configuration */
        returnValue = meiControlRipTideDefaultGet(control,
                                                   &socketInfo,
                                                   &config);
        msgCHECK(returnValue);

        /* Configure RipTide */
        if (MB0 != -1) {
            config.motionBlocks[0] = MB0;
        }

        if (MB1 != -1) {
            config.motionBlocks[1] = MB1;
        }

        config.update20khz = update20Khz;

        if (config.update20khz) {
            MPIControlConfig controlConfig;

            config.motionBlocks[0] = 1;
            config.motionBlocks[1] = 0;

            /* Set Sample Rate */
            returnValue = mpiControlFlashConfigGet(control,
                                                   NULL,
                                                   &controlConfig,
                                                   NULL);
            msgCHECK(returnValue);

            if (returnValue == MPIMessageOK) {
                controlConfig.sampleRate = 20000;

                returnValue = mpiControlFlashConfigSet(control,
                                                       NULL,
                                                       &controlConfig,
                                                       NULL);
                msgCHECK(returnValue);
            }
        }

        if (returnValue == MPIMessageOK) {
            meiPlatformConsole("Configuring RipTide\n");

            returnValue = meiControlFlashRipTideConfigSet(control,
                                                        flash,
                                                        &config);

            if (config.update20khz) {
                meiPlatformConsole("Reconfigured RipTide:\n"
                                    "Configured for 20Khz operation\n"
                                    "Main Board has 1 Motion Block\n"
                                    "Expansion Board has 0 Motion Blocks\n\n");
            }
            else {
                meiPlatformConsole("Reconfigured RipTide:\n"
                                    "Main Board has %d Motion Blocks\n"
                                    "Expansion Board has %d Motion Blocks\n\n",
                                    config.motionBlocks[0],
                                    config.motionBlocks[1]);
            }
        }
    }

    /* clean up */
    if (returnValue == MPIMessageOK) {
        returnValue = meiFlashDelete(flash);
    }

    /* re-initialize controller */
    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiControlInit(control);
    }

    /* check version values */
    if (returnValue == MPIMessageOK) {
        returnValue =
            versionCheck(control);
    }

    return returnValue;
}

long initXmp(MPIControl control, MEIFlashFiles *fileNames)
{
    long returnValue;

    /* Initialize the controller */
    returnValue =
        mpiControlInit(control);

    /* check init returnValue */
    if ((returnValue == MEIControlMessageFIRMWARE_INVALID) ||
        (returnValue == MEIControlMessageFIRMWARE_VERSION) ||
        (returnValue == MEIControlMessageFIRMWARE_VERSION_NONE)) {
        /* display warning */
        meiPlatformConsole("WARNING: %s\n\n",
                   mpiMessage(returnValue, NULL));

        /* load firmware */
        returnValue =
            firmwareLoad(control, fileNames);
    }
    else {
        if (returnValue == MPIMessageOK) {
            /* check firmware version, revision, option, and user version */
            returnValue =
                versionCheck(control);

            if (returnValue == MEIControlMessageFIRMWARE_VERSION) {
                /* load firmware */
                returnValue =
                    firmwareLoad(control, fileNames);
            }
        }
    }

    return (returnValue);
}


limitSw1.c -- Configure positive and negative hardware limit inputs.
/* limitsw1.c */

/* Copyright(c) 1991-2001 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/limitsw1.c 5     7/18/01 9:32a Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    limitsw1Main
argMainRENAME(main, limitsw1)
#endif

/*

:Configure positive and negative hardware limit inputs.

A motor's positive and negative hardware limit inputs have four configurations:

  1) Event Action   (any MPIAction such as MPIActionE_STOP)
  2) Event Trigger  (a trigger polarity, active HIGH or LOW)
  3) Direction Flag (TRUE will cause the command direction of motion to
                        qualify the events, FALSE will ignore direction,
                        based solely on the limit input state)
  4) Duration       (requires the limit condition to exist for
                        a programmable number of seconds before an
                        event will occur)

Events are configured using MPIMotorEventConfigGet/Set(...).

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 MOTOR           (0)
#define EVENT_DURATION  (0.010)     /* seconds */

/* 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);
    }
}

void limitConfigure(MPIMotor        motor,
                    MPIEventType    eventType,
                    MPIAction       action,
                    long            polarity,
                    long            direction,
                    double          duration)
{
    MPIMotorEventConfig eventConfig;
    long                returnValue;

    /* Get the current limit configuration */
    returnValue =
        mpiMotorEventConfigGet(motor,
                               eventType,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Set trigger level to Active Low (FALSE) or Active High (TRUE) */
    eventConfig.trigger.polarity = polarity;

    /* Use commanded velocity direction as a trigger qualifier. (TRUE/FALSE) */
    eventConfig.direction = direction;

    /* Wait duration seconds before triggering */
    eventConfig.duration = (float) duration;

    /* Configure motor to perform action upon limit */
    eventConfig.action = action;

    /* Set the new limit configuration */
    returnValue =
        mpiMotorEventConfigSet(motor,
                               eventType,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);
}

/* Create and initialize MPI objects */
void programInit(MPIControl         *control,
                 MPIControlType      controlType,
                 MPIControlAddress  *controlAddress,
                 MPIMotor           *motor,
                 long                motorNumber)
{
    long returnValue;

    /* Obtain a Control handle */
    *control =
        mpiControlCreate(controlType,
                         controlAddress);
    msgCHECK(mpiControlValidate(*control));

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

    /* Obtain a Motor handle */
    *motor =
        mpiMotorCreate(*control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(*motor));
}

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

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(returnValue);

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

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

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

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

    /* Change the LIMIT_HW_POS configuration */
    limitConfigure(motor,
                   MPIEventTypeLIMIT_HW_POS,    /* +HW limit        */
                   MPIActionE_STOP,             /* E-STOP on limit  */
                   TRUE,                        /* Active High      */
                   TRUE,     /* Use velocity as a trigger qualifier */
                   EVENT_DURATION);

    /* Change the LIMIT_HW_POS configuration */
    limitConfigure(motor,
                   MPIEventTypeLIMIT_HW_NEG,    /* -HW limit        */
                   MPIActionE_STOP,             /* E-STOP on limit  */
                   TRUE,                        /* Active High      */
                   TRUE,     /* Use velocity as a trigger qualifier */
                   EVENT_DURATION);

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

    return MPIMessageOK;
}


mboard1.c -- Setup multiple controllers, clear positions and perform a two-point motion.
/* mboard1.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
 */
#if defined(MEI_RCS)
    static const char MEIAppRCS[] =
        "$Header: /MainTree/XMPLib/XMP/app/mboard1.c 10    7/23/01 2:36p Kevinh $";
#endif
/*

:Setup multiple controllers, clear positions and perform a two-point motion.

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    mboard1Main

argMainRENAME(main, mboard1)
#endif

#define BOARD_COUNT (2)

#define MOTION_COUNT    (1)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            controlNumber   = 0;
long            axisNumber      = 0;
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-control", ArgTypeLONG,    &controlNumber, },
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0, },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel */
        { 10000.0,      100000.0,   100000.0,   },
    },
};

/* motion parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl          controller[BOARD_COUNT];    /* Array of control handles   */
    MPIMotion           motion[BOARD_COUNT];        /* Array of motion  handles   */
    MPIAxis             axis[BOARD_COUNT];          /* Array of axis    handles   */

    MPIControlAddress   controlAddress;

    long    returnValue;
    long    argIndex = 0;
    long    index;

    /* 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 - 1) ||    /* minus application name */
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    /*
        Initialize each controller with default settings,
        specifying the board's controller number.
     */
    for (index = 0; index < BOARD_COUNT; index++) {
        controlAddress.number = controlNumber + index;  /* setting controller number */

        controller[index] =
            mpiControlCreate(MPIControlTypeDEFAULT,
                             &controlAddress);
        msgCHECK(mpiControlValidate(controller[index]));
    }

    /* Initialize the controllers */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiControlInit(controller[index]);

        if (returnValue != MPIMessageOK) {
            fprintf(stderr,
                    "Controller #%d : mpiControlInit(0x%x) returns 0x%x: %s\n",
                    index,
                    controller[index],
                    returnValue,
                    mpiMessage(returnValue, NULL));

            exit(1);
        }
    }

    /*  Obtain Axis and Motion handle for each board */
    for (index = 0; index < BOARD_COUNT; index++) {
        axis[index] =
            mpiAxisCreate(controller[index],
                          axisNumber);
        msgCHECK(mpiAxisValidate(axis[index]));

        /* Create motion object, append axis */
        motion[index] =
            mpiMotionCreate(controller[index],
                            motionNumber,
                            axis[index]);
        msgCHECK(mpiMotionValidate(motion[index]));
    }

    /* Clear the command and actual positions on each controller */
    for (index = 0; index < BOARD_COUNT; index++) {
        double command;

        returnValue =
            mpiAxisCommandPositionGet(axis[index],
                                      &command);
        msgCHECK(returnValue);

        returnValue =
            mpiAxisOriginSet(axis[index],
                             command);
        msgCHECK(returnValue);

        /* clear position error */
        returnValue =
            mpiAxisActualPositionSet(axis[index],
                                     0.0);
        msgCHECK(returnValue);
    }

    /* Sequentially Start motion */
    for (index = 0; index < BOARD_COUNT; index++) {
        MPIMotionParams motionParams;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[0];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[0];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[0];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Start motion */
        returnValue =
            mpiMotionStart(motion[index],
                           motionType,
                           &motionParams);

        fprintf(stderr,
                "mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                motion[index],
                motionType,
                &motionParams,
                returnValue,
                mpiMessage(returnValue, NULL));

        switch (returnValue) {
            case MPIMotionMessageERROR: {
                returnValue =
                    mpiMotionAction(motion[index],
                                    MPIActionRESET);
                fprintf(stderr,
                        "mpiMotionAction(0x%x, RESET) returns 0x%x\n",
                        motion[index],
                        returnValue);
                msgCHECK(returnValue);

                /* FALL THROUGH */
            }
            case MPIMotionMessageNOT_READY: {
                returnValue = MPIMessageOK;
                continue;
            }
            case MPIMotionMessageMOVING: {
                returnValue = MPIMessageOK;
                break;
            }
            case MPIMessageOK:
            default: {
                break;
            }
        }
    }

    /* Delete the Motion handles */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiMotionDelete(motion[index]);
        msgCHECK(returnValue);
    }

    /* Delete the Axis handles */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

    /* Delete the CONTROL handles */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiControlDelete(controller[index]);
        msgCHECK(returnValue);
    }

    return ((int)returnValue);
}


mboard2.c -- Two point motion on multiple controllers with an event manager in polling mode.
/* mboard2.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
 */
#if defined(MEI_RCS)
static const char MEIAppRCS[] =
    "$Header: /MainTree/XMPLib/XMP/app/mboard2.c 12    7/23/01 2:36p Kevinh $";
#endif
/*

:Two point motion on multiple controllers with an event manager in polling mode.

Creates a two point motion sequentially on multiple controller boards.
 One event manager is used for all controllers.  The event manager is polled
 to retrieve MotionDone events from each motion.

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    mboard2Main

argMainRENAME(main, mboard2)
#endif

#define BOARD_COUNT (2)

#define MOTION_COUNT    (1)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            controlNumber   = 0;
long            axisNumber      = 0;
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-control", ArgTypeLONG,    &controlNumber, },
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0 },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel */
        { 10000.0,      100000.0,   100000.0,   },
    },
};

/* motion parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      controller[BOARD_COUNT];/* Array of control handles */
    MPIMotion       motion[BOARD_COUNT];    /* Array of motion handles */
    MPIAxis         axis[BOARD_COUNT];      /* Array of axis handles */
    MPINotify       notify[BOARD_COUNT];    /* Array of notify handles */
    MPIEventMgr     eventMgr;   /* Array of event manager handles */

    MPIEventMask    eventMask;

    MPIControlAddress   address;

    long    returnValue;
    long    argIndex=0;
    long    index;

    /* 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 - 1) ||    /* minus application name */
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    /*
        Initialize each controller with default settings,
        specifying the board's controller number.
     */
    for (index = 0; index < BOARD_COUNT; index++) {
        address.number = controlNumber + index; /* set controller number */

        controller[index] =
            mpiControlCreate(MPIControlTypeDEFAULT,
                             &address);
        msgCHECK(mpiControlValidate(controller[index]));
    }

    /* Initialize the controllers */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiControlInit(controller[index]);

        if (returnValue != MPIMessageOK) {
            fprintf(stderr,
                    "Controller #%d : mpiControlInit(0x%x) returns 0x%x: %s\n",
                    index,
                    controller[index],
                    returnValue,
                    mpiMessage(returnValue, NULL));

            exit(1);
        }
    }

    /* Obtain Axis and Motion handle for each board */
    for (index = 0; index < BOARD_COUNT; index++) {
        axis[index] =
            mpiAxisCreate(controller[index],
                          axisNumber);
        msgCHECK(mpiAxisValidate(axis[index]));

        /* Create motion object, append axis */
        motion[index] =
            mpiMotionCreate(controller[index],
                            motionNumber,
                            axis[index]);
        msgCHECK(mpiMotionValidate(motion[index]));
    }

    /* Setup one Event Manager for all boards */

    /* Create event manager object */
    eventMgr = mpiEventMgrCreate(controller[0]);
    msgCHECK(mpiEventMgrValidate(eventMgr));

    for (index = 1; index < BOARD_COUNT; index++) {
        /* Append additional controllers to the event manager */
        returnValue =
            mpiEventMgrControlAppend(eventMgr,
                                     controller[index]);
        msgCHECK(returnValue);
    }

    /* Flush any existing events */
    returnValue = mpiEventMgrFlush(eventMgr);
    msgCHECK(returnValue);

    /* Setup Notify Object */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskSET(eventMask, MPIEventTypeMOTION_DONE);

    for (index = 0; index < BOARD_COUNT; index++) {
        /* Request notification of Motion Done events from motion */
        returnValue =
            mpiMotionEventNotifySet(motion[index],
                                    eventMask,
                                    NULL);
        msgCHECK(returnValue);

        /* Create event notification object for motion */
        notify[index] =
            mpiNotifyCreate(eventMask,
                            motion[index]);
        msgCHECK(mpiNotifyValidate(notify[index]));

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

    /* Clear the command and actual positions on each controller */
    for (index = 0; index < BOARD_COUNT; index++) {
        double command;

        returnValue =
            mpiAxisCommandPositionGet(axis[index],
                                      &command);
        msgCHECK(returnValue);

        returnValue =
            mpiAxisOriginSet(axis[index],
                             command);
        msgCHECK(returnValue);

        /* clear position error */
        returnValue =
            mpiAxisActualPositionSet(axis[index],
                                     0.0);
        msgCHECK(returnValue);
    }

    /* Sequentially start motion */
    for (index = 0; index < BOARD_COUNT; index++) {
        MPIMotionParams motionParams;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[0];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[0];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[0];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Start motion */
        returnValue =
            mpiMotionStart(motion[index],
                           motionType,
                           &motionParams);

        fprintf(stderr,
                "mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                motion[index],
                motionType,
                &motionParams,
                returnValue,
                mpiMessage(returnValue, NULL));

        switch (returnValue) {
            case MPIMotionMessageERROR: {
                returnValue =
                    mpiMotionAction(motion[index],
                                    MPIActionRESET);
                fprintf(stderr,
                        "mpiMotionAction(0x%x, RESET) returns 0x%x\n",
                        motion[index],
                        returnValue);
                msgCHECK(returnValue);
                /* FALL THROUGH */
            }
            case MPIMotionMessageNOT_READY: {
                returnValue = MPIMessageOK;
                continue;
            }
            case MPIMotionMessageMOVING: {
                returnValue = MPIMessageOK;
                break;
            }
            case MPIMessageOK:
            default: {
                break;
            }
        }

        /* Collect motion events (Polling Event Manager)*/
        while (TRUE) {
            MPIEventStatus  eventStatus;

            /* Obtain firmware event(s) (if any) */
            returnValue =
                mpiEventMgrService(eventMgr,
                                   MPIHandleVOID);
            msgCHECK(returnValue);

            /* Poll for motion event */
            returnValue =
                mpiNotifyEventWait(notify[index],
                                   &eventStatus,
                                   MPIWaitPOLL);

            if (returnValue == MPIMessageTIMEOUT) {
                /* no events have happend yet */
                returnValue = MPIMessageOK;
            }

            if (returnValue == MPIMessageOK) {
                if (eventStatus.type == MPIEventTypeMOTION_DONE) {
                    /* Caught the motion done event */
                    printf("Motion Done: type %d source 0x%x info 0x%x\n",
                            eventStatus.type,
                            eventStatus.source,
                            eventStatus.info[0]);
                    break;
                }
            }
            else {
                printf("%d\n",returnValue);
                meiASSERT(FALSE);
            }
        }
    }

    /* Delete the EventMgr handle (must happen before removing Notify) */
    returnValue = mpiEventMgrDelete(eventMgr);
    msgCHECK(returnValue);

    /* Delete the Notify handles */
    for (index = 0; index < BOARD_COUNT ;index++) {
        returnValue = mpiNotifyDelete(notify[index]);
        msgCHECK(returnValue);
    }

    /* Delete the Motion handles */
    for ( index = 0; index < BOARD_COUNT ;index++) {
        returnValue = mpiMotionDelete(motion[index]);
        msgCHECK(returnValue);
    }

    /* Delete the Axis handles */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

    /* Delete the CONTROL handles */
    for (index = 0; index < BOARD_COUNT; index++) {
        returnValue = mpiControlDelete(controller[index]);
        msgCHECK(returnValue);
    }

    return ((int)returnValue);
}


motGate1.c -- Load and trigger a point to point motion using a control Gate.
/* motGate1.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/motgate1.c 5     7/18/01 9:32a Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    motGate1Main
argMainRENAME(main, motGate1)
#endif

/*

:Load and trigger a point to point motion using a control Gate.

This sample program demonstrates how to use the motion HOLD attribute and
 a control Gate, to pre-load a single axis trapezoidal profile motion.

The XMP-Series controller supports a motion HOLD attribute, which is useful
 for preloading and triggering motion profiles.  One or more motion supervisors
 can be started from the same HOLD conditions.  When multiple motion supervisors
 are triggered by the same HOLD conditions, the individual motion profiles will
 start in the same DSP sample period.  The HOLD can be set/cleared with a host
 function call, an XMP-Series controller internal variable or a Motor I/O
 state change.

The MEIMotionAttrHold{...} structure is used to configure the HOLD conditions:

 typedef    struct MEIMotionAttrHold {
    MEIMotionAttrHoldType   type;
    MEIMotionAttrHoldSource source;

    float   timeout;
} MEIMotionAttrHold;

The HOLD "type" can be one of the following:

 MEIMotionHoldTypeGATE - host software controlled.
 MEIMotionHoldTypeINPUT - XMP controller internal variable.
 MEIMotionHoldTypeMOTOR - XMP controller motor I/O state change.

For each HOLD "type" the "source" union, MEIMotionAttrHoldSource{...},
 configures the HOLD conditions:

 MEIMotionHoldTypeGATE:

  long gate - number between 0 to 31.

  The motion is held until the "gate" is cleared.  The function
  meiControlGateSet(...) is used to set/clear a gate.  When the closed
  parameter is TRUE, the gate is set, and motion is held.  When the
  closed parameter is FALSE, the gate is cleared, and motion starts.

 MEIMotionHoldTypeINPUT

  long *input - address of XMP memory location.
  long mask - bit mask, bitwise ANDed with the input value.
  long pattern - HOLD is released when masked value matches pattern.

  The motion is held until the value of the internal XMP memory location
  (pointed to by *input) bitwise ANDed with the mask matches the pattern.

 MEIMotionHoldTypeMOTOR

  long number - motor "n", XMP's dedicated inputs (Motor[n].IO.DedicaedIN.IO)
  long mask - bit mask, bitwise ANDed with the dedicated inputs.
  long pattern - HOLD is released when masked inputs matches pattern.

  The motion is held until the value of the dedicated input word
  (Motor[n].IO.DedicaedIN.IO) bitwise ANDed with the mask matches the
  pattern.

The HOLD "timeout" will cause the motion to start after the specified period
 (in seconds) even if the hold criteria have not been met.  To disable the
 timeout feature, set the timeout value to zero.

The MPI expects an array of hold attributes specifying separate attributes
 form each axis of a motion supervisor. All axes holding with the same hold
 attributes (same gate, same input, mask, and pattern) will start motion in
 the same sample even if the moves are specified using different motion
 supervisors.

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 GATE_NUMBER     (0)
#define TIMEOUT         (0) /* Wait forever */

#define GOAL_POSITION   ( 10000.0)
#define VELOCITY        ( 10000.0)
#define ACCELERATION    (100000.0)
#define DECELERATION    (100000.0)
#define JERK_PERCENT    (   100.0)

/* 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 control 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 object */
    *motion =
        mpiMotionCreate(*control,
                        motionNumber,
                        *axis);
    msgCHECK(mpiMotionValidate(*motion));
}

/* 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 control object */
    returnValue = mpiControlDelete(*control);
    msgCHECK(returnValue);
}

int main(int    argc,
         char   *argv[])
{
    MPIControl          control;        /* motion controller object handle */
    MPIMotion           motion;         /* motion object handle */
    MPIAxis             axis;           /* axis object handle */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotionParams     params;         /* motion parameters */
    MPITrajectory       trajectory;     /* motion trajectory */
    MEIMotionAttributes attributes;     /* motion attributes */
    MEIMotionAttrHold   hold;           /* hold attribute configuration */

    long                gateNumber  = GATE_NUMBER;
    float               gateTimeout = (float)TIMEOUT;

    double              position;       /* final target position */

    long                returnValue;    /* return value from library */

    /* 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);

    /* Set up motion parameters */
    position                = GOAL_POSITION;    /* counts               */
    trajectory.velocity     = VELOCITY;         /* counts per sec       */
    trajectory.acceleration = ACCELERATION;     /* counts per sec * sec */
    trajectory.deceleration = DECELERATION;     /* counts per sec * sec */
    trajectory.jerkPercent  = JERK_PERCENT;

    params.sCurve.trajectory    = &trajectory;
    params.sCurve.position      = &position;

    /* Configure Motion Attributes */
    hold.type = MEIMotionAttrHoldTypeGATE;  /* software motion Gate control */
    hold.source.gate = gateNumber;
    hold.timeout = gateTimeout;

    attributes.hold = &hold;
    params.external = &attributes;

    printf("Setting the Control Gate to TRUE.\n");

    /* Set a control gate to prevent the motion profile from executing */
    returnValue =
        meiControlGateSet(control,
                          gateNumber,
                          TRUE);    /* set gate */
    msgCHECK(returnValue);

    printf("Loading the motion.\n");

    /* Load motion profile with HOLD attribute */
    returnValue =
        mpiMotionStart(motion,
                       (MPIMotionType)
                            (MPIMotionTypeS_CURVE | MEIMotionAttrMaskHOLD),
                       &params);
    msgCHECK(returnValue);

    printf("Press any key to set the Control Gate to FALSE...\r");

    /* Wait for user key */
    meiPlatformKey(MPIWaitFOREVER);

    printf("Setting the Control Gate to FALSE (executing the motion).\n");

    /* Clear a control gate, executing the preloaded motion */
    returnValue =
        meiControlGateSet(control,
                          gateNumber,
                          FALSE);   /* clear the gate */
    msgCHECK(returnValue);

    /* Delete MPI objects */
    programCleanup(&control,
                   &motion,
                   &axis);

    return ((int)returnValue);
}


motGate2.c -- Load and trigger motion profiles using a control Gate.
/* motGate2.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/motgate2.c 7     8/01/01 2:08p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    motGate2Main
argMainRENAME(main, motGate2)
#endif

/*

:Load and trigger motion profiles using a control Gate.

This sample program demonstrates how to use the motion HOLD attribute and
 a control Gate, to pre-load a single axis motion, and to synchronize the
 start of two independent motion profiles.

Here are the steps:

 1) Move the X axis.
 2) Set a control Gate.
 3) Load a Y axis motion profile, using the HOLD attribute.
 4) Clear the control Gate, causing the Y axis motion to execute.
 5) Set a control Gate.
 6) Load X and Y axis motion profiles, using the HOLD attribute.
 7) Clear the control Gate, causing the X and Y axis motions to execute
    simultaneously.

The XMP-Series controller supports a motion HOLD attribute, which is useful
 for preloading and triggering motion profiles.  One or more motion supervisors
 can be started from the same HOLD conditions.  When multiple motion supervisors
 are triggered by the same HOLD conditions, the individual motion profiles will
 start in the same DSP sample period.  The HOLD can be set/cleared with a host
 function call, an XMP-Series controller internal variable or a Motor I/O
 state change.

The MEIMotionAttrHold{...} structure is used to configure the HOLD conditions:

 typedef    struct MEIMotionAttrHold {
    MEIMotionAttrHoldType   type;
    MEIMotionAttrHoldSource source;

    float   timeout;
} MEIMotionAttrHold;

The HOLD "type" can be one of the following:

 MEIMotionHoldTypeGATE - host software controlled.
 MEIMotionHoldTypeINPUT - XMP controller internal variable.
 MEIMotionHoldTypeMOTOR - XMP controller motor I/O state change.

For each HOLD "type" the "source" union, MEIMotionAttrHoldSource{...},
 configures the HOLD conditions:

 MEIMotionHoldTypeGATE:

  long gate - number between 0 to 31.

  The motion is held until the "gate" is cleared.  The function
  meiControlGateSet(...) is used to set/clear a gate.  When the closed
  parameter is TRUE, the gate is set, and motion is held.  When the
  closed parameter is FALSE, the gate is cleared, and motion starts.

 MEIMotionHoldTypeINPUT

  long *input - address of XMP memory location.
  long mask - bit mask, bitwise ANDed with the input value.
  long pattern - HOLD is released when masked value matches pattern.

  The motion is held until the value of the internal XMP memory location
  (pointed to by *input) bitwise ANDed with the mask matches the pattern.

 MEIMotionHoldTypeMOTOR

  long number - motor "n", XMP's dedicated inputs (Motor[n].IO.DedicaedIN.IO)
  long mask - bit mask, bitwise ANDed with the dedicated inputs.
  long pattern - HOLD is released when masked inputs matches pattern.

  The motion is held until the value of the dedicated input word
  (Motor[n].IO.DedicaedIN.IO) bitwise ANDed with the mask matches the
  pattern.

The HOLD "timeout" will cause the motion to start after the specified period
 (in seconds) even if the hold criteria have not been met.  To disable the
 timeout feature, set the timeout value to zero.

The MPI expects an array of hold attributes specifying separate attributes
 form each axis of a motion supervisor. All axes holding with the same hold
 attributes (same gate, same input, mask, and pattern) will start motion in
 the same sample even if the moves are specified using different motion
 supervisors.

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_NUMBER1  (0)
#define MOTION_NUMBER2  (1)
#define AXIS_NUMBER1    (0)
#define AXIS_NUMBER2    (1)
#define GATE_NUMBER     (0)
#define TIMEOUT         (0) /* Wait forever */

#define GOAL_POSITION1  ( 10000.0)
#define GOAL_POSITION2  (     0.0)
#define VELOCITY        ( 10000.0)
#define ACCELERATION    (100000.0)
#define DECELERATION    (100000.0)
#define JERK_PERCENT    (   100.0)

/* 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          *motionX,
                 MPIMotion          *motionY,
                 long               *motionNumber,
                 MPIAxis            *axisX,
                 MPIAxis            *axisY,
                 long               *axisNumber)
{
    long returnValue;

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

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

    /* Create X axis object using AXIS_X number on controller */
    *axisX =
        mpiAxisCreate(*control,
                      axisNumber[0]);       /* axis Number */
    msgCHECK(mpiAxisValidate(*axisX));

    /* Create Y axis object using AXIS_Y number on controller */
    *axisY =
        mpiAxisCreate(*control,
                      axisNumber[1]);       /* axis Number */
    msgCHECK(mpiAxisValidate(*axisY));

    /* Create Motion object for axisX */
    *motionX =
        mpiMotionCreate(*control,
                        motionNumber[0],        /* motion supervisor number */
                        *axisX);
    msgCHECK(mpiMotionValidate(*motionX));

    /* Create Motion object for axisY */
    *motionY =
        mpiMotionCreate(*control,
                        motionNumber[1],        /* motion supervisor number */
                        *axisY);
    msgCHECK(mpiMotionValidate(*motionY));
}

/* Delete MPI objects */
void programCleanup(MPIControl  *control,
                    MPIMotion   *motionX,
                    MPIMotion   *motionY,
                    MPIAxis     *axisX,
                    MPIAxis     *axisY)
{
    long returnValue;

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

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

    /* Delete axis Y */
    returnValue = mpiAxisDelete(*axisY);
    msgCHECK(returnValue);

    /* Delete axis X */
    returnValue = mpiAxisDelete(*axisX);
    msgCHECK(returnValue);

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

/*
  waitForMotionDone() polls motion to see if the axis is in an idle or error
  state every 10ms. When it gets an MPIStateIdle, MPIStateERROR, or
  MPIStateSTOPPING_ERROR then the waitForMotionDone() exits.
*/
void waitForMotionDone(MPIMotion motion)
{
    MPIStatus   status;
    long        motionDone;
    long        returnValue = 0;

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

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

        switch (status.state) {
            case MPIStateSTOPPING:
            case MPIStateMOVING: {
                /* Sleep for 10ms and give up control to other threads */
                meiPlatformSleep(10);
                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;
            }
        }
    }
}

/* Function demonstrating how gates can control motion */
void gateControlledMotion(MPIControl         control,
                          MPIMotion          motion1,
                          MPIMotion          motion2,
                          MPIMotionParams   *motionParams,
                          MPIMotionType      motionType,
                          long               gateNumber,
                          long               hold)
{
    long returnValue;

    /* If hold = TRUE, turn on the HOLD bit of MPIMotionType */
    if (hold==TRUE) {
        motionType = (MPIMotionType) (motionType | MEIMotionAttrMaskHOLD);
    }

    printf("Turning control gate ON.\r");

    /* Set a control gate to prevent the motion profile from executing */
    returnValue =
        meiControlGateSet(control,
                          gateNumber,
                          TRUE);    /* set gate */
    msgCHECK(returnValue);

    printf("Turned control gate ON. \n");
    printf("Press any key to call mpiMotionStart(...) %s HOLD attribute.\r",
           (hold) ? "with" : "without");

    /* Wait for a key form the user */
    meiPlatformKey(MPIWaitFOREVER);

    /* Load motion profile */
    returnValue = mpiMotionStart(motion1,
                                 motionType,
                                 motionParams);
    msgCHECK(returnValue);

    /* If user specified a second motion object */
    if (motion2!=MPIHandleVOID) {

        /* Load motion profile */
        returnValue = mpiMotionStart(motion2,
                                     motionType,
                                     motionParams);
        msgCHECK(returnValue);
    }

    printf("Called mpiMotionStart(...) %s HOLD attribute.               \n",
           (hold) ? "with" : "without");

    printf("Press any key to turn control gate OFF\r");

    /* Wait for a key form the user */
    meiPlatformKey(MPIWaitFOREVER);

    /* Clear a control gate, executing the preloaded motion */
    returnValue =
        meiControlGateSet(control,
                          gateNumber,
                          FALSE);   /* clear the gate */
    msgCHECK(returnValue);

    printf("Turned control gate OFF.              \n");
}

int main(int    argc,
         char   *argv[])
{
    MPIControl          control;    /* motion controller handle */
    MPIAxis             axisX;      /* X axis                   */
    MPIAxis             axisY;      /* Y axis                   */
    MPIMotion           motionX;    /* motion object for axisX  */
    MPIMotion           motionY;    /* motion object for axisY  */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotionParams     motionParams;   /* motion parameters            */
    MPITrajectory       trajectory;     /* trajectory information       */
    MEIMotionAttributes attributes;     /* motion attributes            */
    MEIMotionAttrHold   hold;           /* hold attribute configuration */

    long    axisNumber[2]   = { AXIS_NUMBER1,   AXIS_NUMBER2,   };
    long    motionNumber[2] = { MOTION_NUMBER1, MOTION_NUMBER2, };
    long    gateNumber      = GATE_NUMBER;
    float   gateTimeout     = (float)TIMEOUT;
    double  position;

    /* Set up motion parameters */
    trajectory.velocity     = VELOCITY;         /* counts per sec       */
    trajectory.acceleration = ACCELERATION;     /* counts per sec * sec */
    trajectory.deceleration = DECELERATION;     /* counts per sec * sec */
    trajectory.jerkPercent  = JERK_PERCENT;

    motionParams.sCurve.trajectory  = &trajectory;
    motionParams.sCurve.position    = &position;

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

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                &motionX,
                &motionY,
                motionNumber,
                &axisX,
                &axisY,
                axisNumber);

    /* Configure Motion Attributes */
    hold.type = MEIMotionAttrHoldTypeGATE;  /* software motion Gate control */
    hold.source.gate = gateNumber;
    hold.timeout = gateTimeout;

    attributes.hold = &hold;
    motionParams.external = &attributes;

    /* Tell axis to go to GOAL_POSITION1 */
    position = GOAL_POSITION1;  /* counts */

    printf("\n*** X AXIS ***\n");

    /* Execute X-axis motion without HOLD attribute */
    gateControlledMotion(control,
                         motionX,
                         MPIHandleVOID,
                         &motionParams,
                         MPIMotionTypeS_CURVE,
                         gateNumber,
                         FALSE);

    printf("Wating for motion to complete...\n");

    /* Wait for motion to complete */
    waitForMotionDone(motionX);

    printf("\n*** Y AXIS ***\n");

    /* Execute Y-axis motion with HOLD attribute */
    gateControlledMotion(control,
                         motionY,
                         MPIHandleVOID,
                         &motionParams,
                         MPIMotionTypeS_CURVE,
                         gateNumber,
                         TRUE);

    printf("Wating for motion to complete...\n");

    /* Wait for motion to complete */
    waitForMotionDone(motionY);

    /* Tell axis to go to GOAL_POSITION2 */
    position = GOAL_POSITION2;  /* counts */

    printf("\n*** X & Y AXES ***\n");

    /* Execute X,Y-axes motion with HOLD attribute */
    gateControlledMotion(control,
                         motionX,
                         motionY,
                         &motionParams,
                         MPIMotionTypeS_CURVE,
                         gateNumber,
                         TRUE);

    /* Delete MPI objects */
    programCleanup(&control,
                   &motionX,
                   &motionY,
                   &axisX,
                   &axisY);

    return MPIMessageOK;
}


motid1.c -- Point to Point motion with Motion Done event identification.
/* motId1.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/motid1.c 19    7/23/01 2:36p Kevinh $";
#endif

/*

:Point to Point motion with Motion Done event identification.

The MPI supports a motion attribute that allows an application to tag
 a mpiMotionStart(...) or mpiMotionModify(...) with an identification
 value.

This feature is useful in tracking the commanded motions to the done
 events.  It is also applicable when using the AUTO_START attribute
 with mpiMotionModify(...).

For example:

Suppose mpiMotionStart(...) is called with the MPIMotionAttrID attribute,
 and the params.attributes.id = 1 and later mpiMotionModify(...) is called
 with params.attributes.id = 2.

Case 1: MPIMotionAttrAUTO_START is not used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageIDLE, there will be 1 DONE
 event with info->data.motion.id = 1.

Case 2: MPIMotionAttrAUTO_START is used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageAUTO_START,
 there will be 2 DONE events. The first will have info->data.motion.id = 1
 and the second will have info->data.motion.id = 2.

The XMP-Series controller supports some user data to be copied during Events
 and then later retrieved from the Host via the Notify object.

There are MEIXmpSignalUserData words of data for the motion, axis and motor
 event sources.  The default configuration for the first word is the XMP's
 sampleCounter.  The default for the second word is "actualPosition" for axis
 event sources, and "encoderPosition" for motor event sources.

In this sample, the second word for motion and axis events is configured for "id".

Note:  Keeping the first word configured for the "sampleCounter" is very
 helpful in determining event sequences.

Here is the default configuration for the event data:

    union {
        long sampleCounter;
        struct {
            long sampleCounter;
        } motion;
        struct {
            long sampleCounter;
            long actualPosition;
        } axis;
        struct {
            long sampleCounter;
            long encoderPosition;
        } motor;
        long word[MEIXmpSignalUserData];
    } data;

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    motId1Main

argMainRENAME(main, motId1)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0,   };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Motion Parameters */
double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  },
    { 0.0,      },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent*/
        { 10000.0,      100000.0,   100000.0,   0.0,    },
    },
};

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

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

    MPIEventMask    eventMask;

    MEIEventNotifyData  motionData;
    MEIXmpAxis          *xmpAxis;

    long    returnValue;    /* return value from library */

    long    index;
    long    moveId;         /* identification tag */
    long    motionDone;

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

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

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

    /* Get current user data configuration */
    mpiEventMaskCLEAR(eventMask);
    returnValue =
        mpiMotionEventNotifyGet(motion,
                                &eventMask,
                                &motionData);
    msgCHECK(returnValue);

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

    /* Request ID data from motion event info[...] */
    returnValue  =
        mpiAxisMemory(axis,     /* use ID from first axis in motion object */
                      &(void *)xmpAxis);
    msgCHECK(returnValue);

    motionData.address[1] = (void *)(&xmpAxis->MoveID);

    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                &motionData);
    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 */
    meiASSERT(service != NULL);

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

    /* Loop repeatedly */
    index       = 0;
    moveId      = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus  eventStatus;

        if (motionDone == TRUE) {
            MPIMotionParams motionParams;       /* motion parameters */

            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            motionParams.attributes.id = moveId;        /* identification tag */

            returnValue =
                mpiMotionStart(motion,
                               (MPIMotionType)(motionType | MPIMotionAttrMaskID),
                               &motionParams);
            msgCHECK(returnValue);

            printf("\nMotion Start #%d...", moveId);

            moveId++;

            motionDone = FALSE;
        }

        /* Wait for motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            MEIEventStatusInfo *info;

            info = (MEIEventStatusInfo *)eventStatus.info;

            printf(" done #%ld",
                    info->data.word[1]);        /* user configurable data */

            if (++index >= MOTION_COUNT) {
                index = 0;
            }

            motionDone = TRUE;
        }
    }

    printf("\n");

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

    returnValue = mpiAxisDelete(axis);
    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);
}


motid2.c -- Point to Point motion with motion/axis event identification.
/* motId2.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.
 */

/*

:Point to Point motion with motion/axis event identification.

The MPI supports a motion attribute that allows an application to tag
 a mpiMotionStart(...) or mpiMotionModify(...) with an identification
 value.

This feature is useful in tracking the commanded motions to the done
 events.  It is also applicable when using the AUTO_START attribute
 with mpiMotionModify(...).

For example:

Suppose mpiMotionStart(...) is called with the MPIMotionAttrID attribute,
 and the params.attributes.id = 1 and later mpiMotionModify(...) is called
 with params.attributes.id = 2.

Case 1: MPIMotionAttrAUTO_START is not used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageIDLE, there will be 1 DONE
 event with info->data.motion.id = 1.

Case 2: MPIMotionAttrAUTO_START is used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageAUTO_START,
 there will be 2 DONE events. The first will have info->data.motion.id = 1
 and the second will have info->data.motion.id = 2.

The XMP-Series controller supports some user data to be copied during Events
 and then later retrieved from the Host via the Notify object.

There are MEIXmpSignalUserData words of data for the motion, axis and motor
 event sources.  The default configuration for the first word is the XMP's
 sampleCounter.  The default for the second word is "actualPosition" for axis
 event sources, and "encoderPosition" for motor event sources.

In this sample, the second word for motion and axis events is configured for "id".

Note:  Keeping the first word configured for the "sampleCounter" is very
 helpful in determining event sequences.

Here is the default configuration for the event data:

    union {
        long sampleCounter;
        struct {
            long sampleCounter;
        } motion;
        struct {
            long sampleCounter;
            long actualPosition;
        } axis;
        struct {
            long sampleCounter;
            long encoderPosition;
        } motor;
        long word[MEIXmpSignalUserData];
    } data;

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    motId2Main

argMainRENAME(main, motId2)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0,   };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Motion Parameters */
double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  },
    { 0.0,      },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent*/
        { 10000.0,      100000.0,   100000.0,   0.0,    },
    },
};

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

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

    MPIEventMask    eventMask;

    MEIEventNotifyData  motionData;
    MEIXmpAxis          *xmpAxis;

    long    returnValue;    /* return value from library */

    long    index;
    long    moveId;     /* identification tag */
    long    motionDone; /* flag when Done occurs */

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

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

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

    /* Get current user data configuration */
    mpiEventMaskCLEAR(eventMask);
    returnValue =
        mpiMotionEventNotifyGet(motion,
                                &eventMask,
                                &motionData);
    msgCHECK(returnValue);

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

    /* Request ID data from motion event info[...] */
    returnValue  =
        mpiAxisMemory(axis,     /* use ID from first axis in motion object */
                      &(void *)xmpAxis);
    msgCHECK(returnValue);

    motionData.address[1] = (void *)(&xmpAxis->MoveID);

    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                &motionData);
    msgCHECK(returnValue);

    /* Configure sampleCounter and ID to be returned from Axis event sources */
    returnValue =
        mpiAxisEventNotifySet(axis,
                              eventMask,    /* use the same eventMask as motion */
                              &motionData); /* use the same data as motion */
    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 */
    meiASSERT(service != NULL);

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

    /* Loop repeatedly */
    index       = 0;
    moveId      = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MEIEventStatusInfo  *info;

        if (motionDone) {
            MPIMotionParams     motionParams;       /* motion parameters */

            /* fill in the MPIMotionParams structure */
            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            motionParams.attributes.id = moveId;    /* identification tag */

            returnValue =
                mpiMotionStart(motion,
                               (MPIMotionType)(motionType | MPIMotionAttrMaskID),
                               &motionParams);
            msgCHECK(returnValue);

            printf("\n\nMotion Start #%d...\n", moveId);

            moveId++;

            motionDone = FALSE;
        }

        /* Wait for motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        info = (MEIEventStatusInfo *)eventStatus.info;

        switch (eventStatus.type) {
            /* In Coarse Event from axis source */
            case MEIEventTypeIN_POSITION_COARSE: {
                printf("  InCoarse #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeIN_POSITION_FINE: {
                printf("  InFine #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeAT_TARGET: {
                printf("  AtTarget #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* Motion Done Event from motion source */
            case MPIEventTypeMOTION_DONE: {
                printf("  Done #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.motion.sampleCounter);

                motionDone = TRUE;

                if (++index >= MOTION_COUNT) {
                    index = 0;
                }
                break;
            }
            default: {
                printf("  %d #%ld(%ld)",
                       eventStatus.type,
                       info->data.word[1],
                       info->data.word[0]);
                break;
            }
        }
    }

    printf("\n");

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

    returnValue = mpiAxisDelete(axis);
    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);
}


motid3.c -- Point to Point motion with ID, APPEND, and HOLD attributes.
/* motId3.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.
 */

/*

:Point to Point motion with ID, APPEND, and HOLD attributes.

The MPI supports a motion attribute that allows an application to tag
 a mpiMotionStart(...) or mpiMotionModify(...) with an identification
 value.

This feature is useful in tracking the commanded motions to the done
 events.  It is also applicable when using the AUTO_START attribute
 with mpiMotionModify(...).

For example:

Suppose mpiMotionStart(...) is called with the MPIMotionAttrID attribute,
 and the params.attributes.id = 1 and later mpiMotionModify(...) is called
 with params.attributes.id = 2.

Case 1: MPIMotionAttrAUTO_START is not used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageIDLE, there will be 1 DONE
 event with info->data.motion.id = 1.

Case 2: MPIMotionAttrAUTO_START is used.
if mpiMotionModify(...) returns MPIMessageOK, there will be 1 DONE event
 with info->data.motion.id = 2.
if mpiMotionModify(...) returns MPIMotionMessageAUTO_START,
 there will be 2 DONE events. The first will have info->data.motion.id = 1
 and the second will have info->data.motion.id = 2.

The XMP-Series controller supports some user data to be copied during Events
 and then later retrieved from the Host via the Notify object.

There are MEIXmpSignalUserData words of data for the motion, axis and motor
 event sources.  The default configuration for the first word is the XMP's
 sampleCounter.  The default for the second word is "actualPosition" for axis
 event sources, and "encoderPosition" for motor event sources.

In this sample, the second word for motion and axis events is configured for "id".

Note:  Keeping the first word configured for the "sampleCounter" is very
 helpful in determining event sequences.

Here is the default configuration for the event data:

    union {
        long sampleCounter;
        struct {
            long sampleCounter;
        } motion;
        struct {
            long sampleCounter;
            long actualPosition;
        } axis;
        struct {
            long sampleCounter;
            long encoderPosition;
        } motor;
        long word[MEIXmpSignalUserData];
    } data;

The APPEND attribute is useful for buffering moves in the controller.
 When the APPEND attribute is used with mpiMotionStart(...), a new motion
 profile is added to the end of any previously loaded motion profiles in
 the controller.  The XMP-Series controller automatically buffers the APPENDed
 MotionStarts, executing each sequentially after the Motion Done criteria has
 been met for each profile.  Each MotionStart profile generates a Motion Done
 event to the Host.

When APPEND attribute is used with mpiMotionModify(...), the motion profile
 is added to the end of any previously loaded motion profiles in the
 controller.  The XMP-Series controller automatically buffers the APPENDed
 MotionModifies, executing each sequentially.  Only the very last
 MotionModify waits for the Motion Done criteria to be met before generating
 a Motion Done event to the host.

The XMP-Series controller supports a motion HOLD attribute, which is useful
 for preloading and triggering motion profiles.  One or more motion
 supervisors can be started from the same HOLD conditions.  When multiple
 motion supervisors are triggered by the same HOLD conditions, the individual
 motion profiles will start in the same DSP sample period.  The HOLD can be
 set/cleared with a host function call, an XMP-Series controller internal
 variable or a Motor I/O state change.

The MEIMotionAttrHold{...} structure is used to configure the HOLD conditions:

 typedef    struct MEIMotionAttrHold {
    MEIMotionAttrHoldType   type;
    MEIMotionAttrHoldSource source;

    float   timeout;
} MEIMotionAttrHold;

The HOLD "type" can be one of the following:

 MEIMotionHoldTypeGATE - host software controlled.
 MEIMotionHoldTypeINPUT - XMP controller internal variable.
 MEIMotionHoldTypeMOTOR - XMP controller motor I/O state change.

For each HOLD "type" the "source" union, MEIMotionAttrHoldSource{...},
 configures the HOLD conditions:

 MEIMotionHoldTypeGATE:

  long gate - number between 0 to 31.

  The motion is held until the "gate" is cleared.  The function
  meiControlGateSet(...) is used to set/clear a gate.  When the closed
  parameter is TRUE, the gate is set, and motion is held.  When the
  closed parameter is FALSE, the gate is cleared, and motion starts.

 MEIMotionHoldTypeINPUT

  long *input - address of XMP memory location.
  long mask - bit mask, bitwise ANDed with the input value.
  long pattern - HOLD is released when masked value matches pattern.

  The motion is held until the value of the internal XMP memory location
  (pointed to by *input) bitwise ANDed with the mask matches the pattern.

 MEIMotionHoldTypeMOTOR

  long number - motor "n", XMP's dedicated inputs (Motor[n].IO.DedicaedIN.IO)
  long mask - bit mask, bitwise ANDed with the dedicated inputs.
  long pattern - HOLD is released when masked inputs matches pattern.

  The motion is held until the value of the dedicated input word
  (Motor[n].IO.DedicaedIN.IO) bitwise ANDed with the mask matches the
  pattern.

The HOLD "timeout" will cause the motion to start after the specified period
 (in seconds) even if the hold criteria have not been met.  To disable the
 timeout feature, set the timeout value to zero.

The MPI expects an array of hold attributes specifying separate attributes
 form each axis of a motion supervisor. All axes holding with the same hold
 attributes (same gate, same input, mask, and pattern) will start motion in
 the same sample even if the moves are specified using different motion
 supervisors.

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    motionId3Main

argMainRENAME(main, motionId3)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (1)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0,   };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;
long            gateNumber = 0;
float           gateTimeout = (float)0.0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },
    {   "-gate",    ArgTypeLONG,    &gateNumber,    },
    {   "-timeout", ArgTypeFLOAT,   &gateTimeout,   },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Motion Parameters */
double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  },
    { 0.0,      },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent*/
        { 10000.0,      100000.0,   100000.0,   0.0,    },
    },
};

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

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

    MPIEventMask    eventMask;

    MEIEventNotifyData  motionData;
    MEIXmpAxis          *xmpAxis;

    MPIMotionParams     motionParams;   /* motion parameters */
    MEIMotionAttributes attributes;     /* motion attributes */
    MEIMotionAttrHold   hold;           /* hold attribute configuration */

    long    returnValue;    /* return value from library */

    long    index;
    long    moveId;     /* identification tag */
    long    motionDone; /* flag when Done occurs */

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST) ||
        (gateNumber < 0) ||
        (gateNumber >= MEIXmpMaxGates) ||
        (gateTimeout < 0.0)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n"
                           "\t\t[-gate # (0 .. %d)]\n"
                           "\t\t[-timeout # (0.0 ..)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1,
                            MEIXmpMaxGates - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

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

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

    /* Get current user data configuration */
    mpiEventMaskCLEAR(eventMask);
    returnValue =
        mpiMotionEventNotifyGet(motion,
                                &eventMask,
                                &motionData);
    msgCHECK(returnValue);

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

    /* Request ID data from motion event info[...] */
    returnValue  =
        mpiAxisMemory(axis,     /* use ID from first axis in motion object */
                      &(void *)xmpAxis);
    msgCHECK(returnValue);

    /* Configure the second user data word for the ID */
    motionData.address[1] = (void *)(&xmpAxis->MoveID);

    /* Configure sampleCounter and ID to be returned from Motion event sources */
    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                &motionData);
    msgCHECK(returnValue);

    /* Configure sampleCounter and ID to be returned from Axis event sources */
    returnValue =
        mpiAxisEventNotifySet(axis,
                              eventMask,    /* use the same eventMask as motion */
                              &motionData); /* use the same data as motion */
    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 */
    meiASSERT(service != NULL);

    /* Configure Motion Attributes */
    hold.type = MEIMotionAttrHoldTypeGATE;  /* software motion Gate control */
    hold.source.gate = gateNumber;
    hold.timeout = gateTimeout;

    attributes.hold = &hold;
    motionParams.external = &attributes;

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

    /* Loop repeatedly */
    index       = 0;
    moveId      = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MEIEventStatusInfo  *info;

        if (motionDone) {

            /* Set a control gate to prevent motion profile from executing */
            returnValue =
                meiControlGateSet(control,
                                  gateNumber,
                                  TRUE);    /* set gate */
            msgCHECK(returnValue);

            for (index = 0; index < MOTION_COUNT; index++) {
                /* fill in the MPIMotionParams structure */
                switch (motionType) {
                    case MPIMotionTypeS_CURVE: {
                        motionParams.sCurve = sCurve[index];
                        break;
                    }
                    case MPIMotionTypeTRAPEZOIDAL: {
                        motionParams.trapezoidal = trapezoidal[index];
                        break;
                    }
                    case MPIMotionTypeVELOCITY: {
                        motionParams.velocity = velocity[index];
                        break;
                    }
                    default: {
                        meiASSERT(FALSE);
                        break;
                    }
                }

                motionParams.attributes.id = moveId;    /* identification tag */

                returnValue =
                    mpiMotionStart(motion,
                                   (MPIMotionType)(motionType |
                                   MPIMotionAttrMaskID |
                                   MPIMotionAttrMaskAPPEND |
                                   MEIMotionAttrMaskHOLD),
                                   &motionParams);
                msgCHECK(returnValue);

                printf("\nMotion Start #%d...\n", moveId);

                moveId++;
            }

            /* Clear a control gate, executing the preloaded motion */
            returnValue =
                meiControlGateSet(control,
                                  gateNumber,
                                  FALSE);   /* clear the gate */
            msgCHECK(returnValue);

            index = 0;
            motionDone = FALSE;
        }

        /* Wait for motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        info = (MEIEventStatusInfo *)eventStatus.info;

        switch (eventStatus.type) {
            /* In Coarse Event from axis source */
            case MEIEventTypeIN_POSITION_COARSE: {
                printf("  InCoarse #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeIN_POSITION_FINE: {
                printf("  InFine #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeAT_TARGET: {
                printf("  AtTarget #%ld(%ld)",
                       info->data.word[1],      /* user configurable data */
                       info->data.axis.sampleCounter);
                break;
            }
            /* Motion Done Event from motion source */
            case MPIEventTypeMOTION_DONE: {
                printf("  Done #%ld(%ld)\n",
                       info->data.word[1],
                       info->data.motion.sampleCounter);

                if (++index >= MOTION_COUNT) {
                    index = 0;
                    motionDone = TRUE;
                }
                break;
            }
            default: {
                printf("  %d #%ld(%ld)",
                       eventStatus.type,
                       info->data.word[1],
                       info->data.word[0]);
                break;
            }
        }
    }

    printf("\n");

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

    returnValue = mpiAxisDelete(axis);
    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);
}


motion1.c -- Perform point to point trapezoidal profile motion.
/* motion1.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/motion1.c 12    7/18/01 9:32a Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    motion1Main

argMainRENAME(main, motion1)
#endif

/*

:Perform point to point trapezoidal profile motion.

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.

Warning!  This is a sample program to assist in the longegration 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 <math.h>
#include "stdmpi.h"
#include "stdmei.h"
#include "apputil.h"

#define MOTION_NUMBER   (0)
#define AXIS_NUMBER     (0)

#define GOAL_POSITION   (50000)
#define VELOCITY        (5000)
#define ACCELERATION    (10000)
#define DECELERATION    (20000)

/* 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);
}

/* Command simple trapezoidal motion */
long simpleTrapMove(MPIMotion   motion,
                    double      goalPosition,
                    double      velocity,
                    double      acceleration,
                    double      deceleration)
{
    MPIMotionParams     params;     /* Motion parameters      */
    MPITrajectory       trajectory; /* Trajectory information */

    long returnValue;               /* MPI library return value */

    /* Setup trajectory structure */
    trajectory.velocity     = velocity;
    trajectory.acceleration = acceleration;
    trajectory.deceleration = deceleration;

    /* Setup parameters structure */
    params.trapezoidal.trajectory   = &trajectory;
    params.trapezoidal.position     = &goalPosition;

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);

    return returnValue;
}

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 simple motion */
    simpleTrapMove(motion,
                   GOAL_POSITION,
                   VELOCITY,
                   ACCELERATION,
                   DECELERATION);

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

    return MPIMessageOK;
}


motion2.c -- Two-axis motion, with synchronized and coordinated S-Curve profiles.
/* motion2.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/motion2.c 18    7/23/01 2:36p Kevinh $";
#endif

/*

:Two-axis motion, with synchronized and coordinated S-Curve profiles.

This sample demonstrates how to create a two-axis motion system, using
 a single motion object.  Simple point to point motion is commanded
 using S-Curve (or Trapezoidal) profile.

When motion is commanded to point 0, using the MPIMotionAttrMaskSYNC_START
 attribute, the controller starts the motion profiles for both axes at the
 same time.  Each axis uses it's own MPITrajectory, independently reaching
 their target positions at different times.

When motion is commanded to point 1, (no attributes), the controller
 starts and completes the motion profiles for the axes at the same time.
 Each axis shares a single MPITrajectory, by breaking the vector trajectory
 values into component trajectory values based on the ratio of the axis
 distances.  The result is point to point linear coordinated move for the
 axes, specified by a target "position" for each axis and a single vector
 "trajectory" for the axes.

During motion, the motion status is polled from the controller.  When both
 axes complete their motions (state = IDLE), the command and actual positions,
 and motion status information is displayed.

If an error condition occurs during motion, the program clears the error
 using mpiMotionAction(motion, MPIActionRESET).

Note:  When multiple axes are associated with a motion supervisor, the
 controller automatically combines the individual axis and motor status
 into the motion status.  Thus, if a Stop, E-Stop or Abort action occurs
 on one axis, the event will be propogated automatically to the other axes.

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    motion2Main

argMainRENAME(main, motion2)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Motion Parameters */
double position[MOTION_COUNT][AXIS_COUNT] = {
    { 2000.0,   20000.0,    },
    { 0.0,      0.0,        },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
};

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

long
    motionIdle(MPIMotion    motion,
               MPIStatus    *status);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIAxis     axisX;      /* X axis */
    MPIAxis     axisY;      /* Y axis */
    MPIMotion   motion;     /* motion object */

    long    returnValue;    /* return value from library */

    long    index;

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create X axis object using axis number 0 on controller*/
    axisX =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axisX));

    /* Create Y axis object using axis number 1 on controller */
    axisY =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axisY));

    /* Create motion object */
    /* Append X axis to motion */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axisX);
    msgCHECK(mpiMotionValidate(motion));

    /* Append Y axis to motion */
    returnValue =
        mpiMotionAxisAppend(motion,
                            axisY);
    msgCHECK(returnValue);

    /* Loop repeatedly */
    index = 0;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        long    motionDone;

        if (returnValue == MPIMessageOK) {
            MPIMotionType   type;
            MPIMotionParams motionParams;

            type = motionType;

            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    if (index == 0) {
                        type = (MPIMotionType)(type | MPIMotionAttrMaskSYNC_START);
                    }
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    if (index == 0) {
                        type = (MPIMotionType)(type | MPIMotionAttrMaskSYNC_START);
                    }
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            printf("\nMotionStart...");

            returnValue =
                mpiMotionStart(motion,
                               type,
                               &motionParams);

            if (returnValue != MPIMessageOK) {
                printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                       motion,
                       type,
                       &motionParams,
                       returnValue,
                       mpiMessage(returnValue, NULL));
            }
        }

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

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

            switch (status.state) {
                case MPIStateIDLE: {
                    motionDone = TRUE;

                    motionIdle(motion,
                               &status);

                    /* Wait for the motor to settle */
                    meiPlatformSleep(300);  /* msec */

                    break;
                }
                case MPIStateERROR: {
                    motionDone = TRUE;

                    /* Clear any error condition(s) */
                    returnValue =
                        mpiMotionAction(motion,
                                        MPIActionRESET);
                    msgCHECK(returnValue);

                    /* Wait for reset to take effect */
                    meiPlatformSleep(100);      /* msec */

                    break;
                }
                default: {
                    break;
                }
            }
        }

        if (++index >= MOTION_COUNT) {
            index = 0;
        }
    }

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

    returnValue = mpiAxisDelete(axisY);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisX);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}

long motionIdle(MPIMotion motion,
                MPIStatus *status)
{
    long    returnValue;

    double  actual[AXIS_COUNT];
    double  command[AXIS_COUNT];

    long    index;

    printf("MotionDone: status: state %d action %d eventMask 0x%x\n"
           "\tatTarget %d settled %d %s\n",
            status->state,
            status->action,
            status->eventMask,
            status->atTarget,
            status->settled,
            (status->settled == FALSE)
                    ? "=== NOT SETTLED ==="
                    : "");

    returnValue =
        mpiMotionPositionGet(motion,
                             actual,
                             command);
    msgCHECK(returnValue);

    /* Display axis positions */
    for (index = 0; index < AXIS_COUNT; index++) {
        printf("\taxis[%d]    position: command %11.3lf\tactual %11.3lf\n",
                index,
                command[index],
                actual[index]);
    }

    return (returnValue);
}


motion3.c -- Custom point to point S-curve motion with velocity specified using position.
/* motion3.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.
 */

/*

:Custom point to point S-curve motion with velocity specified using position.

This program demonstrates how to generate a point to point move using a custom
 velociy profile. The motion profile is specified by a structure called
 moveData[...] containing positions, velocities, and jerk percents.
 The motion is commanded using:

  1) mpiMotionStart(...) with the FINAL_VEL attribute, which loads the first
     point and begins motion.

  2) mpiMotionModify(...) with the FINAL_VEL and APPEND attribute, which adds
     the rest of the motion profiles to the end of the first profile.

The resultant motion profile will reach the "midVelocity" at the specified
 "midPosition" and the "endVelocity" at the specified "endPosition."
 MOVE_SEGMENTS is defined by the size of moveData[...].

The following equation was used to determine accelerations and decelerations.

  acceleration = (velocity1^2 - velocity0^2) / (2 * (position1 - position2))

There is a minimal error checking in this sample.

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 <math.h>

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

#if defined(ARG_MAIN_RENAME)
#define main    motion3Main

argMainRENAME(main, motion3)
#endif

#define AXIS_NUMBER         (0)     /* Axis to be moved */
#define MOTION_NUMBER       (0)     /* Motion supervisor number */
#define JERK_PERCENT        (100.0)

long    axisNumber      = 0;
long    motionNumber    = 0;

struct {
    double  midposition;
    double  endPosition;
    double  midVelocity;
    double  endVelocity;
    double  jerkPercent;

} moveData[] =  {

/*  midposition,    endPosition,    midVel,     endVel, jerkPercent */
    {1200,          3000,           27000.0,    3000.0,     JERK_PERCENT,   },
    {4200,          6000,           15000.0,    3000.0,     JERK_PERCENT,   },
    {8900,          11300,          44000.0,    0.0,        JERK_PERCENT,   },

/*
    {6000,          0,              15000.0,    0.0,        JERK_PERCENT,   },
   Add additional points like the above line
*/

};

Arg argList[] = {
    {   NULL,       ArgTypeINVALID, NULL,   }
};

#define MOVE_SEGMENTS (sizeof(moveData)/sizeof(moveData[0]))

long    parseCommandLine(int                argc,
                         char               *argv[],
                         MPIControlType     *controlType,
                         MPIControlAddress  *controlAddress);

long    createObjects(MPIControl            *control,
                      MPIAxis               *axis,
                      MPIMotion             *motion,
                      MPIControlType        *controlType,
                      MPIControlAddress     *controlAddress,
                      long                  axisNumber);

long    deleteObjects(MPIControl    *control,
                      MPIAxis       *axis,
                      MPIMotion     *motion);

int main(int    argc,
         char   *argv[])
{

    MPIControl          control;        /* Motion controller object handle */
    MPIMotion           motion;         /* Motion object handle */
    MPIAxis             axis;           /* Axis object handle */
    MPIMotionParams     params;         /* Motion parameters */
    MPITrajectory       trajectory;     /* Motion trajectory */
    MEIMotionAttributes attributes;     /* Motion attributes */
    MPIMotionAttrMask   attrMask;       /* Motion attributes mask */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    returnValue;
    long    segmentCount;
    double  endPosition;

    parseCommandLine(argc,
                     argv,
                     &controlType,
                     &controlAddress);

    createObjects(&control,
                  &axis,
                  &motion,
                  &controlType,
                  &controlAddress,
                  axisNumber);

    segmentCount = 0;
    moveData[-1].endVelocity = 0;
    moveData[-1].endPosition = 0;

    while (segmentCount < MOVE_SEGMENTS){
        /* Setup new motion parameters */
        attrMask =
            MPIMotionAttrMaskAPPEND |
            MEIMotionAttrMaskFINAL_VEL;

        endPosition              =  moveData[segmentCount].endPosition;
        trajectory.velocity      =  moveData[segmentCount].midVelocity;
        attributes.finalVelocity = &moveData[segmentCount].endVelocity;

    /*
       Acceleration = (velocity1^2 - velocity0^2) / (2 * (position1 - position2))
       Point 0 is 'endPosition' of the previous move. Point 1 is 'midposition'.
    */

        trajectory.acceleration  =
            fabs(((pow(moveData[segmentCount].midVelocity, 2) -
            pow(moveData[segmentCount - 1].endVelocity, 2)) /
            (2 * (moveData[segmentCount].midposition -
            moveData[segmentCount - 1].endPosition))));

    /*
       Acceleration = (velocity1^2 - velocity0^2) / (2 * (position1 - position2))
       Point 0 is 'midposition'. Point 1 is 'endPosition'.
    */

        trajectory.deceleration  =
            fabs(((pow(moveData[segmentCount].endVelocity, 2) -
            pow(moveData[segmentCount].midVelocity, 2)) /
            (2 * (moveData[segmentCount].endPosition -
            moveData[segmentCount].midposition))));

        trajectory.jerkPercent   =  moveData[segmentCount].jerkPercent;

        if (!segmentCount){
            /* First point */
            params.sCurve.position   = &endPosition;
            params.sCurve.trajectory = &trajectory;
            params.external = &attributes;
            /* Start motion */
            returnValue =
                mpiMotionStart(motion,
                               MPIMotionTypeS_CURVE | attrMask,
                               &params);
            msgCHECK(returnValue);
        }
        else{   /* Not first point */
            /* Modify motion */
            returnValue =
                mpiMotionModify(motion,
                                MPIMotionTypeS_CURVE | attrMask,
                                &params);
            msgCHECK(returnValue);
        }
        segmentCount++;
    }

    deleteObjects(&control,
                  &axis,
                  &motion);

    return (returnValue);
}

long    parseCommandLine(int                argc,
                         char               *argv[],
                         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) ||
        (axisNumber > (MEIXmpMAX_Axes)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    return 0;
}

long    createObjects(MPIControl            *control,
                      MPIAxis               *axis,
                      MPIMotion             *motion,
                      MPIControlType        *controlType,
                      MPIControlAddress     *controlAddress,
                      long                  axisNumber)
{

    long    returnValue;

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

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

    /* Create axis object*/
    *axis =
        mpiAxisCreate(*control,
                      AXIS_NUMBER);     /* Axis number */
    msgCHECK(mpiAxisValidate(*axis));

    /* Create motion object, append axis */
    *motion =
        mpiMotionCreate(*control,
                        MOTION_NUMBER,  /* Motion supervisor number */
                        *axis);         /* Axis object handle */
    msgCHECK(mpiMotionValidate(*motion));

    returnValue =
        mpiMotionAxisListSet(*motion,
                             1,
                             axis);
    msgCHECK(returnValue);

    return returnValue;
}

long    deleteObjects(MPIControl    *control,
                      MPIAxis       *axis,
                      MPIMotion     *motion)
{

    long returnValue;

    /* Object clean-up */
    returnValue = mpiMotionDelete(*motion);
    msgCHECK(returnValue);

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

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

    return returnValue;
}


motmap1.c -- Motion object and Motion Supervisor axis map configuration.
/* motMap1.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/motmap1.c 11    7/23/01 2:36p Kevinh $";
#endif

/*

:Motion object and Motion Supervisor axis map configuration.

The MPI supports Motion objects and Axis objects which reside in the
 host computer.  Several Motion objects can be created and associated
 with single or multiple Axis objects.  Additionally, several Motion
 objects can be configured to share one or more Axis objects.

The XMP controller has Motion Supervisors and Axes.  The controller's
 Motion Supervisors can be associated with a single axis or multiple axes.
 Additionally, several Motion Supervisors can be configured to share
 one or more axes.

When multiple axes are configured for a Motion Supervisor, the controller
 automatically manages the status and error conditions.  For example, if
 a Motion Supervisor is configured with two axes, and one of the axes faults
 with a position error limit, causing an Abort Event, the Motion Supervisor
 will generate Abort Event on the other axis.

Some care must be used with Motion Supervisor axis map configurations when
 axes are shared between Motion Supervisors.  Since the Error conditions
 are automatically proliferated across mapped axes, it is possible to create
 Motion Supervisor axis maps that generate Error conditions that cannot be
 cleared.  For example, if MS#0 is mapped to axes 0 and 1, and MS#1 is mapped
 to axis 0.  MS#1 will NOT be able to clear Error conditions.  Only MS#0 will
 be able to clear Error conditions on axes 0 and 1.

Motion Supervisor axis maps are set with any of the following methods:

1)  mpiMotionAction(...) with the MEIActionMAP or MPIActionRESET
2)  mpiMotionStart(...)
3)  mpiMotionModify(...)
4)  mpiMotionEventNotifySet(...)

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    motMap1Main

argMainRENAME(main, motMap1)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)
#define MS_COUNT        (4)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber[MS_COUNT] = { 0, 1, 2, 3,  };
MPIMotionType   motionType  = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber[0],   },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 10000.0,  20000.0,    },
    { 0.0,      0.0,        },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent  */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
};

/* Motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

long
    motionDoneWait(MPIMotion motion);

long
    motionIdle(MPIMotion    motion,
               MPIStatus    *status);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* Motion controller handle */
    MPIAxis     axisX;      /* X axis */
    MPIAxis     axisY;      /* Y axis */

    MPIMotion   motion;     /* Motion object for no axes */
    MPIMotion   motionX;    /* Motion object for axisX */
    MPIMotion   motionY;    /* Motion object for axisY */
    MPIMotion   motionXY;   /* Motion object for axisX and axisY */

    enum {
        Motion,
        MotionX,
        MotionY,
        MotionXY,
    };

    long    index;

    long    returnValue;    /* Return value from library */

    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) ||
        (axisNumber[0]   > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber[0] > (MEIXmpMAX_MSs - MS_COUNT)) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - MS_COUNT,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

    motionNumber[1] = motionNumber[0] + 1;
    motionNumber[2] = motionNumber[1] + 1;
    motionNumber[3] = motionNumber[2] + 1;

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

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

    /* Create X axis object using AXIS_X number on controller */
    axisX =
        mpiAxisCreate(control,
                      axisNumber[0]);       /* Axis Number */
    msgCHECK(mpiAxisValidate(axisX));

    /* Create Y axis object using AXIS_Y number on controller */
    axisY =
        mpiAxisCreate(control,
                      axisNumber[1]);       /* Axis Number */
    msgCHECK(mpiAxisValidate(axisY));

    /* Create Motion object with NO axes */
    motion =
        mpiMotionCreate(control,
                        motionNumber[Motion],   /* Motion supervisor number */
                        NULL);
    msgCHECK(mpiMotionValidate(motion));

    /* Create Motion object for axisX */
    motionX =
        mpiMotionCreate(control,
                        motionNumber[MotionX],      /* Motion supervisor number */
                        axisX);
    msgCHECK(mpiMotionValidate(motionX));

    /* Create Motion object for axisY */
    motionY =
        mpiMotionCreate(control,
                        motionNumber[MotionY],      /* Motion supervisor number */
                        axisY);
    msgCHECK(mpiMotionValidate(motionY));

    /* Motion object for axisX and axisY */
    motionXY =
        mpiMotionCreate(control,
                        motionNumber[MotionXY],     /* Motion supervisor number */
                        axisX);
    msgCHECK(mpiMotionValidate(motionXY));

    /* Append axisY to motionXY */
    returnValue =
        mpiMotionAxisAppend(motionXY,
                            axisY);
    msgCHECK(returnValue);

    /* Map X axis to Motion Supervisor */
    returnValue =
        mpiMotionAction(motionX,        /* Axis X, using MotionX */
                        (MPIAction)MEIActionMAP);   /* Map axis to Motion Supervisor */
    msgCHECK(returnValue);

    /* Map Y axis to Motion Supervisor */
    returnValue =
        mpiMotionAction(motionY,        /* Axis Y, using MotionY */
                        (MPIAction)MEIActionMAP);   /* Map axis to Motion Supervisor */
    msgCHECK(returnValue);

    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIMotionParams motionParams;

        /* Clear any error conditions on axisX */
        returnValue =
            mpiMotionAction(motionX,
                            (MPIAction)MPIActionRESET);
        msgCHECK(returnValue);

        index = 0;

        /* Move axisX to position #1 */

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        printf("\nMoving X axis...\n");

        returnValue =
            mpiMotionStart(motionX,
                           motionType,
                           &motionParams);

        if (returnValue != MPIMessageOK) {
            printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                   motionX,
                   motionType,
                   &motionParams,
                   returnValue,
                   mpiMessage(returnValue, NULL));
        }

        /* Wait for motion to complete */
        returnValue = motionDoneWait(motionX);
        msgCHECK(returnValue);

        /* Clear any error conditions on axisY */
        returnValue =
            mpiMotionAction(motionY,
                            MPIActionRESET);
        msgCHECK(returnValue);

        /* Move axisY to position #1 */

        printf("\nMoving Y axis...\n");

        returnValue =
            mpiMotionStart(motionY,
                           motionType,
                           &motionParams);

        if (returnValue != MPIMessageOK) {
            printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                   motionY,
                   motionType,
                   &motionParams,
                   returnValue,
                   mpiMessage(returnValue, NULL));
        }

        /* Wait for motion to complete */
        returnValue = motionDoneWait(motionY);
        msgCHECK(returnValue);

        /* Configure Motion Supervisor Map for X,Y */
        returnValue =
            mpiMotionAction(motionXY,       /* Axes X and Y, using MotionXY */
                            (MPIAction)MEIActionMAP);   /* Map axes to Motion Supervisor */
        msgCHECK(returnValue);

        /* Clear any error conditions on AxisX and AxisY */
        returnValue =
            mpiMotionAction(motionXY,
                            MPIActionRESET);
        msgCHECK(returnValue);

        index = 1;

        /* Move axisX and axisY to position #2 */

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams.sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams.trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams.velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        printf("\nMoving X and Y axes...\n");

        returnValue =
            mpiMotionStart(motionXY,
                           motionType,
                           &motionParams);

        if (returnValue != MPIMessageOK) {
            printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                   motionXY,
                   motionType,
                   &motionParams,
                   returnValue,
                   mpiMessage(returnValue, NULL));
        }

        /* Wait for motion to complete */
        returnValue = motionDoneWait(motionXY);
        msgCHECK(returnValue);

        /* Un-configure the controller's XY Motion Supervisor */
        returnValue =
            mpiMotionAction(motion,         /* Motion object has NO axes */
                            (MPIAction)MEIActionMAP);   /* Set a Motion Supervisor map of no axes */
        msgCHECK(returnValue);
    }

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

    returnValue = mpiMotionDelete(motionX);
    msgCHECK(returnValue);

    returnValue = mpiMotionDelete(motionY);
    msgCHECK(returnValue);

    returnValue = mpiMotionDelete(motionXY);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisY);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisX);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}

long
    motionDoneWait(MPIMotion motion)
{
    MPIStatus   status;

    long returnValue;

    long motionDone = FALSE;

    /* Poll status until motion done */
    while (motionDone == FALSE) {
        returnValue =
            mpiMotionStatus(motion,
                            &status,
                            NULL);
        msgCHECK(returnValue);

        switch (status.state) {
            case MPIStateIDLE: {
                motionDone = TRUE;

                returnValue =
                    motionIdle(motion,
                               &status);

                meiPlatformSleep(300);  /* msec */

                break;
            }
            case MPIStateERROR: {
                motionDone = TRUE;

                printf("Motion State Error!\n");

                break;
            }
            default: {
                break;
            }
        }
    }

    return (returnValue);
}

long
    motionIdle(MPIMotion    motion,
               MPIStatus    *status)
{
    long    returnValue;

    double          actual[AXIS_COUNT];
    double          command[AXIS_COUNT];
    MPITrajectory   trajectory[AXIS_COUNT];

    long    index;

    printf("MotionDone: status: state %d action %d eventMask 0x%x\n"
           "\tatTarget %d settled %d %s\n",
            status->state,
            status->action,
            status->eventMask,
            status->atTarget,
            status->settled,
            (status->settled == FALSE)
                    ? "=== NOT SETTLED ==="
                    : "");

    returnValue =
        mpiMotionPositionGet(motion,
                             actual,
                             command);
    msgCHECK(returnValue);

    returnValue =
        mpiMotionTrajectory(motion,
                            trajectory);
    msgCHECK(returnValue);

    /* Display axis positions */
    for (index = 0; index < AXIS_COUNT; index++) {
        printf("\taxis[%d]    position: command %11.3lf\tactual %11.3lf\n",
                index,
                command[index],
                actual[index]);
        printf("\t\ttrajectory: velocity %11.3lf\taccel  %11.3lf\tjerk %11.3lf\n",
                trajectory[index].velocity,
                trajectory[index].acceleration,
                trajectory[index].jerkPercent);
    }

    return (returnValue);
}


motmap2.c -- Motion object and Motion Supervisor Axis mapping with events
/* motMap2.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.
 */

/*

:Motion object and Motion Supervisor Axis mapping with events

This sample code performs the following operation:
 -Map axis 0 to motion object 'motion'.
 -Move axis 0 to position.
 -Wait for an event based upon motion done on axis 0
 -Move axis 1 to position
 -Wait for an event based upon motion done on axis 1
 -Map axis 0 and axis 1 to 'motion'
 -Coordinated move on axis 0 and axis 1 back to position (0,0).

Only one Motion Supervisor and Motion object is used and remapped after
 each move.

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 <windows.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    motMap2Main

argMainRENAME(main, motMap2)
#endif

#define AXIS_COUNT      (2)
#define MS_COUNT        (1)
#define MOTION_COUNT    (3)
#define COUNT           (100)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionSupNumber[MS_COUNT] = { 0,};

MPIMotionType   motionType  = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionSupNumber[0], },
    {   "-type",    ArgTypeLONG,    &motionType, },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 10000.0,},
    { 10000.0,},
    { 0.0,},
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent  */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
};

/* Motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
    {   &trajectory[2][0],  &position[2][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
    {   &trajectory[2][0],  &position[2][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
    {   &trajectory[2][0],  },
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;                /* Motion controller handle */
    MPIAxis         axisList[AXIS_COUNT];   /* Axis handle(s) */
    MPIMotion       motion;                 /* Motion object */

    MPIMotionParams motionParams;

    MPINotify       notify;                 /* event notification object */
    MPIEventMgr     eventMgr;               /* event manager handle */

    MPIEventMask    eventMask;
    MPIEventStatus  eventStatus;

    long        returnValue;    /* Return value from library */
    long        argIndex;
    Service     service;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    /* 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) ||
        (axisNumber[0]   > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionSupNumber[0] > (MEIXmpMAX_MSs - MS_COUNT)) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - MS_COUNT,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

    axisNumber[1] = axisNumber[0] + 1;

    /* Create axis object using axisNumber on controller */
    axisList[0] =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axisList[0]));

    /* Create axis object using axisNumber on controller  */
    axisList[1] =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axisList[1]));

    /* Create motion object motion for axisList[0] */
    motion =
        mpiMotionCreate(control,
                        0,                  /* Motion supervisor number */
                        axisList[0]);
    msgCHECK(mpiMotionValidate(motion));

    /* Create event notification object for events from all sources */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    meiEventMaskALL(eventMask);
    notify =
        mpiNotifyCreate(eventMask,
                        NULL);
    msgCHECK(mpiNotifyValidate(notify));

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

    /* Flush any existing events */
    returnValue =
        mpiEventMgrFlush(eventMgr);
    msgCHECK(returnValue);

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

    /* Request notification of events from motion */
    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

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

    /* Clear any error conditions on motion */
    returnValue =
        mpiMotionAction(motion,
                        MPIActionRESET);
    msgCHECK(returnValue);

    /* Move axis 0 */
    switch (motionType) {
        case MPIMotionTypeS_CURVE: {
            motionParams.sCurve = sCurve[0];
            break;
        }
        case MPIMotionTypeTRAPEZOIDAL: {
            motionParams.trapezoidal = trapezoidal[0];
            break;
        }
        case MPIMotionTypeVELOCITY: {
            motionParams.velocity = velocity[0];
            break;
        }
        default: {
            meiASSERT(FALSE);
            break;
        }
    }

    printf("\nMoving axis 0...\n");

    returnValue =
        mpiMotionStart(motion,
                       motionType,
                       &motionParams);

    if (returnValue != MPIMessageOK) {
        printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
               motion,
               motionType,
               &motionParams,
               returnValue,
               mpiMessage(returnValue, NULL));
    }

    /* Wait for motion to complete */
    while (returnValue == MPIMessageOK) {

        /* Wait for axis and motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);

        fprintf(stderr,
                "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                notify,
                &eventStatus,
                MPIWaitFOREVER,
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            printf("Finished axis 0 move.\n");
            break;
        }
        else {
            continue;
        }
    }

    /* Map axisList[1] to motion object */
    returnValue =
        mpiMotionAxisListSet(motion,
                             1,
                             &axisList[1]);
    msgCHECK(returnValue);

    /* Request notification of events from motion */
    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

    /* Move axis 1 */
    switch (motionType) {
        case MPIMotionTypeS_CURVE: {
            motionParams.sCurve = sCurve[1];
            break;
        }
        case MPIMotionTypeTRAPEZOIDAL: {
            motionParams.trapezoidal = trapezoidal[1];
            break;
        }
        case MPIMotionTypeVELOCITY: {
            motionParams.velocity = velocity[1];
            break;
        }
        default: {
            meiASSERT(FALSE);
            break;
        }
    }

    printf("\nMoving Axis 1...\n");

    returnValue =
        mpiMotionStart(motion,
                       motionType,
                       &motionParams);

    if (returnValue != MPIMessageOK) {
        printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
               motion,
               motionType,
               &motionParams,
               returnValue,
               mpiMessage(returnValue, NULL));
    }

    /* Wait for motion to complete */
    while (returnValue == MPIMessageOK) {

        /* Wait for axis and motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);

        fprintf(stderr,
                "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                notify,
                &eventStatus,
                MPIWaitFOREVER,
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            printf("Finished axis 1 move.\n");
            break;
        }
        else {
            continue;
        }
    }

    /* Map motion for axis 0 and axis 1 */
    returnValue =
        mpiMotionAxisListSet(motion,
                             2,
                             axisList);
    msgCHECK(returnValue);

    /* Request notification of events from motion */
    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

    switch (motionType) {
        case MPIMotionTypeS_CURVE: {
            motionParams.sCurve = sCurve[2];
            break;
        }
        case MPIMotionTypeTRAPEZOIDAL: {
            motionParams.trapezoidal = trapezoidal[2];
            break;
        }
        case MPIMotionTypeVELOCITY: {
            motionParams.velocity = velocity[2];
            break;
        }
        default: {
            meiASSERT(FALSE);
            break;
        }
    }

    printf("\nMoving Axes 0 and 1...\n");

    returnValue =
        mpiMotionStart(motion,
                       motionType,
                       &motionParams);

    if (returnValue != MPIMessageOK) {
        printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
               motion,
               motionType,
               &motionParams,
               returnValue,
               mpiMessage(returnValue, NULL));
    }

    /* Wait for motion to complete */
    while (returnValue == MPIMessageOK) {

        /* Wait for axis and motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);

        fprintf(stderr,
                "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                notify,
                &eventStatus,
                MPIWaitFOREVER,
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            printf("Finished axis 0 and 1 move.\n");
            break;
        }
        else {
            continue;
        }
    }

    /* Delete Objects */
    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisList[0]);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisList[1]);
    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);
}


motmod1.c -- Point to Point trapezoidal profile motion with end point modification.
/* motMod1.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/motmod1.c 4     7/23/01 2:36p Kevinh $";
#endif

/*

:Point to Point trapezoidal profile motion with end point modification.

This is a simple program to demonstrate how to start a trapezoidal profile
 motion on a single axis.  During the execution of the motion, the target
 position (end point), velocity, accel, decel are modified.  The controller
 automatically re-calculates the motion profile, using the modified
 trajectory parameters.

The mpiMotionModify(...) function modifies a presently executing motion
 profile.  If mpiMotionModify(...) is called when no motion is executing,
 the error code, MPIMotionMessageIDLE will be returned, and no motion
 will be commanded.  This error code let's the application know that there
 was no motion to be modified.

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    motMod1Main

argMainRENAME(main, motMod1)
#endif

#define MOTION_NUMBER       (0)
#define AXIS_NUMBER         (0)

/* Motion Start Parameters */
#define TARGET_POSITION     (10000.0)
#define VEL                 (10000.0)
#define ACCEL               (100000.0)
#define DECEL               (100000.0)

/* Motion Modify Parameters */
#define MODIFY_POSITION     (-1000.0)   /* new target position */
#define MODIFY_VEL          (5000.0)    /* new velocity */
#define MODIFY_DECEL        (50000.0)   /* new deceleration */

#define WAIT_TIME           (500)       /* delay to modify move, (msec) */

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

    long    returnValue;

    MPIMotionParams params;     /* motion parameters */
    MPITrajectory   trajectory; /* motion trajectory */
    double          position;   /* final target position */
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

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

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n",
                           argv[0],
                           ArgUSAGE);
        exit(MPIMessagePARAM_INVALID);
    }

    /* Create motion controller object*/
    control =
        mpiControlCreate(MPIControlTypeDEFAULT,
                         NULL);
    msgCHECK(mpiControlValidate(control));

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

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

    /* Create motion object, append axis */
    motion =
        mpiMotionCreate(control,
                        MOTION_NUMBER,  /* motion supervisor number */
                        axis);          /* axis object handle */
    msgCHECK(mpiMotionValidate(motion));

    /* Set up motion parameters */
    trajectory.velocity     = VEL;          /* counts per sec */
    trajectory.acceleration = ACCEL;        /* counts per sec * sec */
    trajectory.deceleration = DECEL;

    position = TARGET_POSITION;     /* target position (counts) */

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

    printf("\nMotionStart...\n");

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);

    meiPlatformSleep(WAIT_TIME);    /* delay */

    /* Set up new motion parameters */
    trajectory.velocity     = MODIFY_VEL;       /* counts per sec */
    trajectory.acceleration = ACCEL;            /* use same acceleration */
    trajectory.deceleration = MODIFY_DECEL;     /* counts per sec * sec */

    /* New target position (counts) */
    position = MODIFY_POSITION;

    printf("\nMotionModify...\n");

    /* Modify the executing motion profile */
    returnValue =
        mpiMotionModify(motion,
                        MPIMotionTypeTRAPEZOIDAL,
                        &params);
    msgCHECK(returnValue);

    /* object clean-up */
    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

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

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

    return ((int)returnValue);
}


motorio1.c -- Configure Transceiver as input or output and toggle.
/* motorIo1.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/motorio1.c 8     7/23/01 2:36p Kevinh $";
#endif

/*

:Configure Transceiver as input or output and toggle.

This sample application configures a single transceiver, on one motor,
for input or output.  If the transceiver is configured for output, the
bit state is configured by changing the user defined XCVR_STATE value.
As a tutorial purpose TRANSCEIVER_ID and TRANSCEIVER_MASK are defined
using MPI definitions.  The MPI definitions must have the same ending
transceiver letter!!(i.e. XCVR_A, XCVR_B, or XCVR_C)

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    motorIo1Main

argMainRENAME(main, motorIo1)
#endif

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

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* User Settings */
#define IO_CONFIG           (MEIMotorTransceiverConfigOUTPUT) /* INPUT or OUTPUT  */
#define TRANSCEIVER_ID      (MEIMotorTransceiverIdA)  /* A, B, or C               */
#define TRANSCEIVER_MASK    (MEIMotorTransceiverMaskA) /* same as above (A,B,or C) */

#define INVERT_BIT          (FALSE)
#define XCVR_STATE          (TRUE)  /* State of output transceiver */

#define WAIT_TIME           (10)    /* Units are msec */
int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;

    MPIMotor        motor;
    MEIMotorConfig  motorConfigXmp;  /* Contains transceiver configuration */
    MPIMotorIo      io;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    returnValue;

    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 >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Get handle to motor object */
    motor =
        mpiMotorCreate(control,
                       motorNumber);
    returnValue = mpiMotorValidate(motor);
    msgCHECK(returnValue);

    /* Configure selected transceiver */
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    motorConfigXmp.Transceiver[TRANSCEIVER_ID].Config = IO_CONFIG;
    motorConfigXmp.Transceiver[TRANSCEIVER_ID].Invert = INVERT_BIT;

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

    /*
       Write the output word if the selected transceiver is configured
       for output.
    */
    if (IO_CONFIG == MEIMotorTransceiverConfigOUTPUT) {
        returnValue =
            mpiMotorIoGet(motor,
                          &io);
        msgCHECK(returnValue);

        if (io.output & TRANSCEIVER_MASK) {
            io.output = (io.output & ~TRANSCEIVER_MASK);
        } else {
            io.output = (io.output | TRANSCEIVER_MASK);
        }

        returnValue =
            mpiMotorIoSet(motor,
                          &io);
        msgCHECK(returnValue);
    }

    /* Wait 10ms before reading new configuration */
    meiPlatformSleep(WAIT_TIME);

    /* Read and display the current transceiver IO bit */
    returnValue =
        mpiMotorIoGet(motor,
                      &io);
    msgCHECK(returnValue);

    printf("\n%s: %d\n",
           (IO_CONFIG == MEIMotorTransceiverConfigINPUT)
                ? "Input bit"
                : "Output bit",
           (IO_CONFIG == MEIMotorTransceiverConfigINPUT)
                ? (io.input & TRANSCEIVER_MASK)
                : (io.output & TRANSCEIVER_MASK));

    /* Delete the MOTOR handle */
    returnValue = mpiMotorDelete(motor);
    msgCHECK(returnValue);

    /* Delete the CONTROL handle */
    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return ((int)returnValue);
}


notify1.c -- Create notify object and wait for events.
/* notify1.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/notify1.c 20    7/23/01 2:36p Kevinh $";
#endif

/*

:Create notify object and wait for events.

Create a thread that uses a notify object to wait for user-defined events
 passed to the notify object from the main thread.

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 <string.h>

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

#if defined(ARG_MAIN_RENAME)
#define main    notify1Main

argMainRENAME(main, notify1)
#endif

/* Command line arguments and defaults */

Arg argList[] = {
    {   NULL,       ArgTypeINVALID, NULL,   }
};

Static  long    NotifyWaitAwake;

Static long
    notifyWait(MPINotify notify);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;        /* Motion controller handle */
    MPINotify   notify;         /* Event notification object */

    MPIEventMask    eventMask;

    long    returnValue;    /* Return value from library */

    long    eventDone;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

    Thread          thread;
    ThreadStatus    status;

    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) {
        meiPlatformConsole("usage: %s %s\n",
                            argv[0],
                            ArgUSAGE);
        exit(MPIMessageARG_INVALID);
    }

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

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

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

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

    if (returnValue == MPIMessageOK) {
        thread = threadCreate();

        returnValue = threadValidate(thread);
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            threadStart(thread,
                        (THREAD_FUNCTION)notifyWait,
                        notify);
    }

    eventDone = FALSE;

    while ((returnValue == MPIMessageOK) &&
           (eventDone == FALSE)) {
        char    buffer[128];
        long    index;
        long    haveEventNumber;

        /* Wait for notifyWait() to call mpiNotifyEventWait() */
        while (NotifyWaitAwake != FALSE) {
            meiPlatformSleep(1);
        }

        /* Make sure notifyWait() thread is still executing */
        returnValue =
            threadStatus(thread,
                         &status);

        if (returnValue != MPIMessageOK) {
            break;
        }

        if (status.active == FALSE) {
            break;
        }

        meiPlatformConsole("Enter an event number, or ESC to exit ...\n");

        memset(buffer, 0, sizeof(buffer));
        index = 0;

        haveEventNumber = FALSE;
        while (haveEventNumber == FALSE) {
            MPIEventStatus  eventStatus;

            long    key;
            long    eventNumber = 0;

            key = meiPlatformKey(MPIWaitFOREVER);

            if (key <= 0) {
                meiPlatformKey(MPIWaitFOREVER);
                continue;
            }

            switch (key) {
                case 0x1b: {    /* ESC */
                    eventNumber = key;
                    haveEventNumber = TRUE;
                    eventDone = TRUE;
                    break;
                }
                case '\r':
                case '\n': {
                    meiPlatformConsole("\n");

                    eventNumber = meiPlatformAtol(buffer);

                    haveEventNumber = TRUE;
                    break;
                }
                case '\b': {
                    if (index > 0) {
                        meiPlatformConsole("\b \b");
                        buffer[--index] = '\0';
                    }
                    break;
                }
                case '-': {
                    if (index == 0) {
                        buffer[index++] = (char)key;
                        meiPlatformConsole("%c", key);
                    }
                    break;
                }
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9': {
                    buffer[index++] = (char)key;
                    meiPlatformConsole("%c", key);
                    break;
                }
                default: {
                    break;
                }
            }

            if (haveEventNumber != FALSE) {
                NotifyWaitAwake = TRUE;

                eventStatus.type    = MPIEventTypeEXTERNAL;
                eventStatus.source  = NULL;
                eventStatus.info[0] = eventNumber;

                returnValue =
                    mpiNotifyEventWake(notify,
                                       &eventStatus);
            }
        }
    }

    if (thread != NULL) {
        while (returnValue == MPIMessageOK) {
            returnValue =
                threadStatus(thread,
                             &status);
            msgCHECK(returnValue);

            if (status.active == FALSE) {
                returnValue = status.returnValue;
                break;
            }

            meiPlatformSleep(1);
        }

        returnValue = threadDelete(thread);
        msgCHECK(returnValue);
    }

    fprintf(stderr,
            "%s exiting: returnValue 0x%x: %s\n",
            argv[0],
            returnValue,
            mpiMessage(returnValue, NULL));

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

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

    return ((int)returnValue);
}

Static long
    notifyWait(MPINotify notify)
{
    long    returnValue;

    MPIWait timeout;
    long    eventDone;

    /* Validate the notify object and its handle */
    returnValue = mpiNotifyValidate(notify);

    timeout = MPIWaitFOREVER;

    eventDone = FALSE;

    while ((returnValue == MPIMessageOK) &&
           (eventDone == FALSE)) {
        MPIEventStatus  eventStatus;

        NotifyWaitAwake = FALSE;

        /* Wait for notify event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               timeout);

        meiPlatformConsole("mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x: %s\n",
                            notify,
                            &eventStatus,
                            timeout,
                            returnValue,
                            mpiMessage(returnValue, NULL));

        switch (returnValue) {
            case MPIMessageOK: {
                meiPlatformConsole("\teventStatus: type %d number %d\n",
                                    eventStatus.type,
                                    eventStatus.info[0]);

                if (eventStatus.info[0] == 0x1b) {
                    eventDone = TRUE;
                }
                break;
            }
            case MPIMessageTIMEOUT: {
                meiPlatformConsole("\tTIMEOUT\n");
                break;
            }
            default: {
                break;
            }
        }
    }

    meiPlatformConsole("notifyWait(0x%x) returning 0x%x: %s\n",
                        notify,
                        returnValue,
                        mpiMessage(returnValue, NULL));

    return (returnValue);
}


path1.c -- Two-axis path motion, around a rectangle with rounded corners.
/* path1.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.
 */

/*

:Two-axis path motion, around a rectangle with rounded corners.

This sample demonstrates how to create a two-axis path motion.

After the Path object has been created, Line and Arc elements are
 appended to the path.  After the path elements have been appended,
 the MotionParams are generated, and the motion is started using
 mpiMotionStart(...).

When the motion has started, the program will wait for a MOTION_DONE event
 to be distributed by the event manager in a separate service thread.

A summary of Path object structures and methods:

    MPIPath -- path object handle
    MPIPathConfig{} -- path config structure
    MPIPathArc{} -- arc from start, angle and radius
    MPIPathLine{} -- point in space

    mpiPathCreate() -- create a path
    mpiPathDelete() -- delete a path
    mpiPathValidate() -- validate a path
    mpiPathConfigGet() -- get the current path configuration
    mpiPathConfigSet() -- set the path configuration
    mpiPathAppend() -- add a path element to the path
    mpiPathMotionParamsGenerate() -- generate the motion parameters

Note:  When multiple axes are associated with a motion supervisor, the
 controller automatically combines the individual axis and motor status
 into the motion status.  Thus, if a Stop, E-Stop or Abort action occurs
 on one axis, the event will be propogated automatically to the other axes.

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 <math.h>

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

#include "apputil.h"

#define AXIS_COUNT          (2)

/* Set the vector values for Vel, Accel, Decel */
#define VELOCITY            (5000.0)
#define ACCEL               (50000.0)
#define DECEL               (50000.0)

/* The practical range for the time slice parameter is from
    10 msec (0.01) to 100 msec (0.1).  The time slice determines
    the spacing of points for the internal algorithm interpolation */
#define TIME_SLICE          (0.050) /* seconds */

/* There must be this many points in the buffer, or the motion
    will E_STOP */
#define EMPTY_COUNT         (5)

/* Ensure that the E_STOP will finish before the points are empty */
#define E_STOP_RATE         (TIME_SLICE * EMPTY_COUNT)

/* Only BSPLINE and BLSPLINE2 are supported for Path motion */
#define MOTION_TYPE         MPIMotionTypeBSPLINE

#define TIMEOUT             (10000) /* ms to wait for MOTION_DONE */

#if defined(ARG_MAIN_RENAME)
#define main    path1Main

argMainRENAME(main, path1)
#endif

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   NULL,       ArgTypeINVALID, NULL,   }
};

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

    MPIMotionConfig     motionConfig;
    MPIPath             path;
    MPIPathConfig       pathConfig;
    MPIPathElement      element;
    MPIMotionParams     motionParams;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIEventMask        eventMask;

    Service             service;        /* service handle */

    long                returnValue;    /* return value from library */
    long                argIndex;
    double              x_start;
    double              y_start;

    /* 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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create axis objects */
    axis[0] =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axis[0]));

    axis[1] =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axis[1]));

    /* Create motion supervisor object using MS number 0 */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Create 2-axis motion coordinate system */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

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

    /* Request notification of all events from motion */
    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);  /* default sleep (msec) */
    meiASSERT(service != NULL);

    /* Read current motion supervisor configuration */
    returnValue =
        mpiMotionConfigGet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    /* Set new E_STOP deceleration rates */
    motionConfig.decelTime.eStop = E_STOP_RATE;

    returnValue =
        mpiMotionConfigSet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    returnValue = mpiAxisCommandPositionGet(axis[0], &x_start);
    msgCHECK(returnValue);
    returnValue = mpiAxisCommandPositionGet(axis[1], &y_start);
    msgCHECK(returnValue);

    path = mpiPathCreate();
    msgCHECK(mpiPathValidate(path));

    returnValue = mpiPathConfigGet(path,
                                    &pathConfig,
                                    NULL);
    msgCHECK(returnValue);

    pathConfig.dimension = AXIS_COUNT;
    MPIPathPointX(pathConfig.start) = x_start;
    MPIPathPointY(pathConfig.start) = y_start;
    pathConfig.velocity = VELOCITY;
    pathConfig.acceleration = ACCEL;
    pathConfig.deceleration = DECEL;
    pathConfig.interpolation = MOTION_TYPE;
    pathConfig.timeSlice = TIME_SLICE;

    returnValue = mpiPathConfigSet(path,
                                    &pathConfig,
                                    NULL);
    msgCHECK(returnValue);

    /* Start appending elements to the path */

    element.type = MPIPathElementTypeLINE;

    /* Set blending to TRUE if the corners of the path
        should be rounded.   Set to FALSE if the corners
        should be sharp. The motion will stop at corners when
        blending is FALSE */
    element.blending = TRUE;
    MPIPathPointX(element.params.line.point) = 1800.0;
    MPIPathPointY(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC;
    element.params.arc.angle.start = 270.0;
    /* Included angle is CCW when positive, CW when negative */
    element.params.arc.angle.included = 90.0;
    element.params.arc.radius = 200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = 2000.0;
    MPIPathPointY(element.params.line.point) = 1800.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC;
    element.params.arc.angle.start = 0.0;
    element.params.arc.angle.included = 90.0;
    element.params.arc.radius = 200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = -1800.0;
    MPIPathPointY(element.params.line.point) = 2000.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC;
    element.params.arc.angle.start = 90.0;
    element.params.arc.angle.included = 90.0;
    element.params.arc.radius = 200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = -2000.0;
    MPIPathPointY(element.params.line.point) = 200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC;
    element.params.arc.angle.start = 180.0;
    element.params.arc.angle.included = 90.0;
    element.params.arc.radius = 200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = 0.0;
    MPIPathPointY(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);
    /* Finished appending elements to the path */

    /* Generate motion parameters from the path object */
    returnValue = mpiPathMotionParamsGenerate(path,
                                      &motionParams);
    msgCHECK(returnValue);

    /* Keep the points in memory, in case we need to backup on path */
    motionParams.bspline.point.retain = TRUE;

    /* Specify the minimum number of points required in
        the XMP buffer -- if there are less, motion will E_STOP */
    motionParams.bspline.point.emptyCount = EMPTY_COUNT;

    /* This motion will not be appended */
    motionParams.bspline.point.final = TRUE;

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MOTION_TYPE,
                       &motionParams);
    fprintf(stderr,
            "mpiMotionStart returns 0x%x: %s\n",
            returnValue,
            mpiMessage(returnValue, NULL));

    /* Collect motion events */
    while (returnValue == MPIMessageOK) {
        MPIEventStatus  eventStatus;

        /* Wait for event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               TIMEOUT);
        msgCHECK(returnValue);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            printf("Motion Done\n");
            break;
        }
        else {
            fprintf(stderr,
                "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                notify,
                &eventStatus,
                MPIWaitFOREVER,
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        }
    }

    fprintf(stderr,
            "%s exiting: returnValue 0x%x: %s\n",
            argv[0],
            returnValue,
            mpiMessage(returnValue, NULL));

    returnValue = mpiPathDelete(path);
    msgCHECK(returnValue);

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

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

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

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

    returnValue = mpiAxisDelete(axis[0]);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axis[1]);
    msgCHECK(returnValue);

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


path3d1.c -- Three-axis path motion with velocities, acceleration and timeSlices
/* path1_3D.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.
 */

/*

:Three-axis path motion with velocities, acceleration and timeSlices
defined for each element.

This sample demonstrates how to create a three-axis path motion together wth
different velocities, aceleration and timeSlices for different elements.

The code draws 2 rectangles. The first, larger rectangle has different velocities
and timeSlices, and different z elevations. The second, smaller one is simply
in the xy plane (z = 0) and has one corner with the direction of the arc
value = -1 which means that the motion will be around 270 degrees and not 90.
Even though the second rectangle is 2D, it must have values for z as it is inadvisable
to mix 2D and 3D paths.

After the Path object has been created, Line and Arc elements are
 appended to the path.  After the path elements have been appended,
 the MotionParams are generated, and the motion is started using
 mpiMotionStart(...).

When the motion has started, the program will wait for a MOTION_DONE event
 to be distributed by the event manager in a separate service thread.

A summary of Path object structures and methods:

    MPIPath -- path object handle
    MPIPathParams{} -- path Params structure
    MPIPathArc{} -- arc from start, angle and radius
    MPIPathLine{} -- point in space

    mpiPathCreate() -- create a path
    mpiPathDelete() -- delete a path
    mpiPathValidate() -- validate a path
    mpiPathParamsGet() -- get the current path parameters
    mpiPathParamsSet() -- set the path parameters
    mpiPathAppend() -- add a path element to the path
    mpiPathMotionParamsGenerate() -- generate the motion parameters

Note:  When multiple axes are associated with a motion supervisor, the
 controller automatically combines the individual axis and motor status
 into the motion status.  Thus, if a Stop, E-Stop or Abort action occurs
 on one axis, the event will be propogated automatically to the other axes.

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 <math.h>

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

#include "apputil.h"

#define AXIS_COUNT          (3)

/* Set the vector values for Vel, ACCEL, Decel */
#define VELOCITY            (5000.0)
#define ACCEL               (50000.0)
#define DECEL               (50000.0)

/* The practical range for the time slice parameter is from
    10 msec (0.01) to 100 msec (0.1).  The time slice determines
    the spacing of points for the internal algorithm interpolation */
#define TIME_SLICE          (0.050) /* seconds */

/* There must be this many points in the buffer, or the motion
    will E_STOP */
#define EMPTY_COUNT         (5)

/* Ensure that the E_STOP will finish before the points are empty */
#define E_STOP_RATE         (TIME_SLICE * EMPTY_COUNT)

/* Only BSPLINE and BLSPLINE2 are supported for Path motion */
#define MOTION_TYPE         MPIMotionTypeBSPLINE

#define TIMEOUT             (100000) /* ms to wait for MOTION_DONE */

#if defined(ARG_MAIN_RENAME)
#define main    path1Main

argMainRENAME(main, path1)
#endif

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, 2};
long            motionNumber    = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   NULL,       ArgTypeINVALID, NULL,   }
};

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

    MPIMotionConfig     motionConfig;
    MPIPath             path;
    MPIPathParams       pathParams;
    MPIPathElement      element;
    MPIMotionParams     motionParams;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIEventMask        eventMask;

    Service             service;        /* service handle */

    long                returnValue;    /* return value from library */
    long                argIndex;
    double              x_start;
    double              y_start;
    double              z_start;

    /* 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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    axisNumber[1] = axisNumber[0] + 1;
    axisNumber[2] = axisNumber[1] + 1;

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

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

    /* Create axis objects */
    axis[0] =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axis[0]));

    axis[1] =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axis[1]));

    axis[2] =
        mpiAxisCreate(control,
                      axisNumber[2]);
    msgCHECK(mpiAxisValidate(axis[2]));

    /* Create motion supervisor object using MS number 0 */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Create 2-axis motion coordinate system */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

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

    /* Request notification of all events from motion */
    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);  /* default sleep (msec) */
    meiASSERT(service != NULL);

    /* Read current motion supervisor Configurationuration */
    returnValue =
        mpiMotionConfigGet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    /* Set new E_STOP deceleration rates */
    motionConfig.decelTime.eStop = E_STOP_RATE;

    returnValue =
        mpiMotionConfigSet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    returnValue = mpiAxisCommandPositionGet(axis[0], &x_start);
    msgCHECK(returnValue);
    returnValue = mpiAxisCommandPositionGet(axis[1], &y_start);
    msgCHECK(returnValue);
    returnValue = mpiAxisCommandPositionGet(axis[2], &z_start);
    msgCHECK(returnValue);

    path = mpiPathCreate();
    msgCHECK(mpiPathValidate(path));

    returnValue = mpiPathParamsGet(path,
                                    &pathParams,
                                    NULL);
    msgCHECK(returnValue);

    pathParams.dimension = AXIS_COUNT;
    MPIPathPointX(pathParams.start) = x_start;
    MPIPathPointY(pathParams.start) = y_start;
    MPIPathPointZ(pathParams.start) = z_start;
    pathParams.velocity = VELOCITY;
    pathParams.acceleration = ACCEL;
    pathParams.deceleration = DECEL;
    pathParams.interpolation = MOTION_TYPE;
    pathParams.timeSlice = TIME_SLICE;

    returnValue = mpiPathParamsSet(path,
                                    &pathParams,
                                    NULL);
    msgCHECK(returnValue);

    /* Start appending elements to the path */

    /* In this element, the path parameters will be used */
    element.type = MPIPathElementTypeLINE ;

    /*
        Set blending to TRUE if the corners of the path
        should be rounded.   Set to FALSE if the corners
        should be sharp. The motion will stop at corners when
        blending is FALSE
    */
    element.blending = TRUE;
    MPIPathPointX(element.params.line.point) = 1800.0;
    MPIPathPointY(element.params.line.point) = 0.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    /*
        The "| MPIPathElementAttrMaskVELOCITY" in the next line states that
        the element has it's own velocity.
    */
    element.type = MPIPathElementTypeARC_END_POINT | MPIPathElementAttrMaskVELOCITY;

    MPIPathPointX(element.params.arcEndPoint.center) = 1800;
    MPIPathPointY(element.params.arcEndPoint.center) = 200;
    MPIPathPointZ(element.params.arcEndPoint.center) = 50;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = 2000;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = 200;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 100;

    element.attributes.velocity = 10 * VELOCITY;

    /*
        The 'direction' is used to describe whether the motion should be around the large,
        or small angle between the start and stop points. direction = 1 means that
        the motion will be through less than 180 degrees, while direction = -1 means that
        the motion will be through more than 180 degrees.
    */
    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    /*
        The "| MPIPathElementAttrMaskTIMESLICE" in the next line states that
        the element has it's own velocity.
    */
    element.type = MPIPathElementTypeLINE | MPIPathElementAttrMaskTIMESLICE;
    MPIPathPointX(element.params.line.point) = 2000.0;
    MPIPathPointY(element.params.line.point) = 1800.0;
    MPIPathPointZ(element.params.line.point) = 100.0;

    element.attributes.timeSlice = 0.1 * TIME_SLICE;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    /* In this element, the path parameters will be used */
    element.type = MPIPathElementTypeARC_END_POINT;
    MPIPathPointX(element.params.arcEndPoint.center) = 1800;
    MPIPathPointY(element.params.arcEndPoint.center) = 1800;
    MPIPathPointZ(element.params.arcEndPoint.center) = 50;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = 1800;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = 2000;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 0;

    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE ;
    MPIPathPointX(element.params.line.point) = -1800.0;
    MPIPathPointY(element.params.line.point) = 2000.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC_END_POINT;
    MPIPathPointX(element.params.arcEndPoint.center) = -1800;
    MPIPathPointY(element.params.arcEndPoint.center) = 1800;
    MPIPathPointZ(element.params.arcEndPoint.center) = -100;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = -2000;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = 1800;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = -200;

    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = -2000.0;
    MPIPathPointY(element.params.line.point) = 200.0;
    MPIPathPointZ(element.params.line.point) = -200.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC_END_POINT;
    MPIPathPointX(element.params.arcEndPoint.center) = -1800;
    MPIPathPointY(element.params.arcEndPoint.center) = 200;
    MPIPathPointZ(element.params.arcEndPoint.center) = -100;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = -1800;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = 0;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 0;

    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = 0.0;
    MPIPathPointY(element.params.line.point) = 0.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE ;
    MPIPathPointX(element.params.line.point) = 0.0;
    MPIPathPointY(element.params.line.point) = -1800.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);

    element.type = MPIPathElementTypeARC_END_POINT ;
    MPIPathPointX(element.params.arcEndPoint.center) = -200;
    MPIPathPointY(element.params.arcEndPoint.center) = -1800;
    MPIPathPointZ(element.params.arcEndPoint.center) = 0;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = -200;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = -2000;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 0;

    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    msgCHECK(returnValue);
        element.type = MPIPathElementTypeLINE ;
    MPIPathPointX(element.params.line.point) = -1800.0;
    MPIPathPointY(element.params.line.point) = -2000.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC_END_POINT ;
    MPIPathPointX(element.params.arcEndPoint.center) = -1800;
    MPIPathPointY(element.params.arcEndPoint.center) = -1800;
    MPIPathPointZ(element.params.arcEndPoint.center) = 0;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = -2000;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = -1800;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 0;

    element.params.arcEndPoint.direction = -1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE ;
    MPIPathPointX(element.params.line.point) = -2000.0;
    MPIPathPointY(element.params.line.point) = -200.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeARC_END_POINT;
    MPIPathPointX(element.params.arcEndPoint.center) = -1800;
    MPIPathPointY(element.params.arcEndPoint.center) = -200;
    MPIPathPointZ(element.params.arcEndPoint.center) = 0;

    MPIPathPointX(element.params.arcEndPoint.endPoint) = -1800;
    MPIPathPointY(element.params.arcEndPoint.endPoint) = 0;
    MPIPathPointZ(element.params.arcEndPoint.endPoint) = 0;

    element.params.arcEndPoint.direction = 1;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    element.type = MPIPathElementTypeLINE;
    MPIPathPointX(element.params.line.point) = 0.0;
    MPIPathPointY(element.params.line.point) = 0.0;
    MPIPathPointZ(element.params.line.point) = 0.0;

    returnValue = mpiPathAppend(path,
                                &element);
    msgCHECK(returnValue);

    /* Finished appending elements to the path */

    /* Generate motion parameters from the path object */
    returnValue = mpiPathMotionParamsGenerate(path,
                                      &motionParams);
    msgCHECK(returnValue);

    /* Keep the points in memory, in case we need to backup on path */
    motionParams.bspline.point.retain = TRUE;

    /* Specify the minimum number of points required in
        the XMP buffer -- if there are less, motion will E_STOP */
    motionParams.bspline.point.emptyCount = EMPTY_COUNT;

    /* This motion will not be appended */
    motionParams.bspline.point.final = TRUE;

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MOTION_TYPE,
                       &motionParams);
    fprintf(stderr,
            "mpiMotionStart returns 0x%x: %s\n",
            returnValue,
            mpiMessage(returnValue, NULL));

    /* Collect motion events */
    while (returnValue == MPIMessageOK) {
        MPIEventStatus  eventStatus;

        /* Wait for event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               TIMEOUT);
        msgCHECK(returnValue);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            printf("Motion Done\n");
            break;
        }
        else {
            fprintf(stderr,
                "mpiNotifyEventWait(0x%x, 0x%x, %d) returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                notify,
                &eventStatus,
                MPIWaitFOREVER,
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        }
    }

    fprintf(stderr,
            "%s exiting: returnValue 0x%x: %s\n",
            argv[0],
            returnValue,
            mpiMessage(returnValue, NULL));

    returnValue = mpiPathDelete(path);
    msgCHECK(returnValue);

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

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

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

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

    returnValue = mpiAxisDelete(axis[0]);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axis[1]);
    msgCHECK(returnValue);

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


PT1.c -- Simple motion path generation, specified by position/time points.
/* pt1.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/pt1.c 9     7/23/01 2:36p Kevinh $";
#endif

/*

:Simple motion path generation, specified by position/time points.

This sample code demonstrates the motion type, MPIMotionTypePT.  A simple
 trapezoidal velocity profile points list is created, and downloaded to
 the controller.  The time delta between each position is constant and
 the positions are spaced to generate an acceleration, constant velocity,
 and deceleration profile to the final position.

Several motion parameters must be initialized for the PT motion type:

 params.pt.pointCount - Specifies the number of points (position/time).

 params.pt.position - Pointer to a position[...] array.  There is one
    position value per point, per axis.  The length of the array must be
    equal to pointCount multiplied by the number of axes.  The positions
    are interleaved in the array by the axis index.

    For example, a three axis system would have:
        position[0] = position for axis 0
        position[1] = position for axis 1
        position[2] = position for axis 2
        position[3] = position for axis 0
        position[4] = position for axis 1
        etc.

 params.pt.time - Pointer to a time[...] array.  There is one time value
    per point.  The time specifies the number of seconds between the specified
    position, and the next position (point).  The length of the time array must
    be equal to the pointCount.

 params.pt.point.retain - Specifies whether the MPI and XMP should buffer the
    points after they have executed.  If retain = 0, the buffer will destroy
    the points after they have executed.  If retain = 1, the buffer will keep the
    points after they have executed.  This parameter is useful for future backup
    on path capability.

 params.pt.point.final - Specifies if more points will be loaded.  If final = 1,
    no more points will be loaded.  If final = 0, more points can be loaded
    with mpiMotionModify(...) using the APPEND attribute.

 params.pt.point.emptyCount - Specifies how many points the XMP-Series
    controller must have in it's buffer.  If the XMP's point buffer falls
    below the emptyCount, an E-Stop event will be generated by the motion
    supervisor, decelerating all the associated axes to a stop.

When the points are passed to mpiMotionStart(...), the MPI calculates
 constant velocity segments to fit exactly through the specified positions at
 the specified times.  The MPI library automatically handles buffering points
 lists that are larger than the XMP's buffer.  Presently, the XMP-Series
 controller can store 128 Frames per axis.  Each point requires one Frame
 per axis.

Special Considerations:

It is not necesary to specify the initial command position as the first
 position point.  The time[...] values can be constant or vary for each point.
 Constant time[...] values make the programmer's calculations easier.  For
 optimum performance, the number of points can be reduced, with no loss of
 resolution, by replacing the constant velocity sections with longer
 time[...] values.

When creating points lists longer than 64 points, you must create an Event
 Manager.  The Event Manager handles point buffering between the MPI and the XMP
 controller.

For Acceleration/Jerk fits through a points list, use the motion type,
 MPIMotionTypePVT. In this case, position/velocity/time points are specified.

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    pt1Main

argMainRENAME(main, pt1)
#endif

#define AXIS_COUNT      (1)
#define POINT_COUNT     (25)    /* Number of points in trajectory */
#define TIME            (.5)    /* Time between points (seconds) */

double position[AXIS_COUNT * POINT_COUNT];
double ptime[POINT_COUNT];

/* Simple trapezoidal profile velocity path */
double point[POINT_COUNT] = {
    0.0,
    10.0,       /* Acceleration */
    30.0,
    60.0,
    100.0,
    150.0,
    210.0,
    280.0,
    360.0,
    450.0,
    550.0,
    650.0,      /* Constant vel */
    750.0,
    850.0,
    950.0,
    1050.0,
    1140.0,     /* Deceleration */
    1220.0,
    1290.0,
    1350.0,
    1400.0,
    1440.0,
    1470.0,
    1490.0,
    1500.0 };

/* Command line arguments and defaults */
long    axisNumber[AXIS_COUNT] = { 0,  };
long    motionNumber = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;                /* Control object */
    MPIAxis         axis[MEIXmpMAX_Axes];   /* Array of axis objects */
    MPIMotion       motion;                 /* Motion object */
    MPINotify       notify;                 /* Event notification handle */
    MPIEventMgr     eventMgr;               /* Event manager handle */
    MPIMotionParams params;                 /* MPI motion parameters */

    Service         service;                /* Event manager service handle */

    long    returnValue;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIEventMask        eventMask;

    long    argIndex;
    long    pointIndex;
    long    axisIndex;
    long    motionDone;

    double  initialPosition[MEIXmpMAX_Axes];

    /* 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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Create Axis objects */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        axis[axisIndex] =
            mpiAxisCreate(control,
                          axisNumber[axisIndex]);
        msgCHECK(mpiAxisValidate(axis[axisIndex]));
    }

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        NULL);
    msgCHECK(mpiMotionValidate(motion));

    /* Append axis objects to motion object */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue =
            mpiMotionAxisAppend(motion,
                                axis[axisIndex]);
        msgCHECK(returnValue);

        /* Read initial command position */
        returnValue =
            mpiAxisCommandPositionGet(axis[axisIndex],
                                      &initialPosition[axisIndex]);
        msgCHECK(returnValue);

    }

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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);  /* Default sleep (msec) */
    meiASSERT(service != NULL);

    /* Initialize motion params structure */
    params.pt.pointCount = POINT_COUNT;
    params.pt.position = position;
    params.pt.time = ptime;
    params.pt.point.retain = 0;     /* Flush frame buffer after execution */
    params.pt.point.final = 1;      /* Last point */
    params.pt.point.emptyCount = 5; /* Start E-Stop if frames left to execute
                                        is less than this limit. -1 disables */

    /* Create points */
    for (pointIndex = 0; pointIndex < POINT_COUNT; pointIndex++) {

        ptime[pointIndex] = TIME;   /* Delta time between points */

        for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
            /* Position at point */
            position[(pointIndex * AXIS_COUNT) + axisIndex] =
                point[pointIndex] + initialPosition[axisIndex];
        }
    }

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypePT,
                       &params);
    fprintf(stderr,
        "mpiMotionStart returns 0x%x: %s\n",
        returnValue,
        mpiMessage(returnValue, NULL));
    msgCHECK(returnValue);

    /* Collect motion events */
    motionDone = FALSE;
    while (motionDone != TRUE) {

        MPIEventStatus  eventStatus;

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

        switch(eventStatus.type) {

            case MPIEventTypeMOTION_DONE: {
                motionDone = TRUE;
                break;
            }
            default: {
                break;
            }
        }

        fprintf(stderr,
                "mpiNotifyEventWait() returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        msgCHECK(returnValue);

    }

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

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

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

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

    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue = mpiAxisDelete(axis[axisIndex]);
        msgCHECK(returnValue);
    }

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

    return ((int)returnValue);
}


PTAppend.c -- Simple motion path generation, using position/time points with Motion Append
/* ptappend.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/PTAppend.c 4     7/23/01 2:36p Kevinh $";
#endif

/*

:Simple motion path generation, using position/time points with Motion Append

This sample code demonstrates the motion type, MPIMotionTypePT, with Motion
 Append.  A simple trapezoidal velocity profile points list is created, and
 downloaded to the controller.  The time delta between each position is
 constant and the positions are spaced to generate an acceleration, constant
 velocity, and deceleration profile to the final position.

Several motion parameters must be initialized for the PT motion type:

 params.pt.pointCount - Specifies the number of points (position/time).

 params.pt.position - Pointer to a position[...] array.  There is one
    position value per point, per axis.  The length of the array must be
    equal to pointCount multiplied by the number of axes.  The positions
    are interleaved in the array by the axis index.

    For example, a three axis system would have:
        position[0] = position for axis 0
        position[1] = position for axis 1
        position[2] = position for axis 2
        position[3] = position for axis 0
        position[4] = position for axis 1
        etc.

 params.pt.time - Pointer to a time[...] array.  There is one time value
    per point.  The time specifies the number of seconds between the specified
    position, and the next position (point).  The length of the time array must
    be equal to the pointCount.

 params.pt.point.retain - Specifies whether the MPI and XMP should buffer the
    points after they have executed.  If retain = 0, the buffer will destroy
    the points after they have executed.  If retain = 1, the buffer will keep the
    points after they have executed.  This parameter is useful for future backup
    on path capability.

 params.pt.point.final - Specifies if more points will be loaded.  If final = 1,
    no more points will be loaded.  If final = 0, more points can be loaded
    with mpiMotionModify(...) using the APPEND attribute.

 params.pt.point.emptyCount - Specifies how many points the XMP-Series
    controller must have in it's buffer.  If the XMP's point buffer falls
    below the emptyCount, an E-Stop event will be generated by the motion
    supervisor, decelerating all the associated axes to a stop.

When the points are passed to mpiMotionStart(...), the MPI calculates
 constant velocity segments to fit exactly through the specified positions at
 the specified times.  The MPI library automatically handles buffering points
 lists that are larger than the XMP's buffer.  Presently, the XMP-Series
 controller can store 128 Frames per axis.  Each point requires one Frame
 per axis.

Special Considerations:

It is not necesary to specify the initial command position as the first
 position point.  The time[...] values can be constant or vary for each point.
 Constant time[...] values make the programmer's calculations easier.  For
 optimum performance, the number of points can be reduced, with no loss of
 resolution, by replacing the constant velocity sections with longer
 time[...] values.

When creating points lists longer than 64 points, you must create an Event
 Manager.  The Event Manager handles point buffering between the MPI and the XMP
 controller.

For Acceleration/Jerk fits through a points list, use the motion type,
 MPIMotionTypePVT. In this case, position/velocity/time points are specified.

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    ptappendMain

argMainRENAME(main, ptappend)
#endif

#define AXIS_COUNT      (1)
#define POINT_COUNT     (36)    /* Number of points in trajectory */
#define TIME            (0.1)   /* Time between points (seconds) */
#define POSITION_DELTA  (10.0)  /* counts for each point */

double position[AXIS_COUNT * POINT_COUNT];
double time[POINT_COUNT];

double position2[AXIS_COUNT * POINT_COUNT];
double time2[POINT_COUNT];

/* Simple trapezoidal profile velocity path */
double point[POINT_COUNT + 1];

/* Command line arguments and defaults */
long    axisNumber[AXIS_COUNT] = { 0,  };
long    motionNumber = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;                /* Control object */
    MPIAxis         axis[MEIXmpMAX_Axes];   /* Array of axis objects */
    MPIMotion       motion;                 /* Motion object */
    MPINotify       notify;                 /* Event notification handle */
    MPIEventMgr     eventMgr;               /* Event manager handle */
    MPIMotionParams params;                 /* MPI motion parameters */
    MPIMotionParams params2;                    /* MPI motion parameters */

    Service         service;                /* Event manager service handle */

    long    returnValue;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;
    long    pointIndex;
    long    axisIndex;
    long    motionDone;

    MPIEventMask    eventMask;

    double  initialPosition[MEIXmpMAX_Axes];

    double pos = 0.0;

    /* 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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Create Axis objects */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        axis[axisIndex] =
            mpiAxisCreate(control,
                          axisNumber[axisIndex]);
        msgCHECK(mpiAxisValidate(axis[axisIndex]));
    }

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        NULL);
    msgCHECK(mpiMotionValidate(motion));

    /* Append axis objects to motion object */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue =
            mpiMotionAxisAppend(motion,
                                axis[axisIndex]);
        msgCHECK(returnValue);

        /* Read initial command position */
        returnValue =
            mpiAxisCommandPositionGet(axis[axisIndex],
                                      &initialPosition[axisIndex]);
        msgCHECK(returnValue);

    }

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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);  /* Default sleep (msec) */
    meiASSERT(service != NULL);

    /* Initialize motion params structure */
    params.pt.pointCount = POINT_COUNT;
    params.pt.position = position;
    params.pt.time = time;
    params.pt.point.retain = TRUE;      /* Flush frame buffer after execution */
    params.pt.point.final = 0;      /* Last point */
    params.pt.point.emptyCount = 2; /* Start E-Stop if frames left to execute
                                        is less than this limit. -1 disables */

    /* Initialize second motion params structure */
    params2.pt.pointCount = POINT_COUNT;
    params2.pt.position = position2;
    params2.pt.time = time2;
    params2.pt.point.retain = TRUE;     /* Flush frame buffer after execution */
    params2.pt.point.final = 1;     /* Last point */
    params2.pt.point.emptyCount = 5;    /* Start E-Stop if frames left to execute
                                        is less than this limit. -1 disables */

    for(pointIndex = 0; pointIndex < (POINT_COUNT + 1); pointIndex++)
    {
        point[pointIndex] = pos;
        pos += (double) POSITION_DELTA;
    }

    /* Create points */
    for (pointIndex = 0; pointIndex < POINT_COUNT; pointIndex++) {

        time[pointIndex] = TIME;    /* Delta time between points */

        for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
            /* Position at point */
            position[(pointIndex * AXIS_COUNT) + axisIndex] =
                point[(pointIndex + 1)] + initialPosition[axisIndex];
        }
    }

    /* Create secondary points */
    for (pointIndex = 0; pointIndex < POINT_COUNT; pointIndex++) {

        time2[pointIndex] = TIME;   /* Delta time between points */

        for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
            /* Position at point */
            position2[(pointIndex * AXIS_COUNT) + axisIndex] =
                (point[(pointIndex + 1)] + point[POINT_COUNT]) + initialPosition[axisIndex];
        }
    }

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypePT,
                       &params);
    fprintf(stderr,
        "mpiMotionStart returns 0x%x: %s\n",
        returnValue,
        mpiMessage(returnValue, NULL));
    msgCHECK(returnValue);

    /* Modify motion */
    returnValue =
        mpiMotionModify(motion,
                       MPIMotionTypePT | MPIMotionAttrMaskAPPEND,
                       &params2);
    fprintf(stderr,
        "mpiMotionModify returns 0x%x: %s\n",
        returnValue,
        mpiMessage(returnValue, NULL));
    msgCHECK(returnValue);

    /* Collect motion events */
    motionDone = FALSE;
    while (motionDone != TRUE) {

        MPIEventStatus  eventStatus;

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

        switch(eventStatus.type) {

            case MPIEventTypeMOTION_DONE: {
                motionDone = TRUE;
                break;
            }
            default: {
                break;
            }
        }

        fprintf(stderr,
                "mpiNotifyEventWait() returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        msgCHECK(returnValue);

    }

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

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

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

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

    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue = mpiAxisDelete(axis[axisIndex]);
        msgCHECK(returnValue);
    }

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

    return ((int)returnValue);
}


pvt1.c -- Simple motion path generation, specified by position/velocity/time points.
/* pvt1.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/pvt1.c 9     3/15/02 11:38a Erikb $";
#endif

/*

:Simple motion path generation, specified by position/velocity/time points.

This sample code demonstrates the motion type, MPIMotionTypePVT.  A simple
 trapezoidal velocity profile points list is created, and downloaded to
 the controller.  The time delta between each position is constant and
 the positions/velocities are spaced to generate an acceleration, constant
 velocity, and deceleration profile to the final position.

Several motion parameters must be initialized for the PVT motion type:

 params.pvt.pointCount - Specifies the number of points (position/vel./time).

 params.pvt.position - Pointer to a position[...] array.  There is one
    position value per point, per axis.  The length of the array must be
    equal to pointCount multiplied by the number of axes.  The positions
    are interleaved in the array by the axis index.

    For example, a three axis system would have:
        position[0] = position for axis 0
        position[1] = position for axis 1
        position[2] = position for axis 2
        position[3] = position for axis 0
        position[4] = position for axis 1
        etc.

 params.pvt.velocity - Pointer to a velocity[...] array.  There is one
    velocity value per point, per axis.  The length of the array must be
    equal to pointCount multiplied by the number of axes.  The velocities
    are interleaved in the array by the axis index.

    For example, a three axis system would have:
        velocity[0] = velocity for axis 0
        velocity[1] = velocity for axis 1
        velocity[2] = velocity for axis 2
        velocity[3] = velocity for axis 0
        velocity[4] = velocity for axis 1
        etc.

 params.pvt.time - Pointer to a time[...] array.  There is one time value
    per point.  The time specifies the number of seconds between the specified
    position/velocity, and the next position/velocity (point).  The length of
    the time array must be equal to the pointCount.

 params.pvt.point.retain - Specifies whether the MPI and XMP should buffer the
    points after they have executed.  If retain = 0, the buffer will destroy
    the points after they have executed.  If retain = 1, the buffer will keep
    the points after they have executed.  This parameter is useful for future
    backup on path capability.

 params.pvt.point.final - Specifies if more points will be loaded.  If final
    = 1, no more points will be loaded.  If final = 0, more points can be
    loaded with mpiMotionModify(...) using the APPEND attribute.

 params.pvt.point.emptyCount - Specifies how many points the XMP-Series
    controller must have in it's buffer.  If the XMP's point buffer falls
    below the emptyCount, an E-Stop event will be generated by the motion
    supervisor, decelerating all the associated axes to a stop.

When the points are passed to mpiMotionStart(...), the MPI calculates
 accleration/jerk segments to fit exactly through the specified positions at
 the specified times.  The MPI library automatically handles buffering points
 lists that are larger than the XMP's buffer.  Presently, the XMP-Series
 controller can store 128 Frames per axis.  Each point requires one Frame
 per axis.

Special Considerations:

It is not necesary to specify the initial command position as the first
 position point.  The time[...] values can be constant or vary for each point.
 Constant time[...] values make the programmer's calculations easier.  For
 optimum performance, the number of points can be reduced, with no loss of
 resolution, by replacing the constant velocity sections with longer
 time[...] values.

When creating points lists longer than 64 points, you must create an Event
 Manager.  The Event Manager handles point buffering between the MPI and the
 XMP controller.

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    pvt1Main

argMainRENAME(main, pvt1)
#endif

#define AXIS_COUNT      (1)
#define POINT_COUNT     (7)
#define TIME            (.2)    /* Time between points (seconds) */

double position[AXIS_COUNT * POINT_COUNT];
double velocity[AXIS_COUNT * POINT_COUNT];
double ptime[POINT_COUNT];

/* Simple trapezoidal profile velocity path, Positions */
double pointPosition[POINT_COUNT] = {
    0.0,
    400.0,      /* Accel to position */
    1200.0,     /* Constant vel to position */
    1600.0,     /* Decel to position */
    1200.0,     /* Move back */
    400.0,
    0.0 };

double pointVelocity[POINT_COUNT] = {
    0.0,
    4000.0,     /* Accel to vel */
    4000.0,     /* Constant vel */
    0.0,        /* Decel to zero vel */
    -4000.0,    /* Move back */
    -4000.0,
    0.0 };

/* Command line arguments and defaults */
long    axisNumber[AXIS_COUNT] = { 0,  };
long    motionNumber = 0;

/* 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,
                 MPIAxis			axis[AXIS_COUNT],
                 MPIMotion			*motion,
                 MPIEventMgr		*eventMgr,
                 MPINotify			*notify,
                 Service			*service)
{
    MPIEventMask eventMask;
    long returnValue;
    long axisIndex;

     /* Obtain a Control handle */
    *control =
        mpiControlCreate(controlType,
                         controlAddress);
    msgCHECK(mpiControlValidate(*control));

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

    /* Create Axis objects */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        axis[axisIndex] =
            mpiAxisCreate(*control,
                          axisNumber[axisIndex]);
        msgCHECK(mpiAxisValidate(axis[axisIndex]));
    }

    /* Create motion object */
    *motion =
        mpiMotionCreate(*control,
                        motionNumber,
                        NULL);
    msgCHECK(mpiMotionValidate(*motion));

    /* Append axis objects to motion object */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue =
            mpiMotionAxisAppend(*motion,
                                axis[axisIndex]);
        msgCHECK(returnValue);
    }

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(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);  /* Default sleep (msec) */
    meiASSERT(service != NULL);
}

/* Perform certain cleanup actions and delete MPI objects */
void programCleanup(MPIControl	control,
                    MPIAxis		axis[AXIS_COUNT],
                    MPIMotion	motion,
                    MPINotify	notify,
                    MPIEventMgr	eventMgr,
                    Service	service)
{
    long axisIndex;
    long returnValue;

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

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

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

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

    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        returnValue = mpiAxisDelete(axis[axisIndex]);
        msgCHECK(returnValue);
    }

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

}

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;                /* Control object */
    MPIAxis         axis[MEIXmpMAX_Axes];   /* Array of axis objects */
    MPIMotion       motion;                 /* Motion object */
    MPINotify       notify;                 /* Event notification handle */
    MPIEventMgr     eventMgr;               /* Event manager handle */
    MPIMotionParams params;                 /* MPI motion parameters */

    Service         service;                /* Event manager service handle */

    long    returnValue;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    pointIndex;
    long    axisIndex;
    long    motionDone;

    double  initialPosition[MEIXmpMAX_Axes];

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

    /* Create and initialize MPI objects */
    programInit(&control,
                controlType,
                &controlAddress,
                axis,
                &motion,
                &eventMgr,
                &notify,
                &service);

    /* Append axis objects to motion object */
    for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
        /* Read initial command position */
        returnValue =
            mpiAxisCommandPositionGet(axis[axisIndex],
                                      &initialPosition[axisIndex]);
        msgCHECK(returnValue);

    }

    /* Initialize motion params structure */
    params.pvt.pointCount = POINT_COUNT;
    params.pvt.position = position;
    params.pvt.velocity = velocity;
    params.pvt.time = ptime;
    params.pvt.point.retain = 0;    /* Flush frame buffer after execution */
    params.pvt.point.final = 1;     /* Last point */
    params.pvt.point.emptyCount = 5;/* Start E-Stop if frames left to execute
                                        is less than this limit. -1 disables */

    /* Create points */
    for (pointIndex = 0; pointIndex < POINT_COUNT; pointIndex++) {

        ptime[pointIndex] = TIME;   /* Delta time between points */

        for (axisIndex = 0; axisIndex < AXIS_COUNT; axisIndex++) {
            /* Position at point */
            position[(pointIndex * AXIS_COUNT) + axisIndex] =
                pointPosition[pointIndex] + initialPosition[axisIndex];

            /* Velocity at point */
            velocity[(pointIndex * AXIS_COUNT) + axisIndex] =
                pointVelocity[pointIndex];
        }
    }

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypePVT,
                       &params);
    fprintf(stderr,
        "mpiMotionStart returns 0x%x: %s\n",
        returnValue,
        mpiMessage(returnValue, NULL));
    msgCHECK(returnValue);

    /* Collect motion events */
    motionDone = FALSE;
    while (motionDone != TRUE) {

        MPIEventStatus  eventStatus;

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

        switch(eventStatus.type) {

            case MPIEventTypeMOTION_DONE: {
                motionDone = TRUE;
                break;
            }
            default: {
                break;
            }
        }

        fprintf(stderr,
                "mpiNotifyEventWait() returns 0x%x\n"
                "\teventStatus: type %d source 0x%x info 0x%x\n",
                returnValue,
                eventStatus.type,
                eventStatus.source,
                eventStatus.info[0]);
        msgCHECK(returnValue);

    }

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

    return ((int)returnValue);
}


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;
}


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

/*

:Read/display 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    record1Main

argMainRENAME(main, record1)
#endif

#define AXIS_COUNT      (1)
#define RECORD_COUNT    (100)

/* Command line arguments and defaults */
long    axisNumber  = 0;
long    period      = 0;    /* every sample */

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-period",  ArgTypeLONG,    &period,        },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handle */
    MPIRecorder recorder;           /* data recorder handle */

    MPIRecorderRecord   records[RECORD_COUNT];
    MEIRecorderRecord   *recordPtr;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    recordCountRemaining;
    long    recordIndex;

    long    returnValue;    /* return value from library */

    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;
        }
    }

    /* Check that the axis number is valid */
    meiASSERT((axisNumber >= 0) &&
              (axisNumber < MEIXmpMAX_Axes));

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

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

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

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

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

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

    /* Start recording the axis */
    returnValue =
        mpiRecorderStart(recorder,
                         RECORD_COUNT,
                         period,    /* period (milliseconds) */
                         0);
    msgCHECK(returnValue);

    /* Fill the record buffer */
    for (recordIndex = 0,
         recordCountRemaining = RECORD_COUNT; recordCountRemaining > 0; ) {
        long    countGet;

        returnValue =
            mpiRecorderRecordGet(recorder,
                                 recordCountRemaining,
                                 &records[recordIndex],
                                 &countGet);
        msgCHECK(returnValue);

        recordCountRemaining -= countGet;
        recordIndex += countGet;
    }

    /* Stop recording */
    returnValue = mpiRecorderStop(recorder);
    if (returnValue == MPIRecorderMessageSTOPPED) {
        returnValue = MPIMessageOK;
    }
    msgCHECK(returnValue);

    /* Output record buffer to screen */
    for (recordIndex = 0; recordIndex < RECORD_COUNT; recordIndex++) {
        printf("record[%d]:\n",
                recordIndex);

        /* Cast records to MEIRecorderRecord pointer */
        recordPtr = (MEIRecorderRecord *)&records[recordIndex];

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

    returnValue = mpiRecorderDelete(recorder);
    msgCHECK(returnValue);

    returnValue =
        mpiAxisDelete(axis[0]);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


record2.c -- Record Data and Demonstrate How to Start/Stop/Restart Recorder
/* record2.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/record2.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Record Data and Demonstrate How to Start/Stop/Restart Recorder

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    record2Main

argMainRENAME(main, record2)
#endif

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

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

long
    recorderMode(MPIRecorder    recorder,
                 long           mode,
                 long           recordCount,
                 long           period);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;                /* motion controller handle */
    MPIRecorder recorder;               /* data recorder handle */

    MEIXmpData  *firmware;

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

    long    pointCount;
    void    *point[MEIXmpMaxRecSize];

    MPIRecorderRecord   *record;
    register MPIRecorderRecord  *recordPtr;

    long    returnValue;    /* return value from library */

    long    index;

    long    recordCountRemaining;
    long    recordIndex;
    long    recordsRead;

    long    mode;

    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[axisNumber ...]\n",
                           argv[0],
                           ArgUSAGE,
                           period,
                           recordCount);
        exit(MPIMessageARG_INVALID);
    }

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

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

    returnValue =
        mpiControlMemory(control,
                         (void **)&firmware,
                         NULL);
    msgCHECK(returnValue);

    pointCount = 0;

    point[pointCount++] = &firmware->SystemData.SampleCounter;

    for (index = 0; index < axisCount; index++) {
        point[pointCount++] = &firmware->MS[axisNumber[index]].Status;
        point[pointCount++] = &firmware->Axis[axisNumber[index]].Status;
        meiASSERT(pointCount <= MEIXmpMaxRecSize);
    }

    record =
        (MPIRecorderRecord *)meiPlatformAlloc(sizeof(*record) *
                                              recordCount);
    meiASSERT(record != NULL);

    recorder =
        mpiRecorderCreate(control);
    msgCHECK(mpiRecorderValidate(recorder));

    returnValue =
        mpiRecorderRecordConfig(recorder,
                                MPIRecorderRecordTypePOINT,
                                pointCount,
                                point);
    msgCHECK(returnValue);

    recordPtr = record;

    mode = 0;

    meiPlatformConsole("Press any key to start recording, ESC to quit\n");

    recordCountRemaining = recordCount;

    while (recordCountRemaining > 0) {
        mode =
            recorderMode(recorder,
                         mode,
                         recordCountRemaining,
                         period);

        if (mode > 0) {
            long    countGet;

            returnValue =
                mpiRecorderRecordGet(recorder,
                                     recordCountRemaining,
                                     recordPtr,
                                     &countGet);
            msgCHECK(returnValue);

            recordCountRemaining -= countGet;
            recordPtr += countGet;
        }
        else if (mode < 0) {
            break;
        }
    }

    recordsRead = recordPtr - record;

    for (recordIndex = 0,
            recordPtr = record;
         recordIndex < recordsRead;
         recordIndex++,
             recordPtr++) {
        long    pointIndex;

        pointIndex = 0;

        printf("record[%d]: sample %d\n",
                recordIndex,
                recordPtr->point[pointIndex++]);

        for (index = 0; index < axisCount; index++) {
            printf("%d: motion status 0x%x axis status 0x%x\n",
                    axisNumber[index],
                    recordPtr->point[pointIndex],
                    recordPtr->point[pointIndex + 1]);

            pointIndex += 2;
        }
        meiASSERT(pointIndex == pointCount);
    }

    returnValue = mpiRecorderDelete(recorder);
    msgCHECK(returnValue);

    returnValue =
        meiPlatformFree(record,
                        (sizeof(*record) * recordCount));
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}

long
    recorderMode(MPIRecorder    recorder,
                 long           mode,
                 long           recordCount,
                 long           period)
{
    long    returnValue;

    long    modeNew;

    long    key;

    key = meiPlatformKey(MPIWaitPOLL);

    if (key <= 0) {
        if (key == 0) {
            key = meiPlatformKey(MPIWaitPOLL);
        }
        modeNew = mode;
    }
    else if (key == 0x1b) {
        modeNew = -1;
    }
    else {
        modeNew = (mode <= 0) ? 1 : 0;
    }

    if (modeNew != mode) {
        if (modeNew <= 0) {
            if (mode > 0) {
                returnValue =
                    mpiRecorderStop(recorder);
                msgCHECK(returnValue);
            }
        }
        else {
            returnValue =
                mpiRecorderStart(recorder,
                                 recordCount,
                                 period,    /* period (milliseconds) */
                                 0);
            msgCHECK(returnValue);
        }

        if (modeNew >= 0) {
            meiPlatformConsole("Press any key to %s recording, ESC to quit\n",
                                (modeNew == 0) ? "start" : "stop ");
        }
    }

    return (modeNew);
}


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);
}


record4.c -- Perform a diagonal two-axis motion and record command velocity and status.
/* record4.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/record4.c 15    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a diagonal two-axis motion and record command velocity and status.

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    record4Main

argMainRENAME(main, record4)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;
long            period          = 0;    /* every sample */
long            recordCount     = 100;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },
    {   "-period",  ArgTypeLONG,    &period,        },
    {   "-records", ArgTypeLONG,    &recordCount,   },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 200000.0, 200000.0,   },
    { 0.0,      0.0,        },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 100000.0,     1000000.0,  1000000.0,  50.0,   },
        { 100000.0,     1000000.0,  1000000.0,  50.0,   },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 100000.0,     1000000.0,  1000000.0,  50.0,   },
        { 100000.0,     1000000.0,  1000000.0,  50.0,   },
    },
};

/* motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIRecorder recorder;   /* data recorder handle */

    MPIAxis     axisX;      /* X axis */
    MPIAxis     axisY;      /* Y axis */
    MPIMotion   motion;     /* motion object */

    long    returnValue;    /* return value from library */

    long    index;

    MEIXmpData  *firmware;

    long    axisCount;

    long    pointCount;
    void    *point[MEIXmpMaxRecSize];

    MPIRecorderRecord   *record;
    register MPIRecorderRecord  *recordPtr;

    long    recordCountRemaining;
    long    recordIndex;
    long    recordsRead;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n"
                           "\t\t[-period (%d)]\n"
                           "\t\t[-records (%d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIMotionTypeLAST - 1,
                            period,
                            recordCount);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    returnValue =
        mpiControlMemory(control,
                         (void **)&firmware,
                         NULL);
    msgCHECK(returnValue);

    /* Create X axis object using axisNumber on controller*/
    axisX =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axisX));

    /* Create Y axis object using axisNumber + 1 on controller */
    axisY =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axisY));

    /* Create motion object */
    /* Append X axis to motion */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axisX);
    msgCHECK(mpiMotionValidate(motion));

    /* Append Y axis to motion */
    returnValue =
        mpiMotionAxisAppend(motion,
                            axisY);
    msgCHECK(returnValue);

    axisCount   = AXIS_COUNT;
    pointCount  = 0;

    point[pointCount++] = &firmware->SystemData.SampleCounter;

    for (index = 0; index < axisCount; index++) {
        point[pointCount++] = &firmware->Axis[index].Status;
        point[pointCount++] = &firmware->Axis[index].TC.Velocity;
        meiASSERT(pointCount <= MEIXmpMaxRecSize);
    }

    record =
        (MPIRecorderRecord *)meiPlatformAlloc(sizeof(*record) *
                                              recordCount);
    meiASSERT(record != NULL);

    recorder =
        mpiRecorderCreate(control);
    msgCHECK(mpiRecorderValidate(recorder));

    returnValue =
        mpiRecorderRecordConfig(recorder,
                                MPIRecorderRecordTypePOINT,
                                pointCount,
                                point);
    msgCHECK(returnValue);

    recordPtr = record;

    recordCountRemaining = recordCount;

    returnValue =
        mpiRecorderStart(recorder,
                         recordCount,
                         period,    /* period (milliseconds) */
                         0);
    msgCHECK(returnValue);

    /* Loop repeatedly */
    index = 0;
    {
        long    motionDone;

        if (returnValue == MPIMessageOK) {
            MPIMotionParams motionParams;

            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            returnValue =
                mpiMotionStart(motion,
                               motionType,
                               &motionParams);

            if (returnValue != MPIMessageOK) {
                printf("mpiMotionStart(0x%x, %d, 0x%x) returns 0x%x: %s\n",
                       motion,
                       motionType,
                       &motionParams,
                       returnValue,
                       mpiMessage(returnValue, NULL));
            }
        }

        while (recordCountRemaining > 0) {
            long    countGet;

            returnValue =
                mpiRecorderRecordGet(recorder,
                                     recordCountRemaining,
                                     recordPtr,
                                     &countGet);
            msgCHECK(returnValue);

            recordCountRemaining -= countGet;
            recordPtr += countGet;
        }

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

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

            switch (status.state) {
                case MPIStateMOVING: {
                    break;
                }
                case MPIStateIDLE: {
                    motionDone = TRUE;
                    break;
                }
                case MPIStateERROR: {
                    motionDone = TRUE;

                    returnValue =
                        mpiMotionAction(motion,
                                        MPIActionRESET);
                    msgCHECK(returnValue);

                    /* Wait for reset to take effect */
                    meiPlatformSleep(100);

                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }
        }

        if (++index >= MOTION_COUNT) {
            index = 0;
        }
    }

    recordsRead = recordPtr - record;

    printf("Record\tSample\tStat 0\tVel 0\tStat 1\tVel 1\n");

    for (recordIndex = 0,
            recordPtr = record;
         recordIndex < recordsRead;
         recordIndex++,
             recordPtr++) {

        printf("%d\t%d\t0X%X\t%f\t0X%X\t%f\n",
                recordIndex,
                recordPtr->point[0],
                recordPtr->point[1],
                (float)*((float *)&recordPtr->point[2]),
                recordPtr->point[3],
                (float)*((float *)&recordPtr->point[4]));

    }

    returnValue = mpiRecorderDelete(recorder);
    msgCHECK(returnValue);

    returnValue =
        meiPlatformFree(record,
                        (sizeof(*record) * recordCount));
    msgCHECK(returnValue);

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

    returnValue = mpiAxisDelete(axisY);
    msgCHECK(returnValue);

    returnValue = mpiAxisDelete(axisX);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


scclose.c -- Transition control from open-loop to closed-loop mode.
/* ScClose.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.
 */

/*

:Transition control from open-loop to closed-loop mode.

On all motors specified by MOTOR_COUNT
 and set origin on axes specified by AXIS_COUNT (note - assumes a linear
 map of motors and axes).

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 ScClose

argMainRENAME(main, ScClose)
#endif

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

void SetPositionZero(MPIAxis axis);

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;/*  motion controller handle  */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIAxis     axis;   /* axis handle */
    MPIMotor    motor;  /* motor handle */

    MEIMotorConfig  motorConfigXmp;

    long    returnValue;

    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) ||
        (axisNumber  >= MEIXmpMAX_Axes) ||
        (motorNumber >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

    printf("Going to closed loop (zeroing position) ...");

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

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

    /* Create axis objects and zero position */

    axis =
        mpiAxisCreate(control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(axis));

    SetPositionZero(axis);

    /* Create motor objects and transition to closed-loop control */

    motor =
        mpiMotorCreate(control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(motor));

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

    motorConfigXmp.Commutation.Mode = MEIXmpCommModeCLOSED_LOOP;

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

    /* Delete objects */
    returnValue = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    returnValue = mpiControlDelete(control);
    meiASSERT(returnValue == MPIMessageOK);

    return ((int)returnValue);
}

void SetPositionZero(MPIAxis axis)
{
    double  actualPosition;
    double  origin;

    long    returnValue;

    returnValue =
        mpiAxisActualPositionGet(axis,
                                 &actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    returnValue =
        mpiAxisOriginGet(axis,
                         &origin);
    meiASSERT(returnValue == MPIMessageOK);

    actualPosition += origin;

    returnValue =
        mpiAxisOriginSet(axis,
                         actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    meiPlatformSleep(15);

    actualPosition = 0;

    returnValue =
        mpiAxisCommandPositionSet(axis,
                                  actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    meiPlatformSleep(15);
};


scdither.c -- Sinusoidal Commutation Initialization Using the Dithering Method
/* ScDither.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.
 */

/*

: Sinusoidal Commutation Initialization Using the Dithering Method

Uses Dithering initialization for one axis. Axis remains in open-loop
  mode with amplifier enabled.

Note -
  #define provided for reversing encoder and DAC phasing. Program disables
  HW Limits, Amp Fault, Home and Error Limit.

The commutation configuration parameters will be different
  for your application.  Take particular care in setting the open-loop
  continuous DAC OutputLevel as this must be a safe level for your specific
  drive and motor combination.  Please read Sinusoidal Commutation Documentation
  in the MPI/MEI Software Reference Manual for further information.

Successful initialization with "Dithering" requires a system with minimal
  influence from external forces (e.g., gravitational force, cable carrier, etc)
  and static friction.

The parameters DAC level ("OutputLevel") and time delay ("VEL_DELAY" and
  "ACC_DELAY")  should be set for optimum performance with the user's specific system.

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    ScDither

argMainRENAME(main, ScDither)
#endif

#define VEL_DELAY           (5)                     /* servo samples */
#define ACC_DELAY           (5)                     /* servo samples */
#define RECORD_COUNT_MAX    (VEL_DELAY + ACC_DELAY) /* number of data recorder points */

/* Command line arguments and defaults */
long    axisNumber      = 0;
long    motionNumber    = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Option to reverse encoder phasing */
#undef ReverseEncPhasing
/* Option to reverse DAC phasing */
#undef ReverseDACPhasing

MEIRecorderRecord   Record[RECORD_COUNT_MAX];

double
    accelActualGet(MPIRecorder  recorder,
                   MPIAxis      axis);

void
    setPositionZero(MPIAxis axis);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIAxis     axis;       /* axis handles */
    MPIFilter   filter;     /* filter handles */
    MPIMotor    motor;      /* motor handles  */
    MPIMotion   motion;     /* coordinated motion object handles */
    MPIRecorder recorder;   /* data recorder handle */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIControlConfig    controlConfig;      /* motion controller configuration */
    MPIAxisConfig       axisConfig;         /* axis configuration */
    MPIMotorConfig      motorConfig;
    MEIMotorConfig      motorConfigXmp;
    MPIFilterGain       gain;
    MEIFilterGainPID    *pid;

    MEIXmpData  *firmware;

    MEIXmpCommutationBlock  *commutation;

    long    nEncCountPerCycle = 4096; /* number of encoder counts per motor revolution */
    float   OpenDAC_Level   =   (float)3277.0;  /* Open Loop DAC Level where 32767. = 10V) */
    float   N_CYCLES    =       (float)3.0;     /* number of elec. cycles per motor rev. */

    long    returnValue;    /* return value from library */

    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) ||
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

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

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

    returnValue =
        mpiControlMemory(control,
                         (void**)&firmware,
                         (void**)NULL);
    msgCHECK(returnValue);

    /*  Create a Data Recorder for future use   */
    recorder =
        mpiRecorderCreate(control);
    msgCHECK(mpiRecorderValidate(recorder));

    /*
        Configure motion controller
        Set Sample Rate = 2 kHz
        configure for commutation B phase DACs and ADCs
     */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    controlConfig.sampleRate = 2000;

    /*
        When supporting commutation,
        Cmd and Aux DACs must be enabled.
        Enabling the same number of Cmd and Aux DACs as there are motors.
     */
    controlConfig.cmdDacCount = controlConfig.motorCount;
    controlConfig.auxDacCount = controlConfig.motorCount;

    /*  Configure required number of A/Ds   */
    controlConfig.adcCount = 8;

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    /*  Create axis, filter and motor controller objects    */

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

    /*  Create filter   */
    filter =
        mpiFilterCreate(control,
                        axisNumber);
    msgCHECK(mpiFilterValidate(filter));

    /*  Create motor    */
    motor =
        mpiMotorCreate(control,
                       axisNumber);
    msgCHECK(mpiMotorValidate(motor));

    /*  Disable the amplifier   */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                             FALSE);
    msgCHECK(returnValue);

    /*  Configure axis  */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    /*  Set inPositionLimit */
    axisConfig.inPosition.tolerance.positionFine = (float)1.0e10;

    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    /*  Configure Motor */
    returnValue =
        mpiMotorConfigGet(motor,
                          &motorConfig,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    /*
        Disable limit error, home, amp fault & H/W Limits
        Set encoder phase
     */

    /*  Disable limit error */
    motorConfig.event[MPIEventTypeLIMIT_ERROR].action           = MPIActionNONE;
    motorConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error    = (float)50000;

    /*  Disable home event  */
    motorConfig.event[MPIEventTypeHOME].action  = MPIActionNONE;

    /*  Disable amp fault event */
    motorConfig.event[MPIEventTypeAMP_FAULT].action = MPIActionNONE;

    /*  Disable neg. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_NEG].action  = MPIActionNONE;

    /*  Disable pos. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_POS].action  = MPIActionNONE;

    /*
            Set encoder phase:

            0 - for normal
            1 - for reversed
     */
#if defined(ReverseEncPhasing)
    motorConfig.encoderPhase = 1;
#else
    motorConfig.encoderPhase = 0;
#endif

    /* Setup commutation  */
    commutation = &motorConfigXmp.Commutation;

    /* Motor Controller commutation parameters */
    commutation->Mode        = MEIXmpCommModeOPEN_LOOP;
    commutation->Length      = nEncCountPerCycle;
    commutation->Scale       = (float)MEIXmpCOMM_TABLE_SIZE * N_CYCLES /
                               (float)commutation->Length;
    commutation->PhaseDelta  = MEIXmpCOMM_120DEGREES;
    commutation->OutputLevel = OpenDAC_Level;
    commutation->Offset      = (long)0;

#if defined(ReverseDACPhasing)
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseINVERTED;
#else
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseNORMAL;
#endif

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                          &motorConfig,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    /* Get current configuration */
    returnValue =
        mpiFilterGainGet(filter,
                         MEIFilterGainIndexDEFAULT,
                         &gain);
    msgCHECK(returnValue);

    pid = (MEIFilterGainPID *)&gain;

    /* Filter Controller control parameters */
    pid->gain.proportional          = (float)50.0;
    pid->gain.integral              = (float)0.0;
    pid->gain.derivative            = (float)200.0;
    pid->feedForward.velocity       = (float)0.0;
    pid->feedForward.acceleration   = (float)0.0;
    pid->feedForward.friction       = (float)0.0;
    pid->integrationMax.moving      = (float)0.0;
    pid->integrationMax.rest        = (float)0.0;
    pid->output.limit               = (float)26213.6;
    pid->output.offset              = (float)0.0;

    /* Set filter configuration  */
    returnValue =
        mpiFilterGainSet(filter,
                         MEIFilterGainIndexDEFAULT,
                         &gain);
    msgCHECK(returnValue);

    /*
        Create a Motion Object and append an Axis
        Note 1 - separate axis appends will be required for coordinated motion
        Note 2 - Axis Map does not take effect until motion is commanded
     */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        axis);
    msgCHECK(mpiMotionValidate(motion));

    /* Clear out any previous errors */
    returnValue =
        mpiMotionAction(motion,
                        MPIActionRESET);
    msgCHECK(returnValue);

    /*  Immediately send Map to controller  */
    returnValue =
        mpiMotionAction(motion,
                        (MPIAction)MEIActionMAP);
    msgCHECK(returnValue);

    /*  Enable the amplifier    */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                             TRUE);
    msgCHECK(returnValue);

    /*  Begin "Dither" phase-finding based on motor acceleration sequence   */
    {
        double  angle;
        double  delta;

        long    index;

        angle = 0.0;
        delta = 256.0;

        /*
            Find Field magnetic vector by dithering Stator vector (monitor
            direction of acceleration
         */
        for (index = 0; index < 8; index++) {
            double  accel;

            long    angleSet;

            accel =
                accelActualGet(recorder,
                               axis);

            if (accel < 0.0) {
                angle += delta;
            }
            else {
                angle -= delta;
            }

            angleSet = (long)angle;

            returnValue =
                mpiMotorMemorySet(motor,
                                  &firmware->Motor[axisNumber].Commutation.Offset,
                                  &angleSet,
                                  sizeof(firmware->Motor[axisNumber].Commutation.Offset));
            msgCHECK(returnValue);

            delta *= .75;

            /* Avoid dual null position issue with first dither */
            if ((index == 0) &&
                (accel == 0.0)) {
                delta *= 2;
            }
        }
    }

    /*  Zero Position   */
    setPositionZero(axis);

    /*  Go Closed Loop  */
#if 0
    returnValue =
        meiMotorCommutationModeSet(motor,
                                   MEIXmpCommModeCLOSED_LOOP);
    msgCHECK(returnValue);
#endif

    /*  Delete Objects  */
    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

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

    returnValue = mpiFilterDelete(filter);
    msgCHECK(returnValue);

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

    returnValue = mpiRecorderDelete(recorder);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}

double
    accelActualGet(MPIRecorder  recorder,
                   MPIAxis      axis)
{
    long    returnValue;    /* return value from library */

    MEIRecorderRecord   *recordPtr;

    long    recordsRemaining;

    long    v1;
    long    v2;

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

    returnValue =
        mpiRecorderStart(recorder,
                         RECORD_COUNT_MAX,  /* number of records */
                         0,                 /* period (milliseconds) */
                         0);
    msgCHECK(returnValue);

    recordPtr = Record;
    recordsRemaining = RECORD_COUNT_MAX;

    while (recordsRemaining > 0) {
        long    recordsRead;

        returnValue =
            mpiRecorderRecordGet(recorder,
                                 recordsRemaining,
                                 (MPIRecorderRecord *)recordPtr,
                                 &recordsRead);
        msgCHECK(returnValue);

        recordsRemaining -= recordsRead;
        recordPtr        += recordsRead;
    }

    returnValue = mpiRecorderStop(recorder);

    if (returnValue == MPIRecorderMessageSTOPPED) {
        returnValue = MPIMessageOK;
    }
    msgCHECK(returnValue);

    v1 =
        Record[VEL_DELAY - 1].axis[0].actual -
        Record[0].axis[0].actual;

    v2 =
        Record[RECORD_COUNT_MAX - 1].axis[0].actual -
        Record[RECORD_COUNT_MAX - VEL_DELAY].axis[0].actual;

    return ((double)(v2 - v1));
}

void
    setPositionZero(MPIAxis axis)
{
    double  actualPosition;
    double  origin;

    long    returnValue;

    returnValue =
        mpiAxisActualPositionGet(axis,
                                 &actualPosition);
    msgCHECK(returnValue);

    returnValue =
        mpiAxisOriginGet(axis,
                         &origin);
    msgCHECK(returnValue);

    actualPosition += origin;

    returnValue =
        mpiAxisOriginSet(axis,
                         actualPosition);
    msgCHECK(returnValue);

    meiPlatformSleep(15);

    actualPosition = 0;

    returnValue =
        mpiAxisCommandPositionSet(axis,
                                  actualPosition);
    msgCHECK(returnValue);

    meiPlatformSleep(15);
}


schall.c -- Single-Axis Sinusoidal Commutation Sample Program with Hall Initialization
/* ScHall.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.
 */

/*

:Single-Axis Sinusoidal Commutation Sample Program with Hall Initialization

This program reads the Hall - I/O bit state, then sets the commutation
 table entry point to match the active Hall sensor.  This version latches
 position and up-dates the commutation entry point based on the first
 Hall transition (latches upon a single I/O with a specific edge).

        Axis 0:     Uses Hall-type initialization with a small trapezoidal
                    move (closed-loop) to the first Hall transition. Updates
                    commutation position based on the Hall transition location.

    Background:     The initial state of the three Hall sensors provides six
                    possible magnetic sectors of 60 degrees which may contain
                    the motor field vector (i.e., rotor magnetic position).
                    This program uses the following logic table:

 Mag.Phase Angle:    0 - 60 60 - 120 120 - 180  180 - 240 240 - 300  300 - 360
                    -----------------------------------------------------------
                    |       |       |         |          |          |         |
    Hall A Sensor   |  On   |   On  |   On    |    Off   |   Off    |    Off  |
                    |       |       |         |          |          |         |
    Hall B Sensor   |  Off  |   Off |   On    |    On    |   On     |    Off  |
                    |       |       |         |          |          |         |
    Hall C Sensor   |  On   |   Off |   Off   |    Off   |   On     |    On   |
                    -----------------------------------------------------------

 Hall Logic (C,B,A) (101)     (001)    (011)      (010)     (110)      (100)

 Hall Region            5       1        3          2         6          4

            The rotor magnetic field vector will initially be located within
            one of these six regions.  Sufficient accuracy for closed-loop control
            is obtained by assigning the magnetic location to the mid-point of
            the active region.  Thus, the actual commutation accuracy will be +/- 30
            electrical degrees (assuming the halls have been accurately located on your
            motor).  The motor is configured under closed-loop control and a slow
            trapezoidal move is implemented to the first observed Hall transition.
            The commutation position is then corrected to reflect the exact magnetic
            position of the Hall transition point.

            Note -  The XMP calculates: A Phase DAC Output = sin(Theta + 120)
                                        B Phase DAC Output = sin(Theta)

            Note -  See the XMP Installation Manual for information on wiring the
                    Transceiver I/O to the Hall sensors.

            Note -  #defs are provided to reverse encoder and DAC phasing.  Be aware
                    that the DAC phasing change should be called only once.

 Configure the XMP:

            Axis 0  Filter 0   Motor 0

 Configure Transceivers as input (default state):

            This sample application configures three transceivers on one motor.

Warning!   This program disables the HW Limits, Amp Fault, Home and Error Limit.

Warning!  The commutation configuration parameters will be different
 for your application.  Take particular care in setting the open-loop
 continuous DAC OutputLevel as this must be a safe level for your specific
 drive and motor combination.  Please read the MEI Sinusoidal Commutation
 Documentation.

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 ScHall

argMainRENAME(main, ScHall)
#endif

#define AXIS_CNT    (1)
#define SLOW        (5.E2)      /* velocity to first Hall transition, cts/sec */
#define SLOW_ACCEL  (1.E4)      /* acceleration to first Hall transition cts/sec */
#define FAST        (5.E4)      /* velocity to shift commutation pointer, cts/sec */
#define FAST_ACCEL  (5.E5)      /* acceleration to shift comm. pointer cts/sec */

#undef USERIO

#if defined USERIO    /* Toggle the user bit associated with the motor */
#define BIT_MASK MEIXmpMotorIOMaskUSER   /* user IO Bit Mask */
#define BIT_IO   MEIXmpMotorIOBitUSER   /* user IO Bit */
#endif

/* User Settings MotorIO transceivers */
#define IO_CONFIG_IN        (MEIMotorTransceiverConfigINPUT) /* INPUT or OUTPUT   */
#define TRANSC_A_ID         (MEIMotorTransceiverIdA)
#define TRANSC_A_MASK       (MEIMotorTransceiverMaskA)
#define TRANSC_B_ID         (MEIMotorTransceiverIdB)
#define TRANSC_B_MASK       (MEIMotorTransceiverMaskB)
#define TRANSC_C_ID         (MEIMotorTransceiverIdC)
#define TRANSC_C_MASK       (MEIMotorTransceiverMaskC)

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

/* Capture Parameters */
#define ACTIVE_LOW_EDGE     (0)
#define ACTIVE_HIGH_EDGE    (1)

long captureActiveEdge = ACTIVE_HIGH_EDGE;      /* capture on high edge */

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* Option to reverse encoder phasing */
#undef ReverseEncPhasing
/* Option to reverse DAC phasing */
#undef ReverseDACPhasing
#undef DumpCommParameters

void SetPositionZero(MPIAxis axis);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIAxis     axis;       /* axis handles */
    MPIFilter   filter;     /* filter handles */
    MPIMotor    motor;      /* motor handles  */
    MPICapture  capture;    /* capture handles */

    MPIControlConfig    controlConfig;  /* motion controller configuration */
    MPIAxisConfig       axisConfig;     /* axis configuration */
    MPIFilterGain       gain;
    MPIMotorConfig      motorConfig;    /* motor configuration */
    MPIMotorEventConfig eventConfig;
    MPIMotorIo          io;
    MPICaptureConfig    captureConfig;  /* capture configuration */
    MPICaptureStatus    captureStatus;  /* capture status */

    MEIMotorConfig      motorConfigXmp; /* contains transceiver configuration */
    MEIFilterGainPID    *pid;
    MEIXmpCommutationBlock  *commutation;

    MPIMotion       motion; /* Coordinated motion object handles */
    MPIMotionParams params; /* Motion parameters */
    MPITrajectory   trajectory;

    MPIControlType          controlType;
    MPIControlAddress       controlAddress;

    long    returnValue;    /* return value from library */
    long    iTranState;     /* value of the Hall transceiver word */
    long    iOffset;        /* integer value to move comm. Offset parameter */
    long    nEncCountPerCycle =  4096;          /* number of encoder counts per motor revolution */
    float   OpenDAC_Level     = (float)3277.0;  /* Open Loop DAC Level where 32767. = 10V) */
    float   N_CYCLES          = (float)3.0;     /* number of elec. cycles per motor rev. */

#if defined(ReverseDACPhasing)
    long    dacCount;
    long    dacNumber[MPIMotorDacCountMAX];
    long    number;
#endif

    double          command;
    double          endposition;
    double          LminusTh;
    double          origin;
    double          origLatchPosition, latchedPosition, latchPosChange;

    float   inPositionLimit = (float)1.0e10;

    long    argIndex;
    long    captureNumber;

    /* 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) ||
        (axisNumber   >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    /* Calculate default capture number for axisNumber */
    captureNumber = (axisNumber/MEIXmpMotorsPerBlock) * MEIXmpMaxLatches +
                    (axisNumber % MEIXmpMotorsPerBlock) * 2;

    /* Create device driver motion controller object  */

    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /*
       Configure motion controller
       Set Sample Rate = 2 kHz (this is the default)
       Configure for commutation B phase DACs
       Configure ADCs
     */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    controlConfig.sampleRate = 2000;

    /*
        When supporting commutation,
        Cmd and Aux DACs must be enabled.
        Enabling the same number of Cmd and Aux DACs as there are motors.
     */
    controlConfig.cmdDacCount = controlConfig.motorCount;
    controlConfig.auxDacCount = controlConfig.motorCount;

    /* Configure required number of A/D  */
    controlConfig.adcCount = 8;

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    /* Create axis, filter and motor controller objects */

    axis =
        mpiAxisCreate(control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(axis));

    filter =
        mpiFilterCreate(control,
                      axisNumber);
    msgCHECK(mpiFilterValidate(filter));

    motor =
        mpiMotorCreate(control,
                      motorNumber);
    msgCHECK(mpiMotorValidate(motor));

    /* Create capture object for captureNumber */
    capture =
        mpiCaptureCreate(control,
                         captureNumber);
    msgCHECK(mpiCaptureValidate(capture));

    /* Disable the amplifier */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                            FALSE);

    /* Disable capture */
    returnValue =
        mpiCaptureArm(capture,
                      FALSE);
    msgCHECK(returnValue);

    msgCHECK(returnValue);

    /* Configure axis  */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    /* Set inPositionLimit  */
    axisConfig.inPosition.tolerance.positionFine = inPositionLimit;

    returnValue =
        mpiAxisConfigSet(axis,
                        &axisConfig,
                        NULL);
    msgCHECK(returnValue);

    /* Configure Motor */
    returnValue =
        mpiMotorConfigGet(motor,
                         &motorConfig,
                         &motorConfigXmp);
    msgCHECK(returnValue);

    /* Disable limit error, home, amp fault & H/W Limits, set encoder phase */

    /* Disable limit error */
    motorConfig.event[MPIEventTypeLIMIT_ERROR].action           = MPIActionNONE;
    motorConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error    = (float)50000;

    /* Disable home event */
    motorConfig.event[MPIEventTypeHOME].action  = MPIActionNONE;

    /* Disable amp fault event */
    motorConfig.event[MPIEventTypeAMP_FAULT].action = MPIActionNONE;

    /* Disable neg. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_NEG].action  = MPIActionNONE;

    /* Disable pos. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_POS].action  = MPIActionNONE;

    /* Verify that transceivers are configured for input (default) */
    motorConfigXmp.Transceiver[TRANSC_A_ID].Config = IO_CONFIG_IN;
    motorConfigXmp.Transceiver[TRANSC_B_ID].Config = IO_CONFIG_IN;
    motorConfigXmp.Transceiver[TRANSC_C_ID].Config = IO_CONFIG_IN;

    /* Set encoder phase; 0 - for normal; 1 - for reversed */

#ifdef ReverseEncPhasing
    motorConfig.encoderPhase = 1;
#else
    motorConfig.encoderPhase = 0;
#endif

    /* Setup Motor commutation in open-loop mode  */
    commutation = &motorConfigXmp.Commutation;

    commutation->Mode        = MEIXmpCommModeOPEN_LOOP;
    commutation->Length      = nEncCountPerCycle;
    commutation->Scale       = (float)MEIXmpCOMM_TABLE_SIZE * N_CYCLES /
                               (float)commutation->Length;
    commutation->PhaseDelta  = MEIXmpCOMM_120DEGREES;
    commutation->OutputLevel = OpenDAC_Level;   /* Open-loop DAC level */
    commutation->Offset      = (long)0;

#if defined(ReverseDACPhasing)
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseINVERTED;
#else
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseNORMAL;
#endif

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /* Get current Filter configuration */
    returnValue =
        mpiFilterGainGet(filter,
                        MEIFilterGainIndexDEFAULT,
                        &gain);
    msgCHECK(returnValue);

    pid = (MEIFilterGainPID *)&gain;

    /* Filter Controller control parameters */
    pid->gain.proportional          = (float)100.0; /* Kp must be set for your system */
    pid->gain.integral              = (float)0.0;   /* Ki set to zero for initial use */
    pid->gain.derivative            = (float)400.0; /* Kd must be set for your system */
    pid->feedForward.velocity       = (float)0.0;
    pid->feedForward.acceleration   = (float)0.0;
    pid->feedForward.friction       = (float)0.0;
    pid->integrationMax.moving      = (float)0.0;
    pid->integrationMax.rest        = (float)0.0;
    pid->output.limit               = (float)32767.0; /* closed-loop output limit */
    pid->output.offset              = (float)0.0;

    /* Set filter configuration  */
    returnValue =
        mpiFilterGainSet(filter,
                        MEIFilterGainIndexDEFAULT,
                        &gain);
    msgCHECK(returnValue);

    /*
       Create a Motion Object and append an Axis
       Note 1 - separate axis appends will be required for coordinated motion
       Note 2 - Axis Map does not take effect until motion is commanded!
     */
    motion =
         mpiMotionCreate(control,
                         motionNumber,
                         axis);
    msgCHECK(mpiMotionValidate(motion));

    /* Clear out any previous errors */
    returnValue =
        mpiMotionAction(motion,
                        MPIActionRESET);
    msgCHECK(returnValue);

    /* Immediately send Map to controller */
    returnValue =
        mpiMotionAction(motion,
                        (MPIAction)MEIActionMAP);
    msgCHECK(returnValue);

    /* Display commutation parameters */
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

 #ifdef DumpCommParameters

    printf("Motor %ld:\n",
            motorNumber);

    printf("\tCommutation Length before O-L move = %ld\n",
            motorConfigXmp.Commutation.Length);

    printf("\tCommutation Scale = %f\n",
            motorConfigXmp.Commutation.Scale);

    printf("\tCommutation Theta = %ld\n",
            motorConfigXmp.Commutation.Theta);

#endif

    if (motorConfigXmp.Commutation.Length != 0) {

        double  phaseAngle;
        long tableIndex;

        tableIndex =
            ((long)(motorConfigXmp.Commutation.Theta *
              motorConfigXmp.Commutation.Scale)) &
             (MEIXmpCOMM_TABLE_SIZE - 1);

        phaseAngle =
             (double)tableIndex * 360.0/
             (double)MEIXmpCOMM_TABLE_SIZE;

        LminusTh = (double)(motorConfigXmp.Commutation.Length -
              motorConfigXmp.Commutation.Theta);

        printf("\tPhase angle = %lf degrees\n",
                phaseAngle);
    }

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /*
       Implement an open-loop "move" (without drive enabled)to
       allow Trajectory Calculator Delta to move commutation
       Theta to the beginning of the commutation table (w/o motion).
       Therefore, if Theta != 0:

                Move distance = Length - Theta (counts)
     */

    if((long)(motorConfigXmp.Commutation.Theta *
              motorConfigXmp.Commutation.Scale) != 0)
        {

        returnValue =
            mpiAxisCommandPositionGet(axis,
                                  &command);
        msgCHECK(returnValue);

        trajectory.velocity     = FAST;
        trajectory.acceleration = FAST_ACCEL;
        trajectory.deceleration = FAST_ACCEL;

        params.trapezoidal.trajectory = &trajectory;
        endposition =
        command + LminusTh;
        params.trapezoidal.position = &endposition;

        meiPlatformSleep(25);

        /*   Start "virtual" motion  */
        returnValue =
            mpiMotionStart(motion,
                           MPIMotionTypeTRAPEZOIDAL,
                         &params);
        msgCHECK(returnValue);

        /*   Delay to allow "virtual" motion to complete  */
        meiPlatformSleep(500);

        }

    /* Zero command and actual positions */
        SetPositionZero(axis);

    /* Read and display the transceiver IO bit */

    returnValue =
        mpiMotorIoGet(motor,
                      &io);
    msgCHECK(returnValue);

/*
   At this point we are still in open-loop mode with the drive disabled.
   The combined transceiver word provides the basic logic needed to establish
   the commutation Offset (Offset range: 0 to 1023) required for the active
   Hall region.
 */

    iTranState = ((io.input & TRANSC_A_MASK) + (io.input & TRANSC_B_MASK) +
                  (io.input & TRANSC_C_MASK));

    printf("\n%s: %d\n","Trans A Input bit",(io.input & TRANSC_A_MASK));
    printf("\n%s: %d\n","Trans B Input bit",(io.input & TRANSC_B_MASK));
    printf("\n%s: %d\n","Trans C Input bit",(io.input & TRANSC_C_MASK));
    printf("\n%s: %d\n","Trans Input Word",iTranState);

/* Configure capture for Transceiver input trigger */
    returnValue =
        mpiCaptureConfigGet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);

/* Set commutation Offset and expected Hall transition */

    switch (iTranState)
    {

        case 1: /* w/CW rotation: next Hall Region 3, next Hall/Trans. edge B+ */
            {
            iOffset     = 256;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskB;
            captureConfig.trigger.pattern = MEIMotorTransceiverMaskB;
            break;
            }

        case 2: /* w/CW rotation: next Hall Region 6, next Hall/Trans. edge C+ */
            {
            iOffset     =  597;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskC;
            captureConfig.trigger.pattern = MEIMotorTransceiverMaskC;
            break;
            }

        case 3: /* w/CW rotation: next Hall Region 2, next Hall/Trans. edge A- */
            {
            iOffset     =  426;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskA;
            captureConfig.trigger.pattern = 0;
            break;
            }

        case 4: /* w/CW rotation: next Hall Region 5, next Hall/Trans. edge A+ */
            {
            iOffset     =  938;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskA;
            captureConfig.trigger.pattern = MEIMotorTransceiverMaskA;
            break;
            }

        case 5: /* w/CW rotation: next Hall Region 1, next Hall/Trans. edge C- */
            {
            iOffset     =   85;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskC;
            captureConfig.trigger.pattern = 0;
            break;
            }

        case 6: /* w/CW rotation: next Hall Region 4, next Hall/Trans. edge B- */
            {
            iOffset     =  768;
            captureConfig.trigger.mask = MEIMotorTransceiverMaskB;
            captureConfig.trigger.pattern = 0;
            break;
            }

        default:
            {
                printf("\n Incorrect read of Transceivers \n");
                exit(0);
            }
    }

    returnValue =
        mpiCaptureConfigSet(capture,
                            &captureConfig,
                            NULL);
    msgCHECK(returnValue);

    /* Configure Home Event action */
    returnValue =
        mpiMotorEventConfigGet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    eventConfig.action = MPIActionNONE;     /* no event */
    eventConfig.trigger.polarity = TRUE;

    returnValue =
        mpiMotorEventConfigSet(motor,
                               MPIEventTypeHOME,
                               &eventConfig,
                               NULL);
    msgCHECK(returnValue);

    /* Arm the capture */
    returnValue =
        mpiCaptureArm(capture,
                      TRUE);
    msgCHECK(returnValue);

    /* Get motor configuration again */
    returnValue =
        mpiMotorConfigGet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /* Setup commutation with closed-loop control and new Offset */

    commutation->Mode        = MEIXmpCommModeCLOSED_LOOP;
    commutation->Offset      = iOffset;     /* Hall updated Offset */

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /* Read original position for capture (origin) */

    returnValue =
        mpiAxisOriginGet(axis,
                         &origin);
    meiASSERT(returnValue == MPIMessageOK);

    origLatchPosition = origin;

    returnValue =
        mpiAxisOriginSet(axis,
                         origin);
    meiASSERT(returnValue == MPIMessageOK);

#ifdef DumpCommParameters

    /* Display commutation parameters again*/
    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    msgCHECK(returnValue);

    printf("\tCommutation Length C-L = %ld\n",
            motorConfigXmp.Commutation.Length);

    printf("\tCommutation Theta = %ld\n",
            motorConfigXmp.Commutation.Theta);

    if (motorConfigXmp.Commutation.Length != 0) {

        double  phaseAngle;
        long tableIndex;

        tableIndex =
            ((long)(motorConfigXmp.Commutation.Theta *
              motorConfigXmp.Commutation.Scale)) &
             (MEIXmpCOMM_TABLE_SIZE - 1);

        phaseAngle =
             (double)tableIndex * 360.0/
             (double)MEIXmpCOMM_TABLE_SIZE;

        printf("\tPhase angle = %lf degrees\n",
                phaseAngle);
    }

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

#endif

    /* Enable the amplifier */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                            TRUE);
    msgCHECK(returnValue);

    /*
       Stage/motor will servo on position with initial (Hall)
       estimate of commutation position.
       Wait period: 0.5 seconds in this example.
     */

    meiPlatformSleep(500);

    /*
        Implement a closed-loop move to the first Hall transition.
        Upon reaching transition point, latch position and update
        commutation table entry point.

        The move is currently set for +72 elec. degrees. Since the
        commutation max. error is +/- 30 deg based on a 60 deg sector,
        this allows up to 12 electrical degrees of physical mis-alignment
        of the hall sensor.
     */

    returnValue =
        mpiAxisCommandPositionGet(axis,
                                  &command);
    msgCHECK(returnValue);

    trajectory.velocity     = SLOW;
    trajectory.acceleration = SLOW_ACCEL;
    trajectory.deceleration = SLOW_ACCEL;

    params.trapezoidal.trajectory = &trajectory;
    endposition =
        command +
        ((double)(nEncCountPerCycle) / ((double)(N_CYCLES * 5.0)));
    params.trapezoidal.position = &endposition;

    meiPlatformSleep(25);

    /* Start motion */
    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);

    printf("\n Moving...(hit any key after motion completes)...\n\n");

    /* State Machine - Poll capture status, update display, etc. */
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        returnValue =
            mpiCaptureStatus(capture,
                             &captureStatus,
                             NULL);
        msgCHECK(returnValue);

        if (captureStatus.state == MPICaptureStateCAPTURED) {

            latchedPosition = captureStatus.latch[0];

            /* Re-arm position capture */
            returnValue =
                mpiCaptureArm(capture,
                              TRUE);
            msgCHECK(returnValue);
        }
    }

    latchPosChange = latchedPosition - origLatchPosition;

    printf("\n iOffset(orig.) = %d", iOffset);
    iOffset += (long)((((float)commutation->Length)/(N_CYCLES*12) - latchPosChange)*(commutation->Scale));
    printf("\n iOffset(final) = %d\n\n", iOffset);

    /* Get motor configuration again */
    returnValue =
        mpiMotorConfigGet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /* Update commutation Offset based on Hall transition location */

    commutation->Offset      = iOffset;     /* Hall updated Offset */

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /*
        Delete Objects
     */
    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

    returnValue = mpiCaptureDelete(capture);
    msgCHECK(returnValue);

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

    returnValue = mpiFilterDelete(filter);
    msgCHECK(returnValue);

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

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

    return ((int)returnValue);
}

void SetPositionZero(MPIAxis axis)
{
    double  actualPosition;
    double  origin;

    long    returnValue;

    returnValue =
        mpiAxisActualPositionGet(axis,
                                 &actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    returnValue =
        mpiAxisOriginGet(axis,
                         &origin);
    meiASSERT(returnValue == MPIMessageOK);

    actualPosition += origin;

    returnValue =
        mpiAxisOriginSet(axis,
                         actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    meiPlatformSleep(15);

    actualPosition = 0;

    returnValue =
        mpiAxisCommandPositionSet(axis,
                                  actualPosition);
    meiASSERT(returnValue == MPIMessageOK);

    meiPlatformSleep(15);
};


scopen.c -- Transition commutation from close-loop to open-loop mode
/* ScOpen.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.
 */

/*

:Transition commutation from close-loop to open-loop mode

Warning! This Sample Program Sets DAC output level = 1.0 Volt

Check your system's safe continuous level (i.e., check amplifier
current gain and safe motor continuous current level)

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 ScOpen

argMainRENAME(main, ScOpen)
#endif

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

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle  */

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    MPIMotor    motor;  /* motor handle */

    MEIMotorConfig  motorConfigXmp;

    long    returnValue;

    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 >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

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

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

    printf("Going to open loop ...");

    motor =
        mpiMotorCreate(control,
                       motorNumber);
    msgCHECK(mpiMotorValidate(motor));

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

    motorConfigXmp.Commutation.Mode = MEIXmpCommModeOPEN_LOOP;

    /* Warning!!!!! Setting DAC output level = 1.0 Volt */
    motorConfigXmp.Commutation.OutputLevel = (float)3277.0;

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

    /* Delete objects */
    returnValue = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


scstep.c -- Single Axis Sinusoidal Commutation Sample Configuration Program

/* ScStep.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.
 */

/*

:Single Axis Sinusoidal Commutation Sample Configuration Program

  Axis 0 -  Uses Stepper type initialization with a small
            90 (elec.) degree move.  Axis stays in open-loop mode
            with amplifier enabled.

  Note -    #def provided to reverse encoder and DAC phasing.
            Program disables HW Limits, Amp Fault, Home and
            Error Limit.

  Configure the XMP:

            Axis 0  Filter 0   Motor 0

 Note that the commutation configuration parameters will be different
 for your application.  Take particular care in setting the open-loop
 continuous DAC OutputLevel as this must be a safe level for your specific
 drive and motor combination.  Please read the MEI Sinusoidal Commutation
 Documentation.

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 StepSCMain

argMainRENAME(main, StepSC)
#endif

#define AXIS_CNT    (1)

/* Command line arguments and defaults */
long    axisNumber      = 0;
long    motionNumber    = 0;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* option to reverse encoder phasing */
#undef ReverseEncPhasing
/* Option to reverse DAC phasing */
#undef ReverseDACPhasing

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPIAxis     axis;       /* axis handles */
    MPIFilter   filter;     /* filter handles */
    MPIMotor    motor;      /* motor handles  */

    MPIControlConfig    controlConfig;  /* motion controller configuration */
    MPIAxisConfig       axisConfig;     /* axis configuration */
    MPIFilterGain       gain;
    MPIMotorConfig      motorConfig;
    MEIMotorConfig      motorConfigXmp;
    MEIFilterGainPID    *pid;
    MEIXmpCommutationBlock  *commutation;

    MPIMotion       motion; /* Coordinated motion object handles */

    MPIControlType          controlType;
    MPIControlAddress       controlAddress;

    long    returnValue;    /* return value from library */

    long    nEncCountPerCycle = 4096; /* number of encoder counts per motor revolution */
    float   OpenDAC_Level   = (float)3277.0;  /* Open Loop DAC Level where 32767. = 10V) */
    float   N_CYCLES    =       (float)3.0;     /* number of elec. cycles per motor rev. */

#if defined(ReverseDACPhasing)
    long    dacCount;
    long    dacNumber[MPIMotorDacCountMAX];
    long    number;
#endif

    float   inPositionLimit = (float)1.0e10;

    long    argIndex, i;

    /* 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) ||
        (axisNumber   >= MEIXmpMAX_Axes + AXIS_CNT) ||
        (motionNumber >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_CNT,
                            MEIXmpMAX_MSs - 1);
        exit(MPIMessageARG_INVALID);
    }

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

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

    /*
       Configure motion controller
       Set Sample Rate = 2 kHz
       Configure for commutation B phase DACs and ADCs
     */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    controlConfig.sampleRate = 2000;

    /*
        When supporting commutation,
        Cmd and Aux DACs must be enabled.
        Enabling the same number of Cmd and Aux DACs as there are motors.
     */
    controlConfig.cmdDacCount = controlConfig.motorCount;
    controlConfig.auxDacCount = controlConfig.motorCount;

    /* Configure required number of A/D */
    controlConfig.adcCount = 8;

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    /* Create axis, filter and motor controller objects */
    axis =
        mpiAxisCreate(control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(axis));

    filter =
        mpiFilterCreate(control,
                      axisNumber);
    msgCHECK(mpiFilterValidate(filter));

    motor =
        mpiMotorCreate(control,
                      axisNumber);
    msgCHECK(mpiMotorValidate(motor));

    /* Disable the amplifier */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                            FALSE);
    msgCHECK(returnValue);

    /*   Configure axis  */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    /* Set inPositionLimit */
    axisConfig.inPosition.tolerance.positionFine = inPositionLimit;

    returnValue =
        mpiAxisConfigSet(axis,
                        &axisConfig,
                        NULL);
    msgCHECK(returnValue);

    /* Configure Motor */
    returnValue =
        mpiMotorConfigGet(motor,
                         &motorConfig,
                         &motorConfigXmp);
    msgCHECK(returnValue);

    /*
       Disable limit error, home, amp fault & H/W Limits
       Set encoder phase
     */

    /* Disable limit error */
    motorConfig.event[MPIEventTypeLIMIT_ERROR].action           = MPIActionNONE;
    motorConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error    = (float)50000;

    /* Disable home event */
    motorConfig.event[MPIEventTypeHOME].action  = MPIActionNONE;

    /* Disable amp fault event */
    motorConfig.event[MPIEventTypeAMP_FAULT].action = MPIActionNONE;

    /* Disable neg. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_NEG].action  = MPIActionNONE;

    /* Disable pos. HW limit event */
    motorConfig.event[MPIEventTypeLIMIT_HW_POS].action  = MPIActionNONE;

    /*
       Set encoder phase:

       0 - for normal
       1 - for reversed
     */

#ifdef ReverseEncPhasing
    motorConfig.encoderPhase = 1;
#else
    motorConfig.encoderPhase = 0;
#endif

    /* Setup commutation  */
    commutation = &motorConfigXmp.Commutation;

    /* Motor Controller commutation parameters */
    commutation->Mode        = MEIXmpCommModeOPEN_LOOP;
    commutation->Length      = nEncCountPerCycle;
    commutation->Scale       = (float)MEIXmpCOMM_TABLE_SIZE * N_CYCLES /
                               (float)commutation->Length;
    commutation->PhaseDelta  = MEIXmpCOMM_120DEGREES;
    commutation->OutputLevel = (float)0.0;   /* level will be ramped after enable */
    commutation->Offset      = (long)0;

#if defined(ReverseDACPhasing)
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseINVERTED;
#else
    motorConfigXmp.Dac.Phase = MEIXmpDACPhaseNORMAL;
#endif

    /* Set configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    /* Get current configuration */
    returnValue =
        mpiFilterGainGet(filter,
                        MEIFilterGainIndexDEFAULT,
                        &gain);
    msgCHECK(returnValue);

    pid = (MEIFilterGainPID *)&gain;

    /* Filter Controller control parameters */
    pid->gain.proportional          = (float)100.;
    pid->gain.integral              = (float)0.0;
    pid->gain.derivative            = (float)400.;
    pid->feedForward.velocity       = (float)0.0;
    pid->feedForward.acceleration   = (float)0.0;
    pid->feedForward.friction       = (float)0.0;
    pid->integrationMax.moving      = (float)0.0;
    pid->integrationMax.rest        = (float)0.0;
    pid->output.limit               = (float)32767.0;
    pid->output.offset              = (float)0.0;

    /* Set filter configuration  */
    returnValue =
        mpiFilterGainSet(filter,
                        MEIFilterGainIndexDEFAULT,
                        &gain);
    msgCHECK(returnValue);

    /*
       Create a Motion Object and append an Axis
       Note 1 - separate axis appends will be required for coordinated motion
       Note 2 - Axis Map does not take effect until motion is commanded
     */
    motion =
         mpiMotionCreate(control,
                         motionNumber,
                         axis);
    msgCHECK(mpiMotionValidate(motion));

    /*  Clear out any previous errors */
    returnValue =
            mpiMotionAction(motion,MPIActionRESET);
    msgCHECK(returnValue);

    /*  Immediately send Map to controller  */
    returnValue =
        mpiMotionAction(motion,
                        (MPIAction)MEIActionMAP);
    msgCHECK(returnValue);

    /*  Enable the amplifier */
    returnValue =
        mpiMotorAmpEnableSet(motor,
                            TRUE);
    msgCHECK(returnValue);

    /*
        DAC output will be ramped and stage will be pulled to a magnetic pole.
        Next, delay for stage to settle.  Implement outbound move,delay, then
        proceed with inbound move and delay.
     */

    returnValue =
        mpiMotorConfigGet(motor,
                        &motorConfig,
                        &motorConfigXmp);
    msgCHECK(returnValue);

    for(i= 1; i <= 100; i++){

        commutation->OutputLevel = (float)(i)*((OpenDAC_Level)/((float)100.0));

        /* Set configuration */
        returnValue =
            mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
        msgCHECK(returnValue);

        meiPlatformSleep(30);
    }

    meiPlatformSleep(1000);

    /* Motor outbound move */

    for(i= 1; i <= 100; i++){

        commutation->Offset      = (long)(i*2.56);

        /* Set configuration */
        returnValue =
            mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
        msgCHECK(returnValue);

        meiPlatformSleep(30);

    }

    meiPlatformSleep(1000);

    /* Motor return move */
    for(i= 1; i <= 100; i++){

        commutation->Offset      = (long)(256 - (i*2.56));

            /* Set configuration */
        returnValue =
            mpiMotorConfigSet(motor,
                        &motorConfig,
                        &motorConfigXmp);
        msgCHECK(returnValue);

        meiPlatformSleep(30);
    }

    meiPlatformSleep(1000);

    /* Delete Objects */
    returnValue = mpiMotionDelete(motion);
    msgCHECK(returnValue);

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

    returnValue = mpiFilterDelete(filter);
    msgCHECK(returnValue);

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

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

    return ((int)returnValue);
}


scview.c -- Display commutation parameters
/* ScView.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.
 */

/*

:Display commutation parameters

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    ScView

argMainRENAME(main, ScView)
#endif

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

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

    {   NULL,       ArgTypeINVALID, NULL,   }
};

char *modeLabel[] = {
    "MEIXmpCommModeNONE",
    "MEIXmpCommModeCLOSED_LOOP",
    "MEIXmpCommModeOPEN_LOOP",
    "MEIXmpCommModeSIMULATE",
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;        /* motion controller handle */
    MPIMotor        motor;          /* motor */
    MEIMotorConfig  motorConfig;    /* motor config structure */

    long    returnValue;    /* return value from library */

    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 >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Motors - 1);
        exit(MPIMessageARG_INVALID);
    }

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

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

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

    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfig);
    msgCHECK(returnValue);

    printf("Motor %ld:\n",
            motorNumber);

    printf("\tCommutation Mode = %ld (%s)\n",
            motorConfig.Commutation.Mode,
            modeLabel[motorConfig.Commutation.Mode]);

    printf("\tCommutation Length = %ld\n",
            motorConfig.Commutation.Length);

    printf("\tCommutation Scale = %f\n",
            motorConfig.Commutation.Scale);

    printf("\tCommutation Phase Delta = %ld\n",
            motorConfig.Commutation.PhaseDelta);

    printf("\tCommutation Theta = %ld\n",
            motorConfig.Commutation.Theta);

    if (motorConfig.Commutation.Length != 0) {

        double  phaseAngle;
        long tableIndex;

        tableIndex =
            ((long)(motorConfig.Commutation.Theta *
              motorConfig.Commutation.Scale)) &
             (MEIXmpCOMM_TABLE_SIZE - 1);

        phaseAngle =
             (double)tableIndex * 360.0/
             (double)MEIXmpCOMM_TABLE_SIZE;

        printf("\tPhase angle = %lf degrees\n",
                phaseAngle);
    }

    /* Delete objects */
    returnValue = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


seq1.c -- Perform a repeated multi-axis motion command sequence
/* seq1.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/seq1.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a repeated multi-axis motion command sequence

This sample program creates a program sequencer that will generate a multi-axis
 motion beween two points.  The program sequencer waits for the motion to
 complete in between moves.  After commanding the two motions the program
 sequencer loops back to the beginning of the motion command sequence, and
 repeats the motion until the user presses a key.  The program execution is
 handled entirely on the controller, with no host computer intervention.  The
 motion can be viewed by the Motion Console and Motion Scope utilities.

The XMP program sequencer controls the execution of a single command or a
 series of commands on the XMP controller.  The program sequencer provides the
 ability to execute programs directly on the XMP controller without host
 intervention.  Examples of individual commands that can be executed by the
 program sequencer are motion, looping, conditional branching, computation,
 reading and writing of memory, time delays, waiting for conditions, setting
 inputs/outputs, and generation of events.  This rich command set provides
 capability similar to, and beyond, that provided by Programmable Logic
 Controller (PLC) programs.

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    seq1Main

argMainRENAME(main, seq1)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
long            sequenceNumber  = 0;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",        ArgTypeLONG,    &axisNumber[0],     },
    {   "-motion",      ArgTypeLONG,    &motionNumber,      },
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,    },
    {   "-type",        ArgTypeLONG,    &motionType,        },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 200000.0, 0.0,        },
    { 0.0,      200000.0,   },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
};

/* Motion Parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

/* 2 => START + MOTION_DONE 1 => BRANCH */
MPICommand  CommandTable[(MOTION_COUNT * 2) + 1];
#define COMMAND_COUNT   (sizeof(CommandTable) / sizeof(MPICommand))

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIMotion   motion;             /* motion handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handles */
    MPISequence sequence;           /* sequence handle */

    MPICommandParams    commandParams;  /* command parameters */

    long    returnValue;    /* return value from library */

    long    commandIndex;   /* CommandTable[] index */
    long    index;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0]  > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber   >= MEIXmpMAX_MSs) ||
        (sequenceNumber >= MEIXmpMAX_PSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_PSs - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

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

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

    /* Create motion axis list */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          -1);
    msgCHECK(mpiSequenceValidate(sequence));

    /* CommandTable[commandIndex] */
    commandIndex = 0;

    /* Create motion Commands */
    for (index = 0; index < MOTION_COUNT; index++) {
        MPIMotionParams *motionParams;

        /* mpiMotionStart(motion, type, params); */
        commandParams.motion.motionCommand  = MPICommandMotionSTART;
        commandParams.motion.motion         = motion;
        commandParams.motion.type           = motionType;

        motionParams = &commandParams.motion.params;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams->sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams->trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams->velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeMOTION,
                             &commandParams,
                             (commandIndex == 0) ? "First" : NULL);

        returnValue = mpiCommandValidate(CommandTable[commandIndex]);
        msgCHECK(returnValue);

        commandIndex++;

        commandParams.waitEvent.handle  = motion;
        commandParams.waitEvent.oper    = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.waitEvent.mask);
        mpiEventMaskSET(commandParams.waitEvent.mask, MPIEventTypeMOTION_DONE);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_EVENT,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;
    }

    /* Branch to the first command of the sequence */
    commandParams.branch.label      = "First";  /* First command */
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Create sequence command list */
    returnValue =
        mpiSequenceCommandListSet(sequence,
                                  commandIndex,
                                  CommandTable);
    msgCHECK(returnValue);

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);
    msgCHECK(returnValue);

    meiPlatformConsole("Press any key to stop sequence\n");
    meiPlatformKey(MPIWaitFOREVER);

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    /* Delete Objects */
    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

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

    return ((int)returnValue);
}


seq2.c -- Perform a repeated multi-axis motion command sequence, wait for an I/O bit
/* seq2.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/seq2.c 13    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a repeated multi-axis motion command sequence, wait for an I/O bit

This sample program creates a program sequencer that will generate a multi-axis
 motion beween two points.  The program sequencer waits for the motion to
 complete in between moves.  After commanding the two motions the program
 sequencer waits for a transceiver I/O bit to change state (defined by
 TRANSCEIVER_ID and TRIGGER_STATE at the top of the program).  Then the sequence
 loops back to the beginning of the motion command sequence, and repeats the
 motion until the user presses a key.  The program execution is handled entirely
 on the controller, with no host computer intervention.  The motion can be
 viewed by the Motion Console and Motion Scope utilities.

The XMP program sequencer controls the execution of a single command or a
 series of commands on the XMP controller.  The program sequencer provides the
 ability to execute programs directly on the XMP controller without host
 intervention.  Examples of individual commands that can be executed by the
 program sequencer are motion, looping, conditional branching, computation,
 reading and writing of memory, time delays, waiting for conditions, setting
 inputs/outputs, and generation of events.  This rich command set provides
 capability similar to, and beyond, that provided by Programmable Logic
 Controller (PLC) programs.

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    seq2Main

argMainRENAME(main, seq2)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Define the transceiver to wait for in between motion sequences */
#define TRANSCEIVER_ID  (MEIMotorTransceiverIdA)  /* A, B, or C */

/* Define the trigger value for the transceiver,
   MPICommandOperatorBIT_SET or MPICommandOperatorBIT_CLEAR
*/
#define TRIGGER_STATE   (MPICommandOperatorBIT_SET)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
long            motorNumber     = 0;
long            sequenceNumber  = 0;
long            sequenceSize    = -1;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",        ArgTypeLONG,    &axisNumber[0],     },
    {   "-motion",      ArgTypeLONG,    &motionNumber,      },
    {   "-motor",       ArgTypeLONG,    &motorNumber,       },
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,    },
    {   "-size",        ArgTypeLONG,    &sequenceSize,      },
    {   "-type",        ArgTypeLONG,    &motionType,        },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  0.0,        },
    { 0.0,      20000.0,    },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
};

/* motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

                        /* 3 => START + MOTION_DONE + I/O 1 => BRANCH */
MPICommand  CommandTable[(MOTION_COUNT * 3) + 1];
#define COMMAND_COUNT   (sizeof(CommandTable) / sizeof(MPICommand))

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIMotion   motion;             /* motion handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handles */
    MPIMotor    motor;              /* motor handle */

    MPISequence sequence;           /* sequence handle */

    MPICommandParams    commandParams;  /* command parameters */

    long    returnValue;    /* return value from library */

    long    commandIndex;   /* CommandTable[] index */
    long    index;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0]  > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber   >= MEIXmpMAX_MSs) ||
        (motorNumber    >= MEIXmpMAX_Motors) ||
        (sequenceNumber >= MEIXmpMAX_PSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[-size # (%d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1,
                            MEIXmpMAX_PSs - 1,
                            sequenceSize,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create motion object for MS number */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

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

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

    /* Create motion axis list */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

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

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          sequenceSize);
    msgCHECK(mpiSequenceValidate(sequence));

    /* CommandTable[commandIndex] */
    commandIndex = 0;

    /* Create motion Commands */
    for (index = 0; index < MOTION_COUNT; index++) {
        MPIMotionParams *motionParams;

        /* mpiMotionStart(motion, type, params); */
        commandParams.motion.motionCommand  = MPICommandMotionSTART;
        commandParams.motion.motion         = motion;
        commandParams.motion.type           = motionType;

        motionParams = &commandParams.motion.params;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams->sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams->trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams->velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeMOTION,
                             &commandParams,
                             (commandIndex == 0) ? "First" : NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        commandParams.waitEvent.handle  = motion;
        commandParams.waitEvent.oper    = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.waitEvent.mask);
        mpiEventMaskSET(commandParams.waitEvent.mask, MPIEventTypeMOTION_DONE);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_EVENT,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        /* while (mpiControlUserIoGet(control, &io), (io.input[0] & mask) == 0); */
        commandParams.waitIO.type           = MPIIoTypeMOTOR;
        commandParams.waitIO.source.motor   = motor;
        commandParams.waitIO.oper           = TRIGGER_STATE;
        commandParams.waitIO.mask           = 0x1 << TRANSCEIVER_ID;    /* bit 0 */

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_IO,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;
    }

    /* Branch to the first command of the sequence */
    commandParams.branch.label      = "First";  /* First command */
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Create sequence command list */
    returnValue =
        mpiSequenceCommandListSet(sequence,
                                  commandIndex,
                                  CommandTable);
    msgCHECK(returnValue);

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);

    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(2);
    }

    meiPlatformConsole("Press any key to stop sequence\n");
    meiPlatformKey(MPIWaitFOREVER);

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

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

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

    return ((int)returnValue);
}


seq3.c -- Wait for an I/O bit to Toggle Before Commanding Motion with a Sequencer
/* seq3.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/seq3.c 12    7/23/01 2:36p Kevinh $";
#endif

/*

:Wait for an I/O bit to Toggle Before Commanding Motion with a Sequencer

Wait for an I/O bit between moves.
This program will wait for motor 0's Transceiver A to go high.
Use an event manager to handle flow control.

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    seq3Main

argMainRENAME(main, seq3)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
long            motorNumber     = 0;
long            sequenceNumber  = 0;
long            sequenceSize    = -1;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",        ArgTypeLONG,    &axisNumber[0],     },
    {   "-motion",      ArgTypeLONG,    &motionNumber,      },
    {   "-motor",       ArgTypeLONG,    &motorNumber,       },
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,    },
    {   "-size",        ArgTypeLONG,    &sequenceSize,      },
    {   "-type",        ArgTypeLONG,    &motionType,        },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  0.0,        },
    { 0.0,      20000.0,    },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
};

/* motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

                        /* 4 => START + MOTION_DONE + I/O + EVENT 1 => BRANCH */
MPICommand  CommandTable[(MOTION_COUNT * 4) + 1];
#define COMMAND_COUNT   (sizeof(CommandTable) / sizeof(MPICommand))

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIMotion   motion;             /* motion handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handles */
    MPIMotor    motor;              /* motor handle */

    MPISequence sequence;           /* sequence handle */
    MPIEventMgr eventMgr;           /* event manager handle */

    Service service;

    MPICommandParams    commandParams;  /* command parameters */

    long    returnValue;    /* return value from library */

    long    commandIndex;   /* CommandTable[] index */

    long    index;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0]  > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber   >= MEIXmpMAX_MSs) ||
        (motorNumber    >= MEIXmpMAX_Motors) ||
        (sequenceNumber >= MEIXmpMAX_PSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[-size # (%d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1,
                            MEIXmpMAX_PSs - 1,
                            sequenceSize,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create motion object for MS number */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Create axis object for X_AXIS number */
    axis[0] =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axis[0]));

    /* Create axis object for Y_AXIS number */
    axis[1] =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axis[1]));

    /* Create motion axis list */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

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

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          sequenceSize);
    msgCHECK(mpiSequenceValidate(sequence));

#if defined(_DEBUG)
    returnValue =
        meiObjectTraceSet(sequence,
                          MEISequenceTraceLOAD);
    msgCHECK(returnValue);
#endif

    /* CommandTable[commandIndex] */
    commandIndex = 0;

    /* Create motion Commands */
    for (index = 0; index < MOTION_COUNT; index++) {
        MPIMotionParams *motionParams;

        /* mpiMotionStart(motion, type, params); */
        commandParams.motion.motionCommand  = MPICommandMotionSTART;
        commandParams.motion.motion         = motion;
        commandParams.motion.type           = motionType;

        motionParams = &commandParams.motion.params;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams->sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams->trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams->velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeMOTION,
                             &commandParams,
                             (commandIndex == 0) ? "First" : NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        commandParams.waitEvent.handle  = motion;
        commandParams.waitEvent.oper    = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.waitEvent.mask);
        mpiEventMaskSET(commandParams.waitEvent.mask, MPIEventTypeMOTION_DONE);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_EVENT,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        commandParams.branchEvent.label     = NULL;
        commandParams.branchEvent.handle    = motion;
        commandParams.branchEvent.oper      = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.branchEvent.mask);
        mpiEventMaskMOTOR(commandParams.branchEvent.mask);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeBRANCH_EVENT,
                             &commandParams,
                             NULL);

        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        /* while (mpiControlUserIoGet(control, &io), (io.input[0] & mask) == 0); */
        commandParams.waitIO.type           = MPIIoTypeMOTOR;
        commandParams.waitIO.source.motor   = motor;

        commandParams.waitIO.oper           = MPICommandOperatorBIT_SET;
        commandParams.waitIO.mask           = 0x1 << 0; /* bit 0 */

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_IO,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;
    }

    /* Branch to the first command of the sequence */
    commandParams.branch.label      = "First";  /* First command */
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Create sequence command list */
    returnValue =
        mpiSequenceCommandListSet(sequence,
                                  commandIndex,
                                  CommandTable);
    msgCHECK(returnValue);

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

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

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);

    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(2);
    }

    meiPlatformConsole("Press any key to stop sequence\n");
    meiPlatformKey(MPIWaitFOREVER);

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

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

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

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

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

    return ((int)returnValue);
}


seq4.c -- Perform a repeated multi-axis motion sequence, wait for I/O, & monitor location
/* seq4.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/seq4.c 20    7/23/01 2:36p Kevinh $";
#endif

/*

:Perform a repeated multi-axis motion sequence, wait for I/O, & monitor location

This sample program creates a program sequencer that will generate a multi-axis
 motion beween two points.  The program sequencer waits for the motion to
 complete in between moves.  After commanding the two motions the program
 sequencer waits for a transceiver I/O bit to change state (defined by
 TRANSCEIVER_WAIT_ID and TRIGGER_STATE at the top of the program).  Then the
 sequence loops back to the beginning of the motion command sequence, and
 repeats the motion until the user presses a key.

In addition there is a second program sequencer that monitors the position of
 the X and Y axes.  If their positions fall within a rectangle, defined by the
 position array, then a transceiver bit is set (defined by TRANSCEIVER_SET_ID).
 This can be used to signal process or inspection equipment to begin their
 actions.

The program execution is handled entirely on the controller, with no host
 computer intervention.  The motion can be viewed by the Motion Console and
 Motion Scope utilities.

The XMP program sequencer controls the execution of a single command or a
 series of commands on the XMP controller.  The program sequencer provides the
 ability to execute programs directly on the XMP controller without host
 intervention.  Examples of individual commands that can be executed by the
 program sequencer are motion, looping, conditional branching, computation,
 reading and writing of memory, time delays, waiting for conditions, setting
 inputs/outputs, and generation of events.  This rich command set provides
 capability similar to, and beyond, that provided by Programmable Logic
 Controller (PLC) programs.

 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 <math.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    seq4Main

argMainRENAME(main, seq4)
#endif

#define MOTION_COUNT    (2)
#define AXIS_COUNT      (2)

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0, 1, };
long            motionNumber    = 0;
long            motorNumber     = 0;
long            sequenceNumber  = 0;
long            sequenceSize    = 128;
MPIMotionType   motionType      = MPIMotionTypeTRAPEZOIDAL;

Arg argList[] = {
    {   "-axis",        ArgTypeLONG,    &axisNumber[0],     },
    {   "-motion",      ArgTypeLONG,    &motionNumber,      },
    {   "-motor",       ArgTypeLONG,    &motorNumber,       },
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,    },
    {   "-size",        ArgTypeLONG,    &sequenceSize,      },
    {   "-type",        ArgTypeLONG,    &motionType,        },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT][AXIS_COUNT] = {
    { 20000.0,  0.0,        },
    { 0.0,      20000.0,    },
};

MPITrajectory trajectory[MOTION_COUNT][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      100000.0,   100000.0,   50.0,   },
        { 10000.0,      100000.0,   100000.0,   50.0,   },
    },
};

/* motion parameters */

MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

typedef enum {
    ExternalEventSEQUENCE_DONE,
} ExternalEvent;

                        /* 4 => START + MOTION_DONE + I/O + EVENT */
                        /* 2 => EXTERNAL_EVENT + BRANCH */
MPICommand  CommandTable[(MOTION_COUNT * 4) + 2];
#define COMMAND_COUNT   (sizeof(CommandTable) / sizeof(MPICommand))

#define IO_CONFIG   (MEIMotorTransceiverConfigOUTPUT) /* INPUT or OUTPUT  */
#define INVERT_BIT  (FALSE)

/* Toggle the transceiver associated with the motor.  In this case, toggle
   transceiver B
*/
#define TRANSCEIVER_SET_ID  (MEIMotorTransceiverIdB)  /* A, B, or C, */
/* Define the transceiver to wait for in between motion sequences */
#define TRANSCEIVER_WAIT_ID (MEIMotorTransceiverIdA)  /* A, B, or C */

/* Define the trigger value for the transceiver,
   MPICommandOperatorBIT_SET or MPICommandOperatorBIT_CLEAR
*/
#define TRIGGER_STATE   (MPICommandOperatorBIT_SET)

MPISequence
    monitorPosition(MPIControl  control,
                    MPIMotor    motor,
                    MPIAxis     axisX,
                    MPIAxis     axisY,
                    double      *limitX,
                    double      *limitY);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;            /* motion controller handle */
    MPIMotion   motion;             /* motion handle */
    MPIAxis     axis[AXIS_COUNT];   /* axis handles */
    MPIMotor    motor;              /* motor handle */

    MPISequence sequence;           /* sequence handle */
    MPISequence sequenceMonitor;    /* sequence handle */
    MPINotify   notify;             /* notification handle */
    MPIEventMgr eventMgr;           /* event manager handle */

    MPIEventMask    eventMask;

    Service service;

    MPICommandType      type;           /* command type */
    MPICommandParams    commandParams;  /* command parameters */

    double  limitX[AXIS_COUNT];
    double  limitY[AXIS_COUNT];
    double  limit;

    long    returnValue;    /* return value from library */

    long    commandIndex;   /* CommandTable[] index */
    long    index;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (axisNumber[0]  > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber   >= MEIXmpMAX_MSs) ||
        (motorNumber    >= MEIXmpMAX_Motors) ||
        (sequenceNumber >= MEIXmpMAX_PSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[-size # (%d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - AXIS_COUNT,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1,
                            MEIXmpMAX_PSs - 1,
                            sequenceSize,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

    axisNumber[1] = axisNumber[0] + 1;

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

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

    /* Create motion object for MS number */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Create axis object for X_AXIS number */
    axis[0] =
        mpiAxisCreate(control,
                      axisNumber[0]);
    msgCHECK(mpiAxisValidate(axis[0]));

    /* Create axis object for Y_AXIS number */
    axis[1] =
        mpiAxisCreate(control,
                      axisNumber[1]);
    msgCHECK(mpiAxisValidate(axis[1]));

    /* Create motion axis list */
    returnValue =
        mpiMotionAxisListSet(motion,
                             AXIS_COUNT,
                             axis);
    msgCHECK(returnValue);

    /* Request notification of all events from motion */
    mpiEventMaskCLEAR(eventMask);
    mpiEventMaskALL(eventMask);
    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);
    msgCHECK(returnValue);

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

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          sequenceSize);
    msgCHECK(mpiSequenceValidate(sequence));

#if defined(_DEBUG)
    returnValue =
        meiObjectTraceSet(sequence,
                          MEISequenceTraceLOAD);
    msgCHECK(returnValue);
#endif

    /* Request notification of all events from sequence */
    returnValue =
        mpiSequenceEventNotifySet(sequence,
                                  eventMask,
                                  NULL);
    msgCHECK(returnValue);

    /* CommandTable[commandIndex] */
    commandIndex = 0;

    /* Create motion Commands */
    for (index = 0; index < MOTION_COUNT; index++) {
        MPIMotionParams *motionParams;

        /* mpiMotionStart(motion, type, params); */
        type = MPICommandTypeMOTION;

        commandParams.motion.motionCommand  = MPICommandMotionSTART;
        commandParams.motion.motion         = motion;
        commandParams.motion.type           = motionType;

        motionParams = &commandParams.motion.params;

        switch (motionType) {
            case MPIMotionTypeS_CURVE: {
                motionParams->sCurve = sCurve[index];
                break;
            }
            case MPIMotionTypeTRAPEZOIDAL: {
                motionParams->trapezoidal = trapezoidal[index];
                break;
            }
            case MPIMotionTypeVELOCITY: {
                motionParams->velocity = velocity[index];
                break;
            }
            default: {
                meiASSERT(FALSE);
                break;
            }
        }

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(type,
                             &commandParams,
                             (commandIndex == 0) ? "First" : NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        commandParams.waitEvent.handle  = motion;
        commandParams.waitEvent.oper    = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.waitEvent.mask);
        mpiEventMaskSET(commandParams.waitEvent.mask, MPIEventTypeMOTION_DONE);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_EVENT,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        commandParams.branchEvent.label     = NULL;
        commandParams.branchEvent.handle    = motion;
        commandParams.branchEvent.oper      = MPICommandOperatorBIT_SET;
        mpiEventMaskCLEAR(commandParams.branchEvent.mask);
        mpiEventMaskMOTOR(commandParams.branchEvent.mask);

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeBRANCH_EVENT,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;

        /* while (mpiControlUserIoGet(control, &io), (io.input[0] & mask) == 0); */
        commandParams.waitIO.type           = MPIIoTypeMOTOR;
        commandParams.waitIO.source.motor   = motor;
        commandParams.waitIO.oper           = TRIGGER_STATE;
        commandParams.waitIO.mask           = 0x1 << TRANSCEIVER_WAIT_ID;   /* bit 0 */

        /* Create Command */
        CommandTable[commandIndex] =
            mpiCommandCreate(MPICommandTypeWAIT_IO,
                             &commandParams,
                             NULL);
        msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

        commandIndex++;
    }

    /* MPIEventTypeEXTERNAL */
    commandParams.event.value = ExternalEventSEQUENCE_DONE;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeEVENT,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Branch to the first command of the sequence */
    commandParams.branch.label      = "First";  /* First command */
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    /* Create Command */
    CommandTable[commandIndex] =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(CommandTable[commandIndex]));

    commandIndex++;

    /* Create sequence command list */
    returnValue =
        mpiSequenceCommandListSet(sequence,
                                  commandIndex,
                                  CommandTable);
    msgCHECK(returnValue);

    /* Create event notification object */
    notify =
        mpiNotifyCreate(eventMask,      /* Notify of all MPI events */
                        MPIHandleVOID); /* Notify from all sources */
    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);

    limit =
        fabs(position[0][0] - position[1][0]) /
        (AXIS_COUNT + 2);

    if (position[0][0] < position[1][0]) {
        limitX[0] = position[0][0] + limit;
        limitX[1] = position[1][0] - limit;
    }
    else {
        limitX[0] = position[1][0] + limit;
        limitX[1] = position[0][0] - limit;
    }

    limit =
        fabs(position[0][1] - position[1][1]) /
        (AXIS_COUNT + 2);

    if (position[0][1] < position[1][1]) {
        limitY[0] = position[0][1] + limit;
        limitY[1] = position[1][1] - limit;
    }
    else {
        limitY[0] = position[1][1] + limit;
        limitY[1] = position[0][1] - limit;
    }

    sequenceMonitor =
        monitorPosition(control,
                        motor,
                        axis[0],
                        axis[1],
                        limitX,
                        limitY);
    msgCHECK(mpiSequenceValidate(sequenceMonitor));

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);

    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(2);
    }

    meiPlatformConsole("Press any key to stop sequence\n");

    while (returnValue == MPIMessageOK) {
        MPIEventStatus  status;

        returnValue =
            mpiNotifyEventWait(notify,
                               &status,
                               MPIWaitFOREVER);

        if (returnValue == MPIMessageOK) {
            MEIEventStatusInfo  *info;

            info = (MEIEventStatusInfo *)status.info;

            switch (status.type) {
                case MPIEventTypeNONE: {    /* ignore */
                    meiPlatformConsole("No event ...\n");
                    break;
                }
                case MPIEventTypeAMP_FAULT:
                case MPIEventTypeHOME:
                case MPIEventTypeLIMIT_ERROR:
                case MPIEventTypeLIMIT_HW_NEG:
                case MPIEventTypeLIMIT_HW_POS:
                case MPIEventTypeLIMIT_SW_NEG:
                case MPIEventTypeLIMIT_SW_POS: {    /* error */
                    long    number;

                    number = info->type.number;

                    meiPlatformConsole("Event %d on motor #%d\n",
                                        status.type,
                                        number);

                    break;
                }
                case MPIEventTypeMOTION_DONE: {
                    meiPlatformConsole("Motion done\n");
                    break;
                }
                case MPIEventTypeEXTERNAL: {
                    switch (info->type.value) {
                        case ExternalEventSEQUENCE_DONE: {
                            meiPlatformConsole("Sequence done\n");
                            break;
                        }
                        default: {
                            meiPlatformConsole("Unknown external event: %d\n",
                                                info->type.value);
                            break;
                        }
                    }

                    break;
                }
                default: {
                    break;
                }
            }
        }

        if (returnValue == MPIMessageOK) {
            if (meiPlatformKey(MPIWaitPOLL) >= 0) {
                break;
            }
        }
    }

    meiPlatformConsole("Exiting ... returnValue 0x%x: %s\n",
                        returnValue,
                        mpiMessage(returnValue, NULL));

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequenceMonitor);
    msgCHECK(returnValue);

    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequenceMonitor);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    for (index = 0; index < AXIS_COUNT; index++) {
        returnValue = mpiAxisDelete(axis[index]);
        msgCHECK(returnValue);
    }

    returnValue = mpiMotorDelete(motor);
    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);
}

MPISequence
    monitorPosition(MPIControl  control,
                    MPIMotor    motor,
                    MPIAxis     axisX,
                    MPIAxis     axisY,
                    double      *limitX,
                    double      *limitY)
{
    MPISequence         sequence;
    MPICommand          command;
    MEIMotorConfig      motorConfigXmp;  /* contains transceiver configuration */
    MPICommandParams    commandParams;

    long        numberX;
    long        numberY;
    MEIXmpAxis  *xmpAxisX;
    MEIXmpAxis  *xmpAxisY;
    long        *positionX;
    long        *positionY;

    long    returnValue;

    returnValue =
        mpiMotorConfigGet(motor,
                          NULL,
                          &motorConfigXmp);
    meiASSERT(returnValue == MPIMessageOK);

    motorConfigXmp.Transceiver[TRANSCEIVER_SET_ID].Config = IO_CONFIG;
    motorConfigXmp.Transceiver[TRANSCEIVER_SET_ID].Invert = INVERT_BIT;

    returnValue =
        mpiMotorConfigSet(motor,
                          NULL,
                          &motorConfigXmp);
    meiASSERT(returnValue == MPIMessageOK);

    returnValue =
        mpiAxisNumber(axisX,
                      &numberX);
    msgCHECK(returnValue);

    returnValue =
        mpiAxisNumber(axisY,
                      &numberY);
    msgCHECK(returnValue);

    returnValue =
        mpiAxisMemory(axisX,
                      (void **)&xmpAxisX);
    msgCHECK(returnValue);

    returnValue =
        mpiAxisMemory(axisY,
                      (void **)&xmpAxisY);
    msgCHECK(returnValue);

    positionX = &xmpAxisX->ActualPosition;
    positionY = &xmpAxisY->ActualPosition;

    sequence =
        mpiSequenceCreate(control,
                          -1,
                          8);
    msgCHECK(mpiSequenceValidate(sequence));

    commandParams.branch.label              = "IoBitClear";
    commandParams.branch.expr.address.l     = positionX;
    commandParams.branch.expr.oper          = MPICommandOperatorLESS;
    commandParams.branch.expr.by.value.l    = (long)limitX[0];

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         "First");
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.branch.label              = "IoBitClear";
    commandParams.branch.expr.address.l     = positionX;
    commandParams.branch.expr.oper          = MPICommandOperatorGREATER;
    commandParams.branch.expr.by.value.l    = (long)limitX[1];

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.branch.label              = "IoBitClear";
    commandParams.branch.expr.address.l     = positionY;
    commandParams.branch.expr.oper          = MPICommandOperatorLESS;
    commandParams.branch.expr.by.value.l    = (long)limitY[0];

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.branch.label              = "IoBitClear";
    commandParams.branch.expr.address.l     = positionY;
    commandParams.branch.expr.oper          = MPICommandOperatorGREATER;
    commandParams.branch.expr.by.value.l    = (long)limitY[1];

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.computeIO.type            = MPIIoTypeMOTOR;
    commandParams.computeIO.source.motor    = motor;
    commandParams.computeIO.oper            = MPICommandOperatorOR;
    commandParams.computeIO.mask            = 0x1 << TRANSCEIVER_SET_ID;    /* Set bit 1 */

    command =
        mpiCommandCreate(MPICommandTypeCOMPUTE_IO,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.branch.label      = "First";
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.computeIO.type            = MPIIoTypeMOTOR;
    commandParams.computeIO.source.motor    = motor;
    commandParams.computeIO.oper            = MPICommandOperatorAND;
    commandParams.computeIO.mask            = ~(0x1 << TRANSCEIVER_SET_ID); /* Clear bit 1 */

    command =
        mpiCommandCreate(MPICommandTypeCOMPUTE_IO,
                         &commandParams,
                         "IoBitClear");
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    commandParams.branch.label      = "First";
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &commandParams,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);
    msgCHECK(returnValue);

    return (sequence);
}


seqKill.c -- Program Sequence to monitor an I/O bit and abort all axes when active.
/* seqkill.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/seqkill.c 9     7/18/01 9:32a Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    seqkillMain

argMainRENAME(main, seqkill)
#endif

/*

:Program Sequence to monitor an I/O bit and abort all axes when active.

This sample program creates a program sequencer that will monitor an I/O bit.
 When this I/O bit is set, it will abort all the axes from 0 to axisCount.  It
 will monitor motor 0's transceiver A to determine when to abort the axes.

The XMP program sequencer controls the execution of a single command or a
 series of commands on the XMP controller.  The program sequencer provides the
 ability to execute programs directly on the XMP controller without host
 intervention.  Examples of individual commands that can be executed by the
 program sequencer are motion, looping, conditional branching, computation,
 reading and writing of memory, time delays, waiting for conditions, setting
 inputs/outputs, and generation of events.  This rich command set provides
 capability similar to, and beyond, that provided by Programmable Logic
 Controller (PLC) programs.

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 MOTOR_NUMBER    (0)
#define AXIS_COUNT      (8)

#define IO_TRIGGER      (MEIXmpMotorIOMaskXCVR_A)

/*
   Active High: MPICommandOperatorBIT_SET
   Active Low : MPICommandOperatorBIT_CLEAR
*/
#define IO_LEVEL        (MPICommandOperatorBIT_SET)

/* 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                axisCount,
                 MPIMotor           *motor,
                 long                motorNumber)
{
    long            index;
    long            returnValue;

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

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

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

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

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

    /* Write Motion Supervisor AxisMap[], and clear fault conditions */
    returnValue =
        mpiMotionAction(*motion,
                        MPIActionRESET);
    msgCHECK(returnValue);
}

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

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(returnValue);

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

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

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

/*
   sequenceCommandAdd() creates a command (MPICommand object) and appends it to
   sequence's list of commands.  This function does return MPI error codes so
   that sequence setup code may be more easily debugged.

   Warning:  sequenceCommandAdd() does not keep track of created command objects
   so it is important that before a sequence object is deleted, that each
   command object on sequence's list is itself deleted.  Otherwise, there will
   be memory leaks.  One can use sequenceProgramDelete() to accomplish this.
*/
long sequenceCommandAdd(MPISequence          sequence,
                        MPICommandType       commandType,
                        MPICommandParams    *commandParams,
                        const char          *label)
{
    MPICommand  command;
    long        returnValue;

    command =
        mpiCommandCreate(commandType,
                         commandParams,
                         label);
    returnValue =
        mpiCommandValidate(command);

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiSequenceCommandAppend(sequence,
                                     command);
    }

    return returnValue;
}

/*
   sequenceKillProgramCreate() creates a program that waits for one of motor's
   io lines (represented by trigger) to turn on then commands an E_STOP_ABORT.
*/
MPISequence sequenceKillProgramCreate(MPIMotion             motion,
                                      MPIMotor              motor,
                                      MEIXmpMotorIOMask     trigger,
                                      MPICommandOperator    level)
{
    MPISequence         sequence;
    MPICommandParams    commandParams;
    long                returnValue;

    /* Create sequence object */
    sequence =
        mpiSequenceCreate(mpiMotionControl(motion),
                          -1,   /* Use the next available sequence */
                          3);   /* # of commands in sequence */
    msgCHECK(mpiSequenceValidate(sequence));

    /* Wait for motor 0's bit 0 (transceiver A) to be set */
    commandParams.waitIO.type           = MPIIoTypeMOTOR;
    commandParams.waitIO.source.motor   = motor;
    commandParams.waitIO.oper           = level;
    commandParams.waitIO.mask           = trigger;

    returnValue =
        sequenceCommandAdd(sequence,
                           MPICommandTypeWAIT_IO,
                           &commandParams,
                           NULL);
    msgCHECK(returnValue);

    /* command an E_STOP_ABORT */
    commandParams.motion.motionCommand  = MPICommandMotionE_STOP_ABORT;
    commandParams.motion.motion     = motion;

    returnValue =
        sequenceCommandAdd(sequence,
                           MPICommandTypeMOTION,
                           &commandParams,
                           NULL);
    msgCHECK(returnValue);

    /* Stop sequence */
    commandParams.branch.label      = NULL;
    commandParams.branch.expr.oper  = MPICommandOperatorALWAYS;

    returnValue =
        sequenceCommandAdd(sequence,
                           MPICommandTypeBRANCH,
                           &commandParams,
                           NULL);
    msgCHECK(returnValue);

    /* Return the new sequence handle */
    return sequence;
}

/*
   sequenceProgramDelete() removes and deletes all command objects on sequence's
   command list and then deletes sequence.  This function does return MPI error
   codes so that sequence setup code may be more easily debugged.
*/
long sequenceProgramDelete(MPISequence *sequence)
{
    MPICommand  command;
    long        returnValue = MPIMessageOK;

    /* Remove and delete command objects on sequence list */
    while(TRUE) {
        command = mpiSequenceCommandLast(*sequence);
        if ((returnValue != MPIMessageOK) ||
            (command==MPIHandleVOID)) {
            break;
        }
        returnValue =
            mpiSequenceCommandRemove(*sequence,
                                     command);

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiCommandDelete(command);
        }
    }

    /* Delete sequence object */
    returnValue =
        mpiSequenceDelete(*sequence);

    if (returnValue == MPIMessageOK) {
        /* Make it obvious that sequence is no longer a valid object */
        *sequence = MPIHandleVOID;
    }

    return returnValue;
}

/*
   Starts a sequence, waits for the user to press a key and then
   stops the sequence.
*/
void sequenceRun(MPISequence sequence)
{
    long returnValue;

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);
    msgCHECK(returnValue);

    fprintf(stderr,"Press any key to stop sequence.\n");
    meiPlatformKey(MPIWaitFOREVER);
    fprintf(stderr,"Exiting ...\n");

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    if ((returnValue != MPIMessageOK) &&
        (returnValue != MPISequenceMessageSTOPPED)) {
        msgCHECK(returnValue);
    }
}

int main(int     argc,
         char   *argv[])
{
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotion           motion;
    MPIAxis             axis[MEIXmpMAX_COORD_AXES];     /* axis handles */
    MPIMotor            motor;
    MPISequence         sequence;

    long    returnValue;

    /* 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_COUNT,
                &motor,
                MOTOR_NUMBER);

    /* Create sequence program */
    sequence =
        sequenceKillProgramCreate(motion,
                                  motor,
                                  IO_TRIGGER,
                                  IO_LEVEL);

    /* Run sequence */
    sequenceRun(sequence);

    /* Delete sequence program */
    returnValue =
        sequenceProgramDelete(&sequence);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


seqrec.c -- Track status of specified motion supervisors and enable data recorder on any motion.
/* seqrec.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/seqrec.c 11    7/23/01 2:36p Kevinh $";
#endif

/*

:Track status of specified motion supervisors and enable data recorder on any motion.

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    seqrecMain

argMainRENAME(main, seqrec)
#endif

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

Arg argList[] = {
    {   "-sequence",    ArgTypeLONG,    &sequenceNumber,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;    /* motion controller handle */
    MPISequence sequence;   /* sequence handle */

    MPICommand  command;

    MEIXmpData  *firmware;

    MPICommandParams    params;

    long    returnValue;    /* return value from library */

    long    index;

    long            motionCount;
    MPIObjectMap    motionMap;

    long    labelCheckMS;

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if (sequenceNumber >= MEIXmpMAX_PSs) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[motion# (0) ...]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_PSs - 1);
        exit(MPIMessageARG_INVALID);
    }

    mpiObjectMapCLEAR(motionMap);

    /* Create motion map */
    if (argIndex >= argc) {
        motionCount = 1;
        mpiObjectMapBitSET(motionMap, 0, 1);    /* MS[0] default */
    }
    else {
        motionCount = 0;

        while (argIndex < argc) {
            char    *arg;
            long    number;

            arg = argv[argIndex++];

            number = meiPlatformAtol(arg);

            if ((number >= 0) &&
                (number < MEIXmpMAX_MSs)) {
                motionCount++;
                mpiObjectMapBitSET(motionMap, number, 1);
            }
            else {
                fprintf(stderr,
                        "%s: invalid motion number\n",
                        arg);
                exit(1);
            }
        }
    }

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-sequence # (0 .. %d)]\n"
                           "\t\t[motion# (0) ...]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_PSs - 1);
        exit(MPIMessageARG_INVALID);
    }

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

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

    returnValue =
        mpiControlMemory(control,
                         (void **)&firmware,
                         NULL);
    msgCHECK(returnValue);

    /* Create Sequence */
    sequence =
        mpiSequenceCreate(control,
                          sequenceNumber,
                          2 + motionCount + 2); /* sequence size */
    msgCHECK(mpiSequenceValidate(sequence));

    /* Create Commands */

    /* Branch to "CheckMS" if Recorder is ON (!= 0) */
    params.branch.label             = "CheckMS";
    params.branch.expr.address.l    = &firmware->Recorder.Enable;
    params.branch.expr.oper         = MPICommandOperatorNOT_EQUAL;
    params.branch.expr.by.value.l   = 0;

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &params,
                         "RecorderON");
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    /* Turn Recorder ON */
    params.assign.dst.l     = &firmware->Recorder.Enable;
    params.assign.value.l   = -1;   /* continuous, else # records */

    command =
        mpiCommandCreate(MPICommandTypeASSIGN,
                         &params,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    labelCheckMS = FALSE;

    for (index = 0; index < MEIXmpMAX_MSs; index++) {
        if (mpiObjectMapBitGET(motionMap, index) == 0) {
            continue;
        }

        /* Branch to "RecorderOn" if motion detected */
        params.branch.label             = "RecorderON";
        params.branch.expr.address.l    = (long *)&firmware->MS[index].Status;
        params.branch.expr.oper         = MPICommandOperatorBIT_CLEAR;
        params.branch.expr.by.value.l   = (0x1 << MEIXmpEventDONE);

        command =
            mpiCommandCreate(MPICommandTypeBRANCH,
                             &params,
                             (labelCheckMS == FALSE) ? "CheckMS" : NULL);
        msgCHECK(mpiCommandValidate(command));

        labelCheckMS = TRUE;

        returnValue =
            mpiSequenceCommandAppend(sequence,
                                     command);
        msgCHECK(returnValue);
    }

    /* Turn Recorder OFF */
    params.assign.dst.l     = &firmware->Recorder.Enable;
    params.assign.value.l   = 0;

    command =
        mpiCommandCreate(MPICommandTypeASSIGN,
                         &params,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    /* Branch to "CheckMS" */
    params.branch.label     = "CheckMS";
    params.branch.expr.oper = MPICommandOperatorALWAYS;

    command =
        mpiCommandCreate(MPICommandTypeBRANCH,
                         &params,
                         NULL);
    msgCHECK(mpiCommandValidate(command));

    returnValue =
        mpiSequenceCommandAppend(sequence,
                                 command);
    msgCHECK(returnValue);

    /* Start sequence */
    returnValue =
        mpiSequenceStart(sequence,
                         MPIHandleVOID);

    if (returnValue != MPIMessageOK) {
        fprintf(stderr, "%s: mpiSequenceStart() returns 0x%x: %s\n",
                        argv[0],
                        returnValue,
                        mpiMessage(returnValue, NULL));
        exit(returnValue);
    }

    meiPlatformConsole("Press any key to stop sequence\n");
    meiPlatformKey(MPIWaitFOREVER);

    /* Stop sequence */
    returnValue = mpiSequenceStop(sequence);
    msgCHECK(returnValue);

    returnValue = mpiSequenceDelete(sequence);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


settle1.c -- Configure in-position tolerance and settling time for an axis.
/* settle1.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/settle1.c 10    7/23/01 2:36p Kevinh $";
#endif

/*

:Configure in-position tolerance and settling time for an axis.

A simple settling configuration which sets the Fine Position Tolerance
 and Settling Time for an axis.  Both are required for the
 MEIXmpStatusIN_FINE_POSITION status bit.  The settling criteria are:

    1)  The absolute value of the position error is less than or equal to
        the fine position tolerance.
    2)  The absolute value of the velocity is less than or equal to the
        velocity tolerance.
    3)  Both criteria 1 and 2 above have been satisfied for the settling
        time.  Whenever either criteria 1 or 2 is not satisfied,
        IN_FINE_POSITION is cleared and the settling tier is reset.

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    settle1Main

argMainRENAME(main, settle1)
#endif

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

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{
    MPIControl      control;        /* Motion controller handle */
    MPIAxis         axis;           /* Axis handle(s) */

    MPIAxisConfig   axisConfig;     /* Axis configuration */

    long    returnValue;            /* Return value from library */

    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;
        }
    }

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

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

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

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

    /* Configure axis */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    axisConfig.inPosition.tolerance.positionFine = (float)50.0;
    axisConfig.inPosition.tolerance.velocity     = (float)100.0;
    axisConfig.inPosition.settlingTime           = (float)0.5; /* .5 seconds */

    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

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

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

    return ((int)returnValue);
}


settle2.c -- Configure settling criteria and exception event settling conditions.
/* settle2.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/settle2.c 8     7/23/01 2:36p Kevinh $";
#endif

/*

:Configure settling criteria and exception event settling conditions.

The MPI supports axis configurations for motion settling criteria to
 determine when motion is complete.  The XMP-Series controller supports
 event notification for Coarse, Fine, and Target positions and motion done.
 Generally, settling criteria is only applicable to normal host commanded
 motion profiles.  The XMP-Series controller can also be configured to
 support settling criteria with Stop and E-Stop events.

The settling criteria is configured set with mpiAxisConfigGet/Set(...),
 using the structures:

typedef struct MPIAxisInPosition {
    struct {
        float   positionFine;
        long    positionCoarse;
        float   velocity;
    } tolerance;
    float   settlingTime;
    long    settleOnStop;
    long    settleOnEstop;
} MPIAxisInPosition;

typedef struct MPIAxisConfig {
    MPIAxisInPosition   inPosition;
    MPIObjectMap    filterMap;
} MPIAxisConfig;

The settling criteria are:

 positionFine - in-position window between command and actual (counts)

 positionCoarse - in-position window between target and actual (counts)

 velocity - actual velocity (counts/second)

 settlingTime - required time for settling (seconds)

The Stop and E-Stop event settling conditions can be enabled/disabled:

 settleOnStop - TRUE or FALSE, enables/disables settling criteria for Stop

 settleOnEstop - TRUE or FALSE, enables/disables settling criteria for E-Stop

The XMP-Series controller sets the appropriate status bits and generates
 the following events based on the settling criteria and logic:

 IN_FINE_POSITION

    1) |command position - actual position| < positionFine tolerance
    2) |command velocity - actual velocity| < velocity tolerance
    3) 1,2 and 3 have been satisfied for the settlingTime tolerance

 IN_COARSE_POSITION

    1) |target position - actual position| < postionCoarse tolerance

 AT_TARGET

    1) The command position = target position.

 DONE

    1) The calculated trajectory is complete.
    2) IN_FINE_POSITION conditions have been satisfied.

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    settle2Main

argMainRENAME(main, settle2)
#endif

#define MOTION_COUNT        (1)     /* Number of motion profiles */
#define AXIS_COUNT          (1)     /* Number of axes */

/* Command line arguments and defaults */
long            axisNumber[AXIS_COUNT] = { 0,   };
long            motionNumber    = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;
float           fineTol         = (float)500.0; /* counts */
long            coarseTol       = 200;          /* counts */
float           velocityTol     = (float)1.0;   /* counts/sec */
float           settlingTime    = (float)0.2;   /* seconds */
long            eventDelay      = 1000;         /* milliseconds */

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber[0], },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-type",    ArgTypeLONG,    &motionType,    },
    {   "-fine",    ArgTypeFLOAT,   &fineTol,       },
    {   "-coarse",  ArgTypeLONG,    &coarseTol,     },
    {   "-velocity",ArgTypeFLOAT,   &velocityTol,   },
    {   "-settling",ArgTypeFLOAT,   &settlingTime,  },
    {   "-delay",   ArgTypeLONG,    &eventDelay,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[][AXIS_COUNT] = {
    { 20000.0,  },
    { 0.0,  },
};

MPITrajectory trajectory[][AXIS_COUNT] = {
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
    {   /* velocity     accel       decel       jerkPercent */
        { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    },
};

/* Motion parameters */

MPIMotionSCurve sCurve[] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionTrapezoidal    trapezoidal[] = {
    {   &trajectory[0][0],  &position[0][0],    },
    {   &trajectory[1][0],  &position[1][0],    },
};

MPIMotionVelocity   velocity[] = {
    {   &trajectory[0][0],  },
    {   &trajectory[1][0],  },
};

#define SETTLE_EVENTS   (2) /* Number of settle configurations */

/* Settle on Stop/E-Stop Events */
long settleEvent[] = {
    FALSE,
    TRUE
};

#define ACTIONS         (5) /* Number of MPI actions */

/* Generate Actions */
MPIAction action[] = {
    MPIActionNONE,
    MPIActionSTOP,
    MPIActionE_STOP,
    MPIActionE_STOP_ABORT,
    MPIActionABORT
};

char * actionString[] = {
    "None",
    "Stop",
    "E-Stop",
    "E-Stop/Abort",
    "Abort"
};

void eventStatusDisplay(MPIEventStatus status);

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

    MPIAxisConfig   axisConfig; /* Axis configuration object */

    MPIEventMask    eventMask;

    long    returnValue;    /* Return value from library */

    long    index;
    long    actionIndex;    /* Index to action[...] array */
    long    settleIndex;    /* Index to settleEvent[...] array */
    long    motionDone;     /* Flag when Done occurs */
    long    previousEvents; /* Flag to check for previously generated events */

    double  actual;         /* Axis position */
    double  origin;         /* Axis origin */

    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) ||
        (axisNumber[0] > (MEIXmpMAX_Axes - AXIS_COUNT)) ||
        (motionNumber  >= MEIXmpMAX_MSs) ||
        (motionType <  MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST) ||
        (fineTol < 0.0) ||
        (coarseTol < 0) ||
        (velocityTol < 0.0) ||
        (settlingTime < 0.0) ||
        (eventDelay < 0)) {
        printf("usage: %s %s\n"
               "\t\t[-axis # (0 .. %d)]\n"
               "\t\t[-motion # (0 .. %d)]\n"
               "\t\t[-type # (0 .. %d)]\n"
               "\t\t[-fine # (0.0 .. )]\n"
               "\t\t[-coarse # (0 .. )]\n"
               "\t\t[-velocity # (0.0 .. )]\n"
               "\t\t[-settling # (0.0 .. )]\n"
               "\t\t[-delay # (0 .. )]\n",
                argv[0],
                ArgUSAGE,
                MEIXmpMAX_Axes - AXIS_COUNT,
                MEIXmpMAX_MSs - 1,
                MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

    /* Create axis object for axisNumber */
    axis =
        mpiAxisCreate(control,
                      axisNumber[0]);
    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);
    meiEventMaskALL(eventMask);

    returnValue =
        mpiMotionEventNotifySet(motion,
                                eventMask,
                                NULL);      /* ALL sources */
    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 */
    meiASSERT(service != NULL);

    meiPlatformConsole("Press any key to quit ...\n");

    /* Loop repeatedly */
    index       = 0;
    actionIndex = 0;
    settleIndex = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MPIStatus           status;

        if (motionDone) {
            MPIMotionParams     motionParams;       /* Motion parameters */

            /* Fill in the MPIMotionParams structure */
            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            /* Check motion status for any error conditions */
            returnValue =
                mpiMotionStatus(motion,
                                &status,
                                NULL);
            msgCHECK(returnValue);

            if (status.state == MPIStateERROR) {
                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                msgCHECK(returnValue);

                printf("  Error state cleared.\n");
            }

            /* Set origin to current actual position */
            returnValue =
                mpiAxisActualPositionGet(axis,
                                         &actual);
            msgCHECK(returnValue);

            returnValue =
                mpiAxisOriginGet(axis,
                                 &origin);
            msgCHECK(returnValue);

            returnValue =
                mpiAxisOriginSet(axis,
                                 (origin + actual));
            msgCHECK(returnValue);

            /* Configure axis settling criteria */
            returnValue =
                mpiAxisConfigGet(axis,
                                 &axisConfig,
                                 NULL);
            msgCHECK(returnValue);

            axisConfig.inPosition.tolerance.positionFine =
                fineTol;
            axisConfig.inPosition.tolerance.positionCoarse =
                coarseTol;
            axisConfig.inPosition.tolerance.velocity =
                velocityTol;
            axisConfig.inPosition.settlingTime =
                settlingTime;

            /* Configure settling criteria for Stop and E-Stop events
                TRUE = use settling criteria for Stop and E-Stop
                FALSE = do NOT use settling criteria for Stop and E-Stop
            */
            axisConfig.inPosition.settleOnStop = settleEvent[settleIndex];
            axisConfig.inPosition.settleOnEstop = settleEvent[settleIndex];

            returnValue =
                mpiAxisConfigSet(axis,
                                 &axisConfig,
                                 NULL);
            msgCHECK(returnValue);

            /* Check for any previous events (generated by RESET) */
            previousEvents = TRUE;
            while (previousEvents) {
                returnValue =
                    mpiNotifyEventWait(notify,
                                       &eventStatus,
                                       MPIWaitPOLL);
                if (returnValue == MPIMessageTIMEOUT) {
                    previousEvents = FALSE;
                }
                else {
                    msgCHECK(returnValue);
                    eventStatusDisplay(eventStatus);
                }
            }

            meiPlatformConsole("\nMotion Start, Target= %12.0lf  ",
                   position[index][axisNumber[0]]);

            meiPlatformConsole("  Settle on Event: %s",
                   settleEvent[settleIndex] ? "yes" : "no");

            /* Point to point motion (relative to new origin) */
            returnValue =
                mpiMotionStart(motion,
                               motionType,
                               &motionParams);
            msgCHECK(returnValue);

            /* Wait for motion profile to partially execute */
            meiPlatformSleep(eventDelay);

            /* Generate an event */
            returnValue =
                mpiMotionAction(motion,
                                action[actionIndex]);
            msgCHECK(returnValue);

            meiPlatformConsole("  Event:%s.\n", actionString[actionIndex]);

            /* Increment through settleEvent[...] and action[...] */
            if (++actionIndex >= ACTIONS) {
                actionIndex = 0;
                if (++settleIndex >= SETTLE_EVENTS) {
                    settleIndex = 0;
                }
            }
            motionDone = FALSE;
        }

        /* Wait for motion event */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        /* Motion Done Event from motion source */
        if  (eventStatus.type == MPIEventTypeMOTION_DONE) {
            motionDone = TRUE;

            if (++index >= MOTION_COUNT) {
                index = 0;
            }
        }
        eventStatusDisplay(eventStatus);
    }

    printf("\n");

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

    returnValue = mpiAxisDelete(axis);
    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);
}

void eventStatusDisplay(MPIEventStatus status)
{
    MEIEventStatusInfo  *info;

    info = (MEIEventStatusInfo *)status.info;

    switch (status.type) {
        /* In Coarse Event from axis source */
        case MEIEventTypeIN_POSITION_COARSE: {
            meiPlatformConsole("  InCoarse, actual:%ld, sample:0x%x\n",
                   info->data.axis.actualPosition,
                   info->data.axis.sampleCounter);
            break;
        }
        /* In Fine Event from axis source */
        case MEIEventTypeIN_POSITION_FINE: {
            meiPlatformConsole("  InFine, actual:%ld, sample:0x%x\n",
                   info->data.axis.actualPosition,
                   info->data.axis.sampleCounter);
            break;
        }
        /* At Target Event from axis source */
        case MEIEventTypeAT_TARGET: {
            meiPlatformConsole("  AtTarget, actual:%ld, sample:0x%x\n",
                   info->data.axis.actualPosition,
                   info->data.axis.sampleCounter);
            break;
        }
        /* Motion Done Event from motion source */
        case MPIEventTypeMOTION_DONE: {
            meiPlatformConsole("  Done, sample:0x%x\n",
                   info->data.motion.sampleCounter);
            break;
        }
        default: {
            meiPlatformConsole("Event (unexpected): %ld (0x%x)",
                   status.type,
                   info->data.word[0]);
            break;
        }
    }
}


shape.c -- Configure Trajectory Shaping Filters
/* shape.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/shape.c 12    7/23/01 2:36p Kevinh $";
#endif

/*

:Configure Trajectory Shaping Filters

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 <string.h>
#include <ctype.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    shapeMain

argMainRENAME(main, shape)
#endif

typedef struct SHAPER {
    long    Index;
    long    Axis;
    long    Length;
    long    MaxDelay;
    long    MaxAmp;
    double  TimeStep;
    long    Time[MEIXmpMAX_PreCoeffs/2];
    long    Amp[MEIXmpMAX_PreCoeffs/2];
} SHAPER;

long
    loadShaper(MPIControl   control,
               SHAPER       *shaper);

int
    main(int    argc,
         char   *argv[])
{
    MPIControl          control;    /* motion controller handle */
    MPIControlConfig    config;

    SHAPER      shaper;

    char    *fileName;
    FILE    *fp;
    char    buffer[256];
    long    shaperCount;
    long    shaperCountOld;

    long    returnValue;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;

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

    fileName =
        (argIndex >= argc)
                ? "shape.txt"
                : argv[argIndex++];

    if (argIndex < argc) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[fileName (%s)]\n",
                           argv[0],
                           ArgUSAGE,
                           "shape.txt");
        exit(0);
    }

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

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

    fp = fopen(fileName, "r");

    if (fp == NULL) {
        fprintf(stderr,
                "shape.txt not found.\n");
        exit(2);
    }

    returnValue =
        mpiControlConfigGet(control,
                            &config,
                            NULL);
    msgCHECK(returnValue);

    shaperCount = 0;
    shaperCountOld = -1;

    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        long    axis;
        long    length;
        long    maxAmp;
        long    maxDelay;

        char    *ptr;

        if (shaperCount > shaperCountOld) {
            shaper.Axis     = -1;   /* Make sure all params are read from file */
            shaper.MaxAmp   = -1;
            shaper.Length   =  0;
            shaper.MaxDelay = -1;
            shaper.TimeStep = 1.0 / config.sampleRate;

            shaperCountOld = shaperCount;
        }

        for (ptr = buffer; *ptr != '\0'; ptr++) {
            char    byte = *ptr;

            if (isupper(byte)) {
                *ptr = (char)tolower(byte);
            }
        }

        if (sscanf(buffer, "#AXIS  = %d", &axis) == 1) {
            shaper.Axis = axis;
            continue;
        }

        if (sscanf(buffer, "#IMPULSES = %d", &length) == 1) {
            shaper.Length = length;
            continue;
        }

        if (sscanf(buffer, "#AMPSUM = %d", &maxAmp) == 1) {
            shaper.MaxAmp = maxAmp;
            continue;
        }

        if (sscanf(buffer, "#STEPS = %d", &maxDelay) == 1) {
            shaper.MaxDelay = maxDelay;
            continue;
        }

        if (strncmp(buffer, "#TIME", 5) == 0) {
            long    sum;
            long    maxTime;
            long    index;

            sum = 0;
            maxTime = 0;

            for (index = 0; index < shaper.Length; index++) {
                long    time;
                long    amp;

                if (fgets(buffer, sizeof(buffer), fp) == NULL) {
                    fprintf(stderr,
                            "Unexpected end-of-file\n");
                    return ((int)returnValue);

                }

                if (sscanf(buffer, "%d %d", &time, &amp) == 2) {
                    shaper.Time[index]  = time;
                    shaper.Amp[index]   = amp;
                    sum += amp;

                    if (time > maxTime) {
                        maxTime = time;
                    }
                }
            }

            if (sum != shaper.MaxAmp) {
                fprintf(stderr,
                        "Sum of amplitudes (%d) does not equal AmpSum (%d).\n",
                        sum,
                        shaper.MaxAmp);
                return ((int)returnValue);
            }

            if (maxTime != shaper.MaxDelay) {
                fprintf(stderr,
                        "Maximum time (%d) does not equal Steps (%d).\n",
                        maxTime,
                        shaper.MaxDelay);
                return (returnValue);
            }

            if (axis < 0) {
                fprintf(stderr,
                        "No #Axis statement.\n");
                return (returnValue);
            }
            else {
                shaper.Index = shaperCount;

                if (shaperCount >= MEIXmpMAX_PreFilters) {
                    fprintf(stderr,
                            "Too many shapers.\n");
                    break;
                }
                else {
                    double  scale;

                    /* Rescale for XMP filter normalization */
                    scale = (double)MEIXmpFILTER_SCALE / (double)shaper.MaxAmp;

                    sum = 0;

                    for (index = 0; index < shaper.Length - 1; index++) {
                        shaper.Amp[index] = (long)(shaper.Amp[index] * scale);
                        sum += shaper.Amp[index];
                    }
                    shaper.Amp[shaper.Length - 1] = MEIXmpFILTER_SCALE - sum;

                    loadShaper(control,
                               &shaper);

                    fprintf(stderr,
                            "Axis %d shaper loaded.\n",
                            axis);

                    shaperCount++;
                }
            }
        }
    }
    fclose(fp);

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

    return ((int)returnValue);
}

long
    loadShaper(MPIControl   control,
               SHAPER       *shaper)
{
    MEIXmpData          *firmware;
    MEIXmpBufferData    *external;

    MPIAxis axis;

    MPIControlConfig    controlConfig;
    MEIControlConfig    controlConfigXmp;
    MPIAxisConfig       axisConfig;
    MEIAxisConfig       axisConfigXmp;

    long    returnValue;

    long    index;
    long    axisNumber;
    long    length;
    long    delayTime;

    /* Get pointer to XMP firmware */
    returnValue =
        mpiControlMemory(control,
                         (void **)&firmware,
                         (void **)&external);
    msgCHECK(returnValue);

    index      = shaper->Index;
    axisNumber = shaper->Axis;

    axis =
        mpiAxisCreate(control,
                      axisNumber);
    msgCHECK(mpiAxisValidate(axis));

    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);

    /* Set command position to Filter input (disable filter) */
    axisConfigXmp.Filter.Pointer    = &firmware->Axis[axisNumber].TC.Filter.Input;
    axisConfigXmp.Filter.Delay      = 0;

    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);

    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            &controlConfigXmp);
    msgCHECK(returnValue);

    controlConfigXmp.PreFilter[index].Type      = MEIXmpFilterTypeSHAPING;
    controlConfigXmp.PreFilter[index].Length    = shaper->Length;
    controlConfigXmp.PreFilter[index].Input     = &firmware->Axis[axisNumber].TC.Filter.Input;
    controlConfigXmp.PreFilter[index].Coeff[0]  = 0;

    for (length = 0; length < shaper->Length; length++) {
        controlConfigXmp.PreFilter[index].Coeff[2 * length + 1] =
            shaper->Time[length];
        controlConfigXmp.PreFilter[index].Coeff[2 * length + 2] =
            shaper->Amp[length];
    }

    if (controlConfigXmp.preFilterCount < (index+1)) {
        controlConfigXmp.preFilterCount = (index + 1);
    }

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            &controlConfigXmp);
    msgCHECK(returnValue);

    /* 2x max delay */
    delayTime = 2 * (long)(shaper->MaxDelay * shaper->TimeStep * 1000.0);

    meiPlatformSleep(delayTime);    /* wait for filter to initialize */

    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);

    /* Set command position pointer to Output of shaper */
    axisConfigXmp.Filter.Pointer    = &external->PreFilter[index].Output;
    axisConfigXmp.Filter.Delay      = shaper->MaxDelay;

    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         &axisConfigXmp);
    msgCHECK(returnValue);

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

    return (returnValue);
}


sidn1.c -- SERCOS node idn get/display
/* sidn1.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/sidn1.c 16    7/23/01 2:36p Kevinh $";
#endif

/*

:SERCOS node idn get/display

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    sidn1Main

argMainRENAME(main, sidn1)
#endif

#define BAUD_RATE_DEFAULT       (MPISercosBaud10MBIT)
#define PHASE_DEFAULT           (2)
#define SAMPLE_RATE_DEFAULT     (1000)
#define MODE_DEFAULT            (MPINodeModeOPENLOOP_POSITION_MOTOR)
#define INTENSITY_DEFAULT       (3)
#define SERCOS_NUMBER_DEFAULT   (0)
#define NODE_NUMBER_DEFAULT     (0)

/* Command line arguments and defaults */
long            baud            = -1;
long            phase           = PHASE_DEFAULT;
long            sampleRate      = SAMPLE_RATE_DEFAULT;
MPINodeMode     mode            = MODE_DEFAULT;
long            intensity       = INTENSITY_DEFAULT;
long            sercosNumber    = SERCOS_NUMBER_DEFAULT;
long            nodeNumber      = NODE_NUMBER_DEFAULT;

Arg argList[] = {
    {   "-baud",        ArgTypeLONG,    &baud,          },
    {   "-phase",       ArgTypeLONG,    &phase,         },
    {   "-sample",      ArgTypeLONG,    &sampleRate,    },
    {   "-mode",        ArgTypeLONG,    &mode,          },
    {   "-intensity",   ArgTypeLONG,    &intensity,     },
    {   "-sercos",      ArgTypeLONG,    &sercosNumber,  },
    {   "-node",        ArgTypeLONG,    &nodeNumber,    },

    {   NULL,           ArgTypeINVALID, NULL,   }
};

#if 0
#define MEI_PMC
#endif

void
    usage(char  *programName)
{
    meiPlatformConsole("usage: %s\n\t%s\n"
                        "\t\t[-baud (%d)]\n"
                        "\t\t[-phase (%d)]\n"
                        "\t\t[-sample (%d)]\n"
                        "\t\t[-mode (%d)]\n"
                        "\t\t[-intensity (%d)]\n"
                        "\t\t[-sercos (%d)]\n"
                        "\t\t[-node (%d)]\n"
                        "\t\tidn [...]\n",
                        programName,
                        ArgUSAGE,
                        (BAUD_RATE_DEFAULT == MPISercosBaud2MBIT)  ?  2 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud4MBIT)  ?  4 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud10MBIT) ? 10
                                                                   : -1,
                        PHASE_DEFAULT,
                        SAMPLE_RATE_DEFAULT,
                        MODE_DEFAULT,
                        INTENSITY_DEFAULT,
                        SERCOS_NUMBER_DEFAULT,
                        NODE_NUMBER_DEFAULT);

    exit(0);
}

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;
    MPISercos   sercos = MPIHandleVOID;
    MPINode     node   = MPIHandleVOID;
    MPIIdn      idn    = MPIHandleVOID;

    long    returnValue;
    long    deleteMessage;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPISercosStatus     SercosStatus;

    long    argIndex;

    MPISercosBaud   baudRate;
    MPISercosConfig sercosConfig;

    MPISercosStatus sercosStatus;

    /* 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) {
        usage(argv[0]);
    }

    baudRate =
        (baud == 2)  ? MPISercosBaud2MBIT  :
        (baud == 4)  ? MPISercosBaud4MBIT  :
        (baud == 10) ? MPISercosBaud10MBIT
                     : BAUD_RATE_DEFAULT;

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

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

    /* Create sercos object */
    sercos =
        mpiSercosCreate(control,
                        sercosNumber);
    msgCHECK(mpiSercosValidate(sercos));

    returnValue =
        mpiSercosStatus(sercos,
                        &sercosStatus,
                        NULL);
    msgCHECK(returnValue);

    printf("sercos[%d] status: phase %d\n",
            sercosNumber,
            sercosStatus.phase);

    if (sercosStatus.phase < 2) {
        MPIControlConfig    controlConfig;

        printf("\nsercos[%d]: transitioning to phase 2\n",
                sercosNumber);

        returnValue =
            mpiControlConfigGet(control,
                                &controlConfig,
                                NULL);
        msgCHECK(returnValue);

        controlConfig.sampleRate = sampleRate;

#if defined(MEI_PMC)
        controlConfig.axisCount     = 8;
        controlConfig.filterCount   = 8;
        controlConfig.motionCount   = 8;
        controlConfig.motorCount    = 8;
        controlConfig.sequenceCount = 8;

        controlConfig.sercosCount = 1;
#else
        controlConfig.axisCount     = 24;
        controlConfig.filterCount   = 24;
        controlConfig.motionCount   = 24;
        controlConfig.motorCount    = 24;
        controlConfig.sequenceCount = 24;

        controlConfig.sercosCount = 3;
#endif

        returnValue =
            mpiControlConfigSet(control,
                                &controlConfig,
                                NULL);
        msgCHECK(returnValue);

        returnValue =
            mpiSercosConfigGet(sercos,
                               &sercosConfig,
                               NULL);
        msgCHECK(returnValue);

        sercosConfig.baudRate = baudRate;
        sercosConfig.xmitIntensity = intensity;

        returnValue =
            mpiSercosConfigSet(sercos,
                               &sercosConfig,
                               NULL);
        msgCHECK(returnValue);

        returnValue =
            mpiSercosInit(sercos,
                          2);
        msgCHECK(returnValue);

        returnValue =
            mpiSercosStatus(sercos,
                            &SercosStatus,
                            NULL);
        msgCHECK(returnValue);

        printf("sercos[%d] status: phase %d\n",
                sercosNumber,
                SercosStatus.phase);
    }

    node =
        mpiNodeCreate(sercos,
                      nodeNumber);
    msgCHECK(mpiNodeValidate(node));

    returnValue =
        mpiSercosNodeAppend(sercos,
                            node);
    msgCHECK(returnValue);

    idn = mpiIdnCreate((MPIIdnNumber)(mpiIdnNumberSTANDARD(1)));
    returnValue = mpiIdnValidate(idn);

    while ((returnValue == MPIMessageOK) &&
           (argIndex < argc)) {
        MPIIdnElement   idnElement;
        MPIIdnField     field;

        long    idnNumber;

        char    idnText[32];

        idnNumber = meiPlatformAtol(argv[argIndex++]);

        returnValue =
            mpiIdnNumberSET(idn,
                            &idnNumber);

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiNodeIdnGET(node,
                              idn);
        }

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiIdnElementGET(idn,
                                 &idnElement);
        }

        if (returnValue == MPIMessageOK) {
            printf("\nsercos[%d] node number %d idn %s:\n",
                    sercosNumber,
                    nodeNumber,
                    mpiIdnNumberName((MPIIdnNumber)idnNumber, idnText));

            for (field = MPIIdnFieldFIRST; field < MPIIdnFieldLAST; field++) {
                switch (field) {
                    case MPIIdnFieldNUMBER: {
                        const char  *text;

                        if (returnValue == MPIMessageOK) {
                            returnValue =
                                mpiIdnNumberText(idn,
                                                 &text);
                        }

                        if (returnValue == MPIMessageOK) {
                            printf("\tnumber %s\n",
                                    text);
                        }
                        break;
                    }
                    case MPIIdnFieldNAME: {
                        printf("\tname %s\n",
                                idnElement.name);
                        break;
                    }
                    case MPIIdnFieldATTRIBUTES: {
                        printf("\tattributes 0x%x\n",
                                idnElement.attributes);
                        break;
                    }
                    case MPIIdnFieldUNIT: {
                        printf("\tunit %s\n",
                                idnElement.unit);
                        break;
                    }
                    case MPIIdnFieldMINIMUM: {
                        printf("\tminimum 0x%x\n",
                                idnElement.minimum.u);
                        break;
                    }
                    case MPIIdnFieldMAXIMUM: {
                        printf("\tmaximum 0x%x\n",
                                idnElement.maximum.u);
                        break;
                    }
                    case MPIIdnFieldDATA: {
                        if (mpiIdnFieldAttrGET(MPIIdnFieldAttrVARIABLE, idnElement.attributes) == 0) {
                            printf("\tdata 0x%x\n",
                                    idnElement.data.binary);
                        }
                        else {
                            MPIIdnVarLength *varLength;

                            long    index;

                            varLength = &idnElement.data.varLength;

                            for (index = 0; index < varLength->count; index++) {
                                printf("\tdata[%d] ",
                                        index);

                                switch (varLength->type) {
                                    case MPIIdnDataTypeBINARY: {
                                        printf("0x%x\n",
                                                varLength->as.value[index].u);
                                        break;
                                    }
                                    case MPIIdnDataTypeIDN: {
                                        char    idnName[32];

                                        printf("%s\n",
                                                mpiIdnNumberName(varLength->as.idn[index],
                                                                 idnName));
                                        break;
                                    }
                                    case MPIIdnDataTypeLONG: {
                                        printf("%d\n",
                                                varLength->as.value[index].l);
                                        break;
                                    }
                                    case MPIIdnDataTypeTEXT: {
                                        printf("%s\n",
                                                varLength->as.text);
                                        break;
                                    }
                                    case MPIIdnDataTypeUNSIGNED: {
                                        printf("%u\n",
                                                varLength->as.value[index].u);
                                        break;
                                    }
                                    case MPIIdnDataTypeUNSIGNED_HEX: {
                                        printf("0x%x\n",
                                                varLength->as.value[index].u);
                                        break;
                                    }
                                    default: {
                                        break;
                                    }
                                }

                                if (varLength->type == MPIIdnDataTypeTEXT) {
                                    break;
                                }
                            }
                        }
                        break;
                    }
                    default: {
                        break;
                    }
                }
            }
        }
    }

    /* Delete the IDN handle */
    if (idn != MPIHandleVOID) {
        deleteMessage = mpiIdnDelete(idn);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Clear Sercos Node list */
    if (sercos != MPIHandleVOID) {
        deleteMessage =
            mpiSercosNodeListSet(sercos,
                                 0,
                                 NULL);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the NODE handle */
    if (node != MPIHandleVOID) {
        deleteMessage = mpiNodeDelete(node);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the SERCOS handle */
    if (sercos != MPIHandleVOID) {
        deleteMessage = mpiSercosDelete(sercos);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the CONTROL handle */
    if (control != MPIHandleVOID) {
        deleteMessage = mpiControlDelete(control);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    return ((int)returnValue);
}


sidn2.c -- SERCOS node idn get/display/set
/* sidn2.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/sidn2.c 18    7/23/01 2:36p Kevinh $";
#endif

/*

:SERCOS node idn get/display/set

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 <string.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    sidn2Main

argMainRENAME(main, sidn2)
#endif

#define BAUD_RATE_DEFAULT       (MPISercosBaud10MBIT)
#define PHASE_DEFAULT           (2)
#define SAMPLE_RATE_DEFAULT     (1000)
#define MODE_DEFAULT            (MPINodeModeOPENLOOP_POSITION_MOTOR)
#define INTENSITY_DEFAULT       (3)
#define SERCOS_NUMBER_DEFAULT   (0)
#define NODE_NUMBER_DEFAULT     (0)

/* Command line arguments and defaults */
long            baud            = -1;
long            phase           = PHASE_DEFAULT;
long            sampleRate      = SAMPLE_RATE_DEFAULT;
MPINodeMode     mode            = MODE_DEFAULT;
long            intensity       = INTENSITY_DEFAULT;
long            sercosNumber    = SERCOS_NUMBER_DEFAULT;
long            nodeNumber      = NODE_NUMBER_DEFAULT;

Arg argList[] = {
    {   "-baud",        ArgTypeLONG,    &baud,          },
    {   "-phase",       ArgTypeLONG,    &phase,         },
    {   "-sample",      ArgTypeLONG,    &sampleRate,    },
    {   "-mode",        ArgTypeLONG,    &mode,          },
    {   "-intensity",   ArgTypeLONG,    &intensity,     },
    {   "-sercos",      ArgTypeLONG,    &sercosNumber,  },
    {   "-node",        ArgTypeLONG,    &nodeNumber,    },

    {   NULL,           ArgTypeINVALID, NULL,   }
};

#if 0
#define MEI_PMC
#endif

unsigned long VarData[64];

long
    idnDisplay(MPINode          node,
               MPIIdn           idn,
               unsigned long    *attributes);

void
    usage(char  *programName)
{
    meiPlatformConsole("usage: %s\n\t%s\n"
                        "\t\t[-baud (%d)]\n"
                        "\t\t[-phase (%d)]\n"
                        "\t\t[-sample (%d)]\n"
                        "\t\t[-mode (%d)]\n"
                        "\t\t[-intensity (%d)]\n"
                        "\t\t[-sercos (%d)]\n"
                        "\t\t[-node (%d)]\n"
                        "\t\tidn [...]\n",
                        programName,
                        ArgUSAGE,
                        (BAUD_RATE_DEFAULT == MPISercosBaud2MBIT)  ?  2 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud4MBIT)  ?  4 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud10MBIT) ? 10
                                                                   : -1,
                        PHASE_DEFAULT,
                        SAMPLE_RATE_DEFAULT,
                        MODE_DEFAULT,
                        INTENSITY_DEFAULT,
                        SERCOS_NUMBER_DEFAULT,
                        NODE_NUMBER_DEFAULT);

    exit(MPIMessageARG_INVALID);
}

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;
    MPISercos   sercos = MPIHandleVOID;
    MPINode     node   = MPIHandleVOID;
    MPIIdn      idn    = MPIHandleVOID;

    long    returnValue;

    long    deleteMessage;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPISercosStatus     SercosStatus;

    long    argIndex;

    MPIIdnNumber    idnNumber;
    MPIIdnData      idnData;

    MPISercosBaud   baudRate;
    MPISercosConfig sercosConfig;

    MPISercosStatus sercosStatus;

    unsigned long   attributes;

    /* 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;
        }
    }

    if (argIndex >= argc) {
        usage(argv[0]);
    }

    idnNumber = (MPIIdnNumber)(meiPlatformAtol(argv[argIndex++]));

    /* Check for unknown/invalid command line arguments */
    if (argIndex >= argc) {
        usage(argv[0]);
    }

    baudRate =
        (baud == 2)  ? MPISercosBaud2MBIT  :
        (baud == 4)  ? MPISercosBaud4MBIT  :
        (baud == 10) ? MPISercosBaud10MBIT
                     : BAUD_RATE_DEFAULT;

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

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

    /* Create sercos object */
    sercos =
        mpiSercosCreate(control,
                        sercosNumber);
    msgCHECK(mpiSercosValidate(sercos));

    returnValue =
        mpiSercosStatus(sercos,
                        &sercosStatus,
                        NULL);
    msgCHECK(returnValue);

    printf("sercos[%d] status: phase %d\n",
            sercosNumber,
            sercosStatus.phase);

    if (sercosStatus.phase < 2) {
        MPIControlConfig    controlConfig;

        printf("\nsercos[%d]: transitioning to phase 2\n",
                sercosNumber);

        returnValue =
            mpiControlConfigGet(control,
                                &controlConfig,
                                NULL);
        msgCHECK(returnValue);

        controlConfig.sampleRate = sampleRate;

#if defined(MEI_PMC)
        controlConfig.axisCount     = 8;
        controlConfig.filterCount   = 8;
        controlConfig.motionCount   = 8;
        controlConfig.motorCount    = 8;
        controlConfig.sequenceCount = 8;

        controlConfig.sercosCount = 1;
#else
        controlConfig.axisCount     = 24;
        controlConfig.filterCount   = 24;
        controlConfig.motionCount   = 24;
        controlConfig.motorCount    = 24;
        controlConfig.sequenceCount = 24;

        controlConfig.sercosCount = 3;
#endif

        returnValue =
            mpiControlConfigSet(control,
                                &controlConfig,
                                NULL);
        msgCHECK(returnValue);

        returnValue =
            mpiSercosConfigGet(sercos,
                               &sercosConfig,
                               NULL);
        msgCHECK(returnValue);

        sercosConfig.baudRate = baudRate;
        sercosConfig.xmitIntensity = intensity;

        returnValue =
            mpiSercosConfigSet(sercos,
                               &sercosConfig,
                               NULL);
        msgCHECK(returnValue);

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiSercosInit(sercos,
                              2);
        }

        returnValue =
            mpiSercosStatus(sercos,
                            &SercosStatus,
                            NULL);
        msgCHECK(returnValue);

        printf("sercos[%d] status: phase %d\n",
                sercosNumber,
                SercosStatus.phase);
    }

    node =
        mpiNodeCreate(sercos,
                      nodeNumber);
    msgCHECK(mpiNodeValidate(node));

    returnValue =
        mpiSercosNodeAppend(sercos,
                            node);
    msgCHECK(returnValue);

    idn = mpiIdnCreate(idnNumber);
    msgCHECK(mpiIdnValidate(idn));

    printf("\nsercos[%d] nodeNumber %d idnNumber %d:\n",
            sercosNumber,
            nodeNumber,
            idnNumber);

    returnValue =
        idnDisplay(node,
                   idn,
                   &attributes);
    msgCHECK(returnValue);

    if (mpiIdnFieldAttrGET(MPIIdnFieldAttrVARIABLE, attributes) == 0) {
        idnData.binary = strtoul(argv[argIndex++], NULL, 0);

        if (argIndex < argc) {
            usage(argv[0]);
        }
    }
    else {
        MPIIdnVarLength *varLength;

        varLength = &idnData.varLength;

        varLength->type = mpiIdnFieldAttrDATA_TYPE(attributes);

        switch (varLength->type) {
            case MPIIdnDataTypeTEXT: {
                varLength->as.text = argv[argIndex++];
                varLength->count   = strlen(varLength->as.text);

                if (argIndex < argc) {
                    usage(argv[0]);
                }
                break;
            }
            case MPIIdnDataTypeINVALID: {
                meiASSERT(FALSE);
                break;
            }
            default: {
                long    index;

                varLength->as.value = (MPIIdnValue *)VarData;
                varLength->count    = argc - argIndex;

                for (index = 0; index < varLength->count; index++) {
                    VarData[index] = strtoul(argv[argIndex++], NULL, 0);
                }
                break;
            }
        }
        }

    returnValue =
        mpiIdnDataSET(idn,
                      &idnData);
    msgCHECK(returnValue);

    returnValue =
        mpiNodeIdnDataSET(node,
                          idn);

    if (returnValue == MPIMessageOK) {
        returnValue =
            idnDisplay(node,
                       idn,
                       &attributes);
    }
    else {
        printf("Error 0x%x: %s\n",
                returnValue,
                mpiMessage(returnValue, NULL));

        if (returnValue == MPISercosMessageSERVICE_CHANNEL_ERROR) {
            MPISercosError  error;

            returnValue =
                mpiSercosError(sercos,
                               &error);

            if (returnValue == MPIMessageOK) {
                printf("\tSERCOS error 0x%x\n",
                        error);
            }
        }
    }

    /* Delete the IDN handle */
    if (idn != MPIHandleVOID) {
        deleteMessage = mpiIdnDelete(idn);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Clear Sercos Node list */
    if (sercos != MPIHandleVOID) {
        deleteMessage =
            mpiSercosNodeListSet(sercos,
                                 0,
                                 NULL);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the NODE handle */
    if (node != MPIHandleVOID) {
        deleteMessage = mpiNodeDelete(node);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the SERCOS handle */
    if (sercos != MPIHandleVOID) {
        deleteMessage = mpiSercosDelete(sercos);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    /* Delete the CONTROL handle */
    if (control != MPIHandleVOID) {
        deleteMessage = mpiControlDelete(control);

        if (returnValue == MPIMessageOK) {
            returnValue = deleteMessage;
        }
    }

    return ((int)returnValue);
}

long
    idnDisplay(MPINode          node,
               MPIIdn           idn,
               unsigned long    *attributes)
{
    MPIIdnElement   idnElement;
    MPIIdnField     field;

    long    returnValue;

    returnValue =
        mpiNodeIdnGET(node,
                      idn);

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiIdnElementGET(idn,
                             &idnElement);
    }

    if (returnValue == MPIMessageOK) {
        putchar('\n');

        for (field = MPIIdnFieldFIRST; field < MPIIdnFieldLAST; field++) {
            switch (field) {
                case MPIIdnFieldNUMBER: {
                    const char  *text;

                    if (returnValue == MPIMessageOK) {
                        returnValue =
                            mpiIdnNumberText(idn,
                                             &text);
                    }

                    if (returnValue == MPIMessageOK) {
                        printf("\tnumber %s\n",
                                text);
                    }
                    break;
                }
                case MPIIdnFieldNAME: {
                    printf("\tname %s\n",
                            idnElement.name);
                    break;
                }
                case MPIIdnFieldATTRIBUTES: {
                    printf("\tattributes 0x%x\n",
                            idnElement.attributes);
                    break;
                }
                case MPIIdnFieldUNIT: {
                    printf("\tunit %s\n",
                            idnElement.unit);
                    break;
                }
                case MPIIdnFieldMINIMUM: {
                    printf("\tminimum 0x%x\n",
                            idnElement.minimum.u);
                    break;
                }
                case MPIIdnFieldMAXIMUM: {
                    printf("\tmaximum 0x%x\n",
                            idnElement.maximum.u);
                    break;
                }
                case MPIIdnFieldDATA: {
                    if (mpiIdnFieldAttrGET(MPIIdnFieldAttrVARIABLE, idnElement.attributes) == 0) {
                        printf("\tdata 0x%x\n",
                                idnElement.data.binary);
                    }
                    else {
                        MPIIdnVarLength *varLength;

                        long    index;

                        varLength = &idnElement.data.varLength;

                        for (index = 0; index < varLength->count; index++) {
                            printf("\tdata[%d] ",
                                    index);

                            switch (varLength->type) {
                                case MPIIdnDataTypeBINARY: {
                                    printf("0x%x\n",
                                            varLength->as.value[index].u);
                                    break;
                                }
                                case MPIIdnDataTypeIDN: {
                                    char    idnName[32];

                                    printf("%s\n",
                                            mpiIdnNumberName(varLength->as.idn[index],
                                                             idnName));
                                    break;
                                }
                                case MPIIdnDataTypeLONG: {
                                    printf("%d\n",
                                            varLength->as.value[index].l);
                                    break;
                                }
                                case MPIIdnDataTypeTEXT: {
                                    printf("%s\n",
                                            varLength->as.text);
                                    break;
                                }
                                case MPIIdnDataTypeUNSIGNED: {
                                    printf("%u\n",
                                            varLength->as.value[index].u);
                                    break;
                                }
                                case MPIIdnDataTypeUNSIGNED_HEX: {
                                    printf("0x%x\n",
                                            varLength->as.value[index].u);
                                    break;
                                }
                                default: {
                                    break;
                                }
                            }

                            if (varLength->type == MPIIdnDataTypeTEXT) {
                                break;
                            }
                        }
                    }
                    break;
                }
                default: {
                    break;
                }
            }
        }
    }

    *attributes =
        (returnValue == MPIMessageOK)
                    ? idnElement.attributes
                    : 0;

    return (returnValue);
}


sinit1.c -- SERCOS ring initialization
/* sinit1.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/sinit1.c 15    7/23/01 2:36p Kevinh $";
#endif

/*

:SERCOS ring initialization

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 <string.h>

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

#include "apputil.h"

#if defined(ARG_MAIN_RENAME)
#define main    sinit1Main

argMainRENAME(main, sinit1)
#endif

#define BAUD_RATE_DEFAULT       (MPISercosBaud10MBIT)
#define PHASE_DEFAULT           (4)
#define SAMPLE_RATE_DEFAULT     (1000)
#define MODE_DEFAULT            (MPINodeModeOPENLOOP_POSITION_MOTOR)
#define INTENSITY_DEFAULT       (3)

/* Command line arguments and defaults */
long            baud        = -1;
long            phase       = PHASE_DEFAULT;
long            sampleRate  = SAMPLE_RATE_DEFAULT;
MPINodeMode     mode        = MODE_DEFAULT;
long            intensity   = INTENSITY_DEFAULT;

Arg argList[] = {
    {   "-baud",        ArgTypeLONG,    &baud,          },
    {   "-phase",       ArgTypeLONG,    &phase,         },
    {   "-sample",      ArgTypeLONG,    &sampleRate,    },
    {   "-mode",        ArgTypeLONG,    &mode,          },
    {   "-intensity",   ArgTypeLONG,    &intensity,     },

    {   NULL,           ArgTypeINVALID, NULL,   }
};

#if 0
#define MEI_PMC
#endif

MPISercosStatus SercosStatus;

MPIIdnList  Amplifier;
MPIIdnList  MasterData;
MPIIdnList  Phase2;
MPIIdnList  Phase3;

long
    displayError(MPISercos sercos,
                 long errorCode);

long
    idnListConfig(MPINode   node);

void
    usage(char  *programName)
{
    meiPlatformConsole("usage: %s\n\t%s\n"
                        "\t\t[-baud (%d)]\n"
                        "\t\t[-phase (%d)]\n"
                        "\t\t[-sample (%d)]\n"
                        "\t\t[-mode (%d)]\n"
                        "\t\t[-intensity (%d)]\n",
                        programName,
                        ArgUSAGE,
                        (BAUD_RATE_DEFAULT == MPISercosBaud2MBIT)  ?  2 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud4MBIT)  ?  4 :
                        (BAUD_RATE_DEFAULT == MPISercosBaud10MBIT) ? 10
                                                                   : -1,
                        PHASE_DEFAULT,
                        SAMPLE_RATE_DEFAULT,
                        MODE_DEFAULT,
                        INTENSITY_DEFAULT);

    exit(MPIMessageARG_INVALID);
}

int
    main(int    argc,
         char   *argv[])
{
    MPIControl  control;
    MPISercos   sercos;

    long    returnValue = MPIMessageOK;

    MPIControlType      controlType;
    MPIControlAddress   controlAddress;

    long    argIndex;
    long    sercosNumber;
    long    initialMotorNumber;

    MPISercosBaud       baudRate;
    MPISercosConfig     sercosConfig;
    MPIControlConfig    controlConfig;

    /* 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) {
        usage(argv[0]);
    }

    baudRate =
        (baud == 2)  ? MPISercosBaud2MBIT  :
        (baud == 4)  ? MPISercosBaud4MBIT  :
        (baud == 10) ? MPISercosBaud10MBIT
                     : BAUD_RATE_DEFAULT;

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

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

    /* Configure the controller */
    returnValue =
        mpiControlConfigGet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

#if defined(MEI_PMC)
    controlConfig.axisCount     = 8;
    controlConfig.filterCount   = 8;
    controlConfig.motionCount   = 8;
    controlConfig.motorCount    = 8;
    controlConfig.sequenceCount = 8;

    controlConfig.sercosCount = 1;
#else
    controlConfig.axisCount     = 24;
    controlConfig.filterCount   = 24;
    controlConfig.motionCount   = 24;
    controlConfig.motorCount    = 24;
    controlConfig.sequenceCount = 24;

    controlConfig.sercosCount = 4;
#endif

    returnValue =
        mpiControlConfigSet(control,
                            &controlConfig,
                            NULL);
    msgCHECK(returnValue);

    initialMotorNumber = 0;

    for (sercosNumber = 0;
         sercosNumber < controlConfig.sercosCount;
         sercosNumber++) {
        MPINode         node[MPISercosNODE_COUNT_MAX];
        MPINodeConfig   nodeConfig[MPISercosNODE_COUNT_MAX];

        long    count;
        long    index;

        returnValue = MPIMessageOK;     /* reset returnValue for next sercos object */

        if (initialMotorNumber >= MEIXmpMAX_Motors) {
            break;
        }

        count =
            sizeof( node) /
            sizeof(*node);

        for (index = 0; index < count; index++) {
            node[index]  = MPIHandleVOID;
        }

        sercos =
            mpiSercosCreate(control,
                            sercosNumber);
        returnValue = mpiSercosValidate(sercos);

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiSercosConfigGet(sercos,
                                    &sercosConfig,
                                    NULL);
        }

        if (returnValue == MPIMessageOK) {
            sercosConfig.baudRate = baudRate;
            sercosConfig.TSCYC = sampleRate;
            sercosConfig.xmitIntensity = intensity;

            returnValue =
                mpiSercosConfigSet(sercos,
                                    &sercosConfig,
                                    NULL);
        }

        if (returnValue == MPIMessageOK) {
            returnValue =
                mpiSercosStatus(sercos,
                                &SercosStatus,
                                NULL);
        }

        if (returnValue == MPIMessageOK) {
            printf("\nsercos[%d] status: phase %d\n",
                    sercosNumber,
                    SercosStatus.phase);

            if (phase <= SercosStatus.phase) {
                goto done;
            }

            if (SercosStatus.phase < 2) {
                printf("\nsercos[%d]: transitioning to phase 2\n",
                        sercosNumber);

                if (returnValue == MPIMessageOK) {
                    returnValue =
                        mpiSercosInit(sercos,
                                      2);
                }

                if (returnValue == MPIMessageOK) {
                    returnValue =
                        mpiSercosStatus(sercos,
                                        &SercosStatus,
                                        NULL);
                }

                if (returnValue == MPIMessageOK) {
                    printf("sercos[%d] status: phase %d\n",
                            sercosNumber,
                            SercosStatus.phase);
                }
            }
        }

        /* Will be in at least Phase 2 here */
        if (returnValue == MPIMessageOK) {
            for (index = 0; index < SercosStatus.nodeCount; index++) {
                if (returnValue == MPIMessageOK) {
                    node[index] = mpiNodeCreate(sercos, index);
                    returnValue = mpiNodeValidate(node[index]);
                }

                if (returnValue == MPIMessageOK) {
                    returnValue =
                        mpiNodeConfigGet(node[index],
                                         &nodeConfig[index],
                                         NULL);
                }

                if (returnValue == MPIMessageOK) {
                    printf("\tnode[%d]: address %d\n",
                            index,
                            nodeConfig[index].address);
                }
            }
        }

        if (returnValue == MPIMessageOK) {
            if (phase > 2) {
                for (index = 0; index < SercosStatus.nodeCount; index++) {
                    if (returnValue == MPIMessageOK) {
                        nodeConfig[index].motorNumber = initialMotorNumber + index;
                        nodeConfig[index].filterNumber = nodeConfig[index].motorNumber;
                        nodeConfig[index].mode = mode;

                        returnValue =
                            mpiNodeConfigSet(node[index],
                                             &nodeConfig[index],
                                             NULL);
                    }

                    if(returnValue == MPIMessageOK) {
                        returnValue =
                            mpiSercosNodeAppend(sercos,
                                                node[index]);
                    }

                    if (returnValue == MPIMessageOK) {
                        returnValue =
                            idnListConfig(node[index]);
                    }
                }

                if (returnValue == MPIMessageOK) {
                    if (SercosStatus.nodeCount > 0) {
                        printf("\nsercos[%d]: transitioning to phase %d\n",
                                sercosNumber,
                                phase);

                        returnValue =
                            mpiSercosInit(sercos,
                                          phase);
                    }
                }

                if (returnValue == MPIMessageOK) {
                    returnValue =
                        mpiSercosStatus(sercos,
                                        &SercosStatus,
                                        NULL);
                }

                if (returnValue == MPIMessageOK) {
                    initialMotorNumber += SercosStatus.nodeCount;

                    printf("sercos[%d] status: phase %d\n",
                            sercosNumber,
                            SercosStatus.phase);
                }
            }
        }

done:
        if (returnValue != MPIMessageOK) {
            const char  *text;

            text = mpiMessage(returnValue, NULL);

            printf("\nSercos[%d]: Ring Initialization Error: 0x%x:%s\n",
                    sercosNumber,
                    returnValue,
                    (text == NULL)?"":text);
        }

        /* Delete the IDNLIST handles */
        if (Amplifier != MPIHandleVOID) {
            long deleteMessage = mpiIdnListDelete(Amplifier);

            Amplifier = MPIHandleVOID;

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }
        if (MasterData != MPIHandleVOID) {
            long deleteMessage = mpiIdnListDelete(MasterData);

            MasterData = MPIHandleVOID;

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }
        if (Phase2 != MPIHandleVOID) {
            long deleteMessage = mpiIdnListDelete(Phase2);

            Phase2 = MPIHandleVOID;

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }
        if (Phase3 != MPIHandleVOID) {
            long deleteMessage = mpiIdnListDelete(Phase3);

            Phase3 = MPIHandleVOID;

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }

        /* Clear Sercos Node list */
        if (sercos != MPIHandleVOID) {
            long deleteMessage =
                mpiSercosNodeListSet(sercos,
                                     0,
                                     NULL);

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }

        /* Delete the NODE handle(s) */
        count =
            sizeof( node) /
            sizeof(*node);

        for (index = 0; index < count; index++) {
            if (node[index] != MPIHandleVOID) {
                long deleteMessage = mpiNodeDelete(node[index]);

                node[index] = MPIHandleVOID;

                if (returnValue == MPIMessageOK) {
                    returnValue = deleteMessage;
                }
            }
        }

        /* Delete the SERCOS handle */
        if (sercos != MPIHandleVOID) {
            long deleteMessage = mpiSercosDelete(sercos);

            sercos = MPIHandleVOID;

            if (returnValue == MPIMessageOK) {
                returnValue = deleteMessage;
            }
        }
    }

    /* Delete the CONTROL handle */
    returnValue = mpiControlDelete(control);
    msgCHECK(returnValue);

    return ((int)returnValue);
}

long
    displayError(MPISercos  sercos,
                 long       errorCode)
{
    long returnValue = MPIMessageOK;

    if (errorCode != MPIMessageOK) {
        long sercosNumber;

        returnValue =
            mpiSercosNumber(sercos,
                            &sercosNumber);

        if (returnValue == MPIMessageOK) {
            if (errorCode == MPISercosMessageSERVICE_CHANNEL_ERROR) {
                MPISercosError error;

                returnValue =
                    mpiSercosError(sercos,
                                   &error);

                if (returnValue == MPIMessageOK) {
                    printf("\nSercos[%d] Service Channel Error: 0x%x\n",
                            sercosNumber,
                            error);
                }
            }
            else {
                const char  *text;

                text = mpiMessage(errorCode, NULL);

                printf("\nSercos[%d] Error: 0x%x:%s\n",
                        sercosNumber,
                        errorCode,
                        (text == NULL)?"":text);
            }
        }
    }

    if (returnValue == MPIMessageOK) {
        returnValue = errorCode;
    }

    return (returnValue);
}

long
    idnListConfig(MPINode   node)
{
    long    returnValue = MPIMessageOK;

#if 0
    MPIIdn          idn;
#endif

#if 0
    MPIIdnData  idnData;
#endif

    /* Amplifier */
    if (returnValue == MPIMessageOK) {
        Amplifier = mpiIdnListCreate(MPIHandleVOID);
        returnValue = mpiIdnListValidate(Amplifier);
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListGet(node,
                              MPINodeIdnListTypeAMPLIFIER,
                              Amplifier);
    }

    if (returnValue == MPIMessageOK) {
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListSet(node,
                              MPINodeIdnListTypeAMPLIFIER,
                              Amplifier);
    }

    /* Master */
    if (returnValue == MPIMessageOK) {
        MasterData = mpiIdnListCreate(MPIHandleVOID);
        returnValue = mpiIdnListValidate(MasterData);
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListGet(node,
                              MPINodeIdnListTypeMASTER_DATA,
                              MasterData);
    }

    if (returnValue == MPIMessageOK) {
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListSet(node,
                              MPINodeIdnListTypeMASTER_DATA,
                              MasterData);
    }

#if 0
    /* Phase 2 */
    if (returnValue == MPIMessageOK) {
        Phase2 = mpiIdnListCreate(MPIHandleVOID);
        returnValue = mpiIdnListValidate(Phase2);
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListGet(node,
                              MPINodeIdnListTypePHASE2,
                              Phase2);
    }

    /* Set Phase 2 IDNs */
    if (returnValue == MPIMessageOK) {
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListSet(node,
                              MPINodeIdnListTypePHASE2,
                              Phase2);
    }
#endif

#if 0
    /* Phase3 */
    if (returnValue == MPIMessageOK) {
        Phase3 = mpiIdnListCreate(MPIHandleVOID);
        returnValue = mpiIdnListValidate(Phase3);
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListGet(node,
                              MPINodeIdnListTypePHASE3,
                              Phase3);
    }

    /* Set Phase 3 IDNs */
    if (returnValue == MPIMessageOK) {
    }

    if (returnValue == MPIMessageOK) {
        returnValue =
            mpiNodeIdnListSet(node,
                              MPINodeIdnListTypePHASE3,
                              Phase3);
    }
#endif
    return (returnValue);
}


stepcfg.c -- Configure a motor as a stepper motor
/* stepcfg.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/stepcfg.c 14    8/01/01 2:08p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    stepcfgMain

argMainRENAME(main, stepcfg)
#endif

/*

:Configure a motor as a stepper motor

This program will configure the motor and filter parameters for a motor to allow
 the motor to control a stepper motor.  The motor type is set to stepper, and
 the pulse width is set (default is 25.5 microseconds), and the loop back mode
 is set.  If loop back is set to TRUE, then the stepper pusles are read by the
 encoder input that is attached to the motor.

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 FILTER_NUMBER   (0)
#define MOTOR_NUMBER    (0)

/* LOOPBACK_CONFIG : TRUE = enable stepper loopback, FALSE = no loopback */
#define LOOPBACK_CONFIG     TRUE
/* output pulse width  (seconds) */
#define PULSE_WIDTH_VALUE   (2.55e-5)

#undef CW_CCW_STEPPERS

#if defined CW_CCW_STEPPERS
#define IO_CONFIG_A         (MEIMotorTransceiverConfigCW)
#define IO_CONFIG_B         (MEIMotorTransceiverConfigCCW)
#else
#define IO_CONFIG_A         (MEIMotorTransceiverConfigSTEP)
#define IO_CONFIG_B         (MEIMotorTransceiverConfigDIR)
#endif

#define TRANSCEIVER_ID_A    (MEIMotorTransceiverIdA)
#define TRANSCEIVER_ID_B    (MEIMotorTransceiverIdB)
#define INVERT_BIT          (FALSE)

/* 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,
                 MPIFilter          *filter,
                 long                filterNumber,
                 MPIMotor           *motor,
                 long                motorNumber)
{
    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,
                        *axis);
    msgCHECK(mpiMotionValidate(*motion));

    /* Create filter object */
    *filter =
        mpiFilterCreate(*control,
                        filterNumber);
    msgCHECK(mpiFilterValidate(*filter));

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

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

    /* Delete motor object */
    returnValue =
        mpiMotorDelete(*motor);
    msgCHECK(returnValue);

    /* Delete filter object */
    returnValue =
        mpiFilterDelete(*filter);
    msgCHECK(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);
}

/* Disable Filter Algorithm */
void disableFilterAlgorithm(MPIFilter filter)
{
    MEIFilterConfig filterConfigXmp;
    long            returnValue;

    /* Read filter configuration */
    returnValue =
        mpiFilterConfigGet(filter,
                           NULL,
                           &filterConfigXmp);
    msgCHECK(returnValue);

    /* Set filter algorithm to NONE */
    filterConfigXmp.Algorithm = MEIXmpAlgorithmNONE;

    /* Set filter configuration */
    returnValue =
        mpiFilterConfigSet(filter,
                           NULL,
                           &filterConfigXmp);
    msgCHECK(returnValue);
}

/* Configure motor for use as a stepper motor */
void configureStepperMotor(MPIMotor                     motor,
                           MEIMotorTransceiverConfig    xcvrAType,
                           long                         xcvrAInvert,
                           MEIMotorTransceiverConfig    xcvrBType,
                           long                         xcvrBInvert,
                           float                        pulseWidth,
                           long                         loopBack)
{
    MPIMotorConfig  motorConfigMPI;
    MEIMotorConfig  motorConfigXMP;
    long            returnValue;

    /* Read motor configuration */
    returnValue =
        mpiMotorConfigGet(motor,
                          &motorConfigMPI,
                          &motorConfigXMP);
    msgCHECK(returnValue);

    /* Setup motor as a stepper motor */
    motorConfigMPI.type = (MPIMotorType)MEIXmpMotorTypeSTEPPER;

    motorConfigMPI.event[MPIEventTypeAMP_FAULT].action   = MPIActionNONE;
    motorConfigMPI.event[MPIEventTypeLIMIT_ERROR].action = MPIActionNONE;

    motorConfigXMP.Transceiver[TRANSCEIVER_ID_A].Config = xcvrAType;
    motorConfigXMP.Transceiver[TRANSCEIVER_ID_B].Config = xcvrBType;
    motorConfigXMP.Transceiver[TRANSCEIVER_ID_A].Invert = xcvrAInvert;
    motorConfigXMP.Transceiver[TRANSCEIVER_ID_B].Invert = xcvrBInvert;

    motorConfigXMP.Stepper.PulseWidth = pulseWidth;

    motorConfigXMP.Stepper.Loopback = loopBack;

    /* Set motor configuration */
    returnValue =
        mpiMotorConfigSet(motor,
                          &motorConfigMPI,
                          &motorConfigXMP);
    msgCHECK(returnValue);
}

/* Set in position fine tolerance */
void setAxisFineTolerance(MPIAxis   axis,
                          float     fineTolerance)
{
    MPIAxisConfig   axisConfig;
    long            returnValue;

    /* Read axis configuration */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    /* Set axis in position fine tolerance */
    axisConfig.inPosition.tolerance.positionFine = fineTolerance;

    /* Set axis configuration */
    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);
}

int main(int    argc,
         char   *argv[])
{
    MPIControl          control;
    MPIControlType      controlType;
    MPIControlAddress   controlAddress;
    MPIMotion           motion;
    MPIAxis             axis;
    MPIFilter           filter;
    MPIMotor            motor;

    /* 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,
                &filter,
                FILTER_NUMBER,
                &motor,
                MOTOR_NUMBER);

    /* Disable Filter Algorithm */
    disableFilterAlgorithm(filter);

    /* Configure motor for use as a stepper motor */
    configureStepperMotor(motor,
                          IO_CONFIG_A,
                          INVERT_BIT,
                          IO_CONFIG_B,
                          INVERT_BIT,
                          (float)PULSE_WIDTH_VALUE,
                          LOOPBACK_CONFIG);

    /* Set in position fine tolerance */
    setAxisFineTolerance(axis,
                         (float)1.E8);

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

    return MPIMessageOK;
}


stepcfg2.c -- Configure an 8 axis XMP to support 8 Servos and 8 Steppers
/* stepCfg2.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/stepcfg2.c 8     7/23/01 2:36p Kevinh $";
#endif

/*

:Configure an 8 axis XMP to support 8 Servos and 8 Steppers

The XMP controller has the capability to control 8 servo axes as well
 as 8 stepper axes on a single controller.  The XMP uses the Xcvr
 IO for axes 0 - 7 for stepper outputs on axes 8 - 15.  This is obtained
 by redirecting the stepper controller pointer from Xcvr hardware that
 would be present on a 16 axis controller to Xcvr's 0 - 7.

Certain limitations apply:
 -No Steppers can be configured on the first 8 axes.
 -The 2nd 8 axes will not have any IO (User, Home, PosLimits, AmpEnables, etc).
 -No encoder loopback is availiable on the Stepper axes.
 -The IN_FINE position criteria must be increased for motion done to return.

The following code performs the necessary configurations to run a Step/Dir
 stepper on Motor 8 using Xcvr0 A & B.  Define CONFIG_ONLY to configure the
 XMP, but not perform any motion.

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    stepCfg2Main

argMainRENAME(main, stepCfg2)
#endif

#define AXIS_COUNT      (16)
#define FILTER_COUNT    (16)
#define MS_COUNT        (16)
#define MOTOR_COUNT     (16)

/* Command line arguments and defaults */
long    axisNumber[AXIS_COUNT]      = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long    filterNumber[FILTER_COUNT]  = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long    motorNumber[MOTOR_COUNT]    = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
long    motionNumber                = -1;   /* Use next availiable MS */
long    width                       = 255;

Arg argList[] = {
    {   NULL,       ArgTypeINVALID, NULL,   }
};

/* LOOPBACK_CONFIG : TRUE = count step pulses in encoder register, FALSE = no loopback */
#define LOOPBACK_CONFIG     TRUE
/* output pulse width  (seconds) */
#define PULSE_WIDTH_VALUE   (2.55e-5)

#undef CW_CCW_STEPPERS

#if defined CW_CCW_STEPPERS
#define IO_CONFIG_A         (MEIMotorTransceiverConfigCW)
#define IO_CONFIG_B         (MEIMotorTransceiverConfigCCW)
#else
#define IO_CONFIG_A         (MEIMotorTransceiverConfigSTEP)
#define IO_CONFIG_B         (MEIMotorTransceiverConfigDIR)
#endif

#define TRANSCEIVER_ID_A    (MEIXmpMotorIOBitXCVR_A)
#define TRANSCEIVER_ID_B    (MEIXmpMotorIOBitXCVR_B)
#define INVERT_BIT          (FALSE)

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

    MPIFilter           filter;

    MPIAxis             axis;
    MPIAxisConfig       axisConfig;     /* Axis configuration */

    MPIMotion           motion;

    MPIMotor            motorZero;
    MPIMotor            motorEight;
    MPIMotorConfig      motorZeroConfig;
    MPIMotorConfig      motorEightConfig;

    MEIMotorConfig      motorZeroConfigXmp;
    MEIMotorConfig      motorEightConfigXmp;

    MPIMotionParams params;     /* motion parameters */
    MPITrajectory   trajectory; /* motion trajectory */
    double          position;   /* final target position */

    long    argIndex;
    long    returnValue;
    long    motionDone = FALSE;
    long    stepperNumber;

    /* 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)) {
        meiPlatformConsole("usage: %s %s\n",
                            argv[0],
                            ArgUSAGE);
        exit(MPIMessageARG_INVALID);
    }

    /* Obtain a Control handle */
    control =
        mpiControlCreate(controlType,
                         &controlAddress);
    msgCHECK(mpiControlValidate(control));

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

    /* Get controller status */
    returnValue =
        mpiControlConfigGet(control,
                            &config,
                            NULL);
    msgCHECK(returnValue);

    /* Configure controller for 16 Axes, Filters, and Motors */
    config.axisCount            = AXIS_COUNT;
    config.filterCount          = FILTER_COUNT;
    config.motionCount          = MS_COUNT;
    config.motorCount           = MOTOR_COUNT;

    /* Set controller configuration */
    returnValue =
        mpiControlConfigSet(control,
                            &config,
                            NULL);
    msgCHECK(returnValue);

    /* Display controller configuration */
    printf("Controller:\n"
            "\taxisCount %d\n"
            "\tadcCount  %d\n"
            "\t cmdDacCount  %d\n"
            "\tfilterCount %d\n"
            "\tmotionCount %d\n"
            "\tmotorCount %d\n"
            "\tsequenceCount %d\n"
            "\tsampleRate    %d\n",
            config.axisCount,
            config.adcCount,
            config.cmdDacCount,
            config.filterCount,
            config.motionCount,
            config.motorCount,
            config.sequenceCount,
            config.sampleRate);

    /* Create filter object */
    filter =
        mpiFilterCreate(control,
                        filterNumber[8]);
    msgCHECK(mpiFilterValidate(filter));

    /* Configure Filter for Step algorithm */
    if (returnValue == MPIMessageOK) {
        MEIFilterConfig filterConfigXmp;

        returnValue =
            mpiFilterConfigGet(filter,
                               NULL,
                               &filterConfigXmp);
        msgCHECK(returnValue);

        filterConfigXmp.Algorithm = MEIXmpAlgorithmNONE;

        returnValue =
            mpiFilterConfigSet(filter,
                               NULL,
                               &filterConfigXmp);
        msgCHECK(returnValue);

    }

    /* Create axis object*/
    axis =
        mpiAxisCreate(control,
                      axisNumber[8]);       /* axis number */
    msgCHECK(mpiAxisValidate(axis));

    /* Configure axis */
    returnValue =
        mpiAxisConfigGet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

    axisConfig.inPosition.tolerance.positionFine = (float)10E10;

    returnValue =
        mpiAxisConfigSet(axis,
                         &axisConfig,
                         NULL);
    msgCHECK(returnValue);

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

    /* Set up motion parameters */
    trajectory.velocity     =  1000.0;      /* counts per sec */
    trajectory.acceleration = 10000.0;      /* counts per sec * sec */
    trajectory.deceleration = 10000.0;

    position = 2000.0;          /* target position (counts) */

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

    /* Create Motor0 Object */
    motorZero =
        mpiMotorCreate(control,
                       0);
    msgCHECK(mpiMotorValidate(motorZero));

    /* Create Motor8 Object */
    motorEight =
        mpiMotorCreate(control,
                       8);
        msgCHECK(mpiMotorValidate(motorEight));

    /* Get Motor0's Configuration */
    returnValue =
        mpiMotorConfigGet(motorZero,
                         &motorZeroConfig,
                         &motorZeroConfigXmp);
    msgCHECK(returnValue);

    /* Configure Xcvr A/B for Step/Dir */
    motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_A].Config = IO_CONFIG_A;
    motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_B].Config = IO_CONFIG_B;
    motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_A].Invert = INVERT_BIT;
    motorZeroConfigXmp.Transceiver[TRANSCEIVER_ID_B].Invert = INVERT_BIT;

    returnValue =
        mpiMotorConfigSet(motorZero,
                          &motorZeroConfig,
                          &motorZeroConfigXmp);
    msgCHECK(returnValue);

    printf("StepControl Pointer for Motor 0: 0x%X\n", motorZeroConfigXmp.Commutation.StepControl);

    /* Get MotorEight's Configuration */
    returnValue =
        mpiMotorConfigGet(motorEight,
                         &motorEightConfig,
                         &motorEightConfigXmp);
    msgCHECK(returnValue);

    motorEightConfigXmp.Stepper.PulseWidth = (float)PULSE_WIDTH_VALUE;
    motorEightConfigXmp.Stepper.Loopback = LOOPBACK_CONFIG;

    /* Set motorEight's Commutation.StepControl register equal to MotorZero's */
    stepperNumber = motorNumber[0];

    returnValue =
        meiMotorConfigStepper(motorEight,
                              &motorEightConfigXmp,
                              stepperNumber);  /* StepControl source location */
    msgCHECK(returnValue);

    /*  Disable limit error */
    motorEightConfig.event[MPIEventTypeLIMIT_ERROR].action          = MPIActionNONE;
    motorEightConfig.event[MPIEventTypeLIMIT_ERROR].trigger.error   = (float)10E10;

    /*  Disable home event  */
    motorEightConfig.event[MPIEventTypeHOME].action         = MPIActionNONE;

    /*  Disable amp fault event */
    motorEightConfig.event[MPIEventTypeAMP_FAULT].action    = MPIActionNONE;

    /*  Disable neg. HW limit event */
    motorEightConfig.event[MPIEventTypeLIMIT_HW_NEG].action = MPIActionNONE;

    /*  Disable pos. HW limit event */
    motorEightConfig.event[MPIEventTypeLIMIT_HW_POS].action = MPIActionNONE;

    /*  Disable neg. SW limit event */
    motorEightConfig.event[MPIEventTypeLIMIT_SW_NEG].action = MPIActionNONE;

    /*  Disable pos. SW limit event */
    motorEightConfig.event[MPIEventTypeLIMIT_SW_POS].action = MPIActionNONE;

    /*  Disable Encoder Fault event */
    motorEightConfig.event[MPIEventTypeENCODER_FAULT].action= MPIActionNONE;

    /*  Configure Motor 8 as Stepper */
    motorEightConfig.type = MPIMotorTypeSTEPPER;

    returnValue =
        mpiMotorConfigSet(motorEight,
                          &motorEightConfig,
                          &motorEightConfigXmp);
    msgCHECK(returnValue);

    /* Write MS/Axis map to controller and clear any events */
    returnValue =
        mpiMotionAction(motion,
                        MPIActionRESET);
    msgCHECK(mpiMotionValidate(motion));

    /* Verify it worked */
    returnValue =
        mpiMotorConfigGet(motorEight,
                         &motorEightConfig,
                         &motorEightConfigXmp);
    msgCHECK(returnValue);

    printf("New StepControl Pointer for Motor 8: 0x%X\n", motorEightConfigXmp.Commutation.StepControl);

#ifndef CONFIG_ONLY

    printf("Motor 8 configured for Stepper using Xcvr 0 & 1.\n"
           "Starting move on Motor 8...\n");

    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);

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

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

        switch (status.state) {
            case MPIStateIDLE: {
                motionDone = TRUE;

                /* Wait for the motor to settle */
                meiPlatformSleep(300);  /* msec */

                break;
            }

            case MPIStateERROR: {
                motionDone = TRUE;

                /* Clear any error condition(s) */
                returnValue =
                    mpiMotionAction(motion,
                                    MPIActionRESET);
                msgCHECK(returnValue);

                /* Wait for reset to take effect */
                meiPlatformSleep(100);      /* msec */

                break;
            }
            default: {
                break;
            }
        }
    }

    position = 0.0;         /* target position (counts) */
    params.trapezoidal.position     = &position;

    returnValue =
        mpiMotionStart(motion,
                       MPIMotionTypeTRAPEZOIDAL,
                       &params);
    msgCHECK(returnValue);

#endif /* CONFIG_ONLY */

    /* Delete object handles */
    returnValue = mpiMotorDelete(motorZero);
    msgCHECK(returnValue);

    returnValue = mpiMotorDelete(motorEight);
    msgCHECK(returnValue);

    returnValue = mpiFilterDelete(filter);
    msgCHECK(returnValue);

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

    return ((int)returnValue);
}


stoprate.c -- Set deceleration rate for MPIActionSTOP and MPIActionE_STOP.
/* stoprate.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/stoprate.c 8     7/23/01 2:36p Kevinh $";
#endif

/*

:Set deceleration rate for MPIActionSTOP and MPIActionE_STOP.

This sample code demonstrates how to configure the MPIActionSTOP and
MPIActionE_STOP deceleration rates for a given Motion objectr.  Unless
specified at the command line, the DEFAULT deceleration rates will be used.

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    stoprateMain

argMainRENAME(main, stoprate)
#endif

/* Define STOP and ESTOP rates in seconds */
#define STOP_RATE_DEFAULT   ((float)3.0)
#define ESTOP_RATE_DEFAULT  ((float)1.0)

/* Command line arguments and defaults */
long    motionNumber    = 0;
float   stopRate        = STOP_RATE_DEFAULT;
float   eStopRate       = ESTOP_RATE_DEFAULT;

Arg argList[] = {
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-stop",    ArgTypeFLOAT,   &stopRate,      },
    {   "-estop",   ArgTypeFLOAT,   &eStopRate,     },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

int
    main(int    argc,
         char   *argv[])
{

    MPIControl  control;        /* Motion controller handle */
    MPIMotion   motion;         /* Motion supervisor handle */

    MPIMotionConfig     motionConfig;   /* Motion supervisor configuration */

    long    returnValue;            /* Return value from library */

    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;
        }
    }

    /* Check for unknown/invalid command line arguments */
    if ((argIndex < argc) ||
        (motionNumber >= MEIXmpMAX_MSs)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-stop (%f)]\n"
                           "\t\t[-estop (%f)]\n",
                           argv[0],
                           ArgUSAGE,
                           MEIXmpMAX_MSs - 1,
                           STOP_RATE_DEFAULT,
                           ESTOP_RATE_DEFAULT);
        exit(MPIMessageARG_INVALID);
    }

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

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

    /* Create motion object */
    motion =
        mpiMotionCreate(control,
                        motionNumber,
                        MPIHandleVOID);
    msgCHECK(mpiMotionValidate(motion));

    /* Read current motion supervisor configuration */
    returnValue =
        mpiMotionConfigGet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    printf("OLD: motion %d: stopRate %f eStopRate %f\n",
            motionNumber,
            motionConfig.decelTime.stop,
            motionConfig.decelTime.eStop);

    /* Set new STOP and E_STOP deceleration rates */
    motionConfig.decelTime.stop  = stopRate;
    motionConfig.decelTime.eStop = eStopRate;

    returnValue =
        mpiMotionConfigSet(motion,
                           &motionConfig,
                           NULL);
    msgCHECK(returnValue);

    printf("NEW: motion %d: stopRate %f eStopRate %f\n",
            motionNumber,
            stopRate,
            eStopRate);

    /* Delete objects */

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

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

    return ((int)returnValue);
}


template.c -- Template application (one line description for sample app)
/* template.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/template.c 13    7/18/01 2:45p Kevinh $";
#endif

#if defined(ARG_MAIN_RENAME)
#define main    templateMain
argMainRENAME(main, template)
#endif

/*

:Template application (one line description for sample app)

detailed description

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.

The msgCHECK(...) macros used in the following sample code are intended
 to convey our strong belief that ALL error return codes should be checked.
 Actual application code should use specific error handling techniques (other
 than msgCHECKs) best suited to your internal error recovery methods.

*/

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

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

#include "apputil.h"

/* 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)
{
    long    returnValue;

    /* Obtain a control handle */
    *control =
        mpiControlCreate(controlType, controlAddress);
    msgCHECK(mpiControlValidate(*control));

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

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

    /* Delete control handle */
    returnValue =
        mpiControlDelete(*control);
    msgCHECK(returnValue);
}

/* Your first function */
void function1()
{
    printf(""); /* Dummy function call - Replace with useful code */
}

/* Your second function */
void function2()
{
    printf(""); /* Dummy function call - Replace with useful code */
}

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

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

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

    /* Place your code here! */
    function1();
    function2();

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

    return MPIMessageOK;
}


usrlim1.c -- User Limit to watch an input bit and set an output bit.
/* UsrLim1.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/usrlim1.c 12    7/23/01 2:36p Kevinh $";
#endif

/*

: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 {
    MEIXmpLimitType         Type;
    void                    *SourceAddress;
    long                    Mask;
    MEIXmpGenericValue      LimitValue;
} MEIXmpLimitCondition;

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

typedef struct {
    MEIXmpLimitCondition    Condition[MEIXmpLimitConditions];
    MEIXmpStatus            Status;
    MEIXmpLogic             Logic;
    MEIXmpLimitOutput       Output;
    long                    Count;
    long                    State;
} MEIXmpLimitData;

MEIXmpLimitTypes 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.

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

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

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

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

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

The other MEIXmpLogic 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 MEIXmpLogic 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 8 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 ! = MEIXmpLogicNEVER).

For example:
 If UserLimit 0 (motor 0) is configured for MEIXmpLogicSINGLE, then the XMP will
    only process the first UserLimit for each motor.
 If UserLimit 3 (motor 0) is configured for MEIXmpLogicSINGLE, 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
 MEIXmpLogicNEVER.

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    UsrLim1Main

argMainRENAME(main, UsrLim1)
#endif

/* Motor I/O Configurations */
#define INPUT_BIT       (MEIMotorTransceiverIdC)    /* A, B, or C */
#define INPUT_MASK      (MEIMotorTransceiverMaskC)  /* mask for input bit */
#define ACTIVE_STATE    (FALSE)                     /* trigger on active or inactive */

#define OUTPUT_BIT      (MEIMotorTransceiverIdB)    /* A, B, or C */
#define OUTPUT_MASK     (MEIMotorTransceiverMaskB)  /* mask for output bit */
#define OUTPUT_INVERT   (TRUE)                      /* inverted or normal */

/* User Limit Event configuration */
#define EVENT_TYPE      (MEIEventTypeLIMIT_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,
                      MEIEventType 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;

    MEIMotorConfig  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 >= MEIXmpMAX_Motors)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-motor # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_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);
    meiEventMaskALL(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 */
    meiASSERT(service != NULL);

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

    motorConfigXmp.Transceiver[INPUT_BIT].Config = MEIMotorTransceiverConfigINPUT;

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

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

    motorConfigXmp.Transceiver[OUTPUT_BIT].Config = MEIMotorTransceiverConfigOUTPUT;
    motorConfigXmp.Transceiver[OUTPUT_BIT].Invert = OUTPUT_INVERT;

    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 (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MEIEventStatusInfo  *info;

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

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

            info = (MEIEventStatusInfo *)eventStatus.info;

            switch (eventStatus.type) {
                /* User Limit Event from motor source */
                case MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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,
                      MEIEventType eventType)
{
    MPIControl          control;

    MEIXmpData          *firmware;

    MEIMotorEventConfig motorEventConfig;
    MEIXmpStatus        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 MEIEventTypeLIMIT_USER0: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER0);
                break;
            }
            case MEIEventTypeLIMIT_USER1: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER1);
                break;
            }
            case MEIEventTypeLIMIT_USER2: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER2);
                break;
            }
            case MEIEventTypeLIMIT_USER3: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER3);
                break;
            }
            case MEIEventTypeLIMIT_USER4: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER4);
                break;
            }
            case MEIEventTypeLIMIT_USER5: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER5);
                break;
            }
            case MEIEventTypeLIMIT_USER6: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER6);
                break;
            }
            case MEIEventTypeLIMIT_USER7: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_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
            MEIXmpLimitTypeBIT_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 = MEIXmpLimitTypeBIT_CMP;
        motorEventConfig.Condition[0].SourceAddress =
            &firmware->Motor[motorIndex].IO.DedicatedIN.IO;     /* input address */
        motorEventConfig.Condition[0].Mask = inputMask;         /* AND mask */
        motorEventConfig.Condition[0].LimitValue.l =
            inputActiveState ? inputMask : 0x0;                 /* expected value */

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

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

        motorEventConfig.Output.OutputPtr =
            &firmware->Motor[motorIndex].IO.MotorOutput;    /* 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;
}


usrlim2.c -- Position comparison using User Limits to generate events.
/* UsrLim2.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.
 */

/*

:Position comparison using User Limits to generate events.

This sample code shows how to configure the XMP controller's User Limits
 to compare an axis' actual position to a specific position value.  If the
 actual position is greater than or equal to the value specified, then
 the controller will generate a User Event to the Host.

The function CompareLimitSet(...) demonstrates how to configure a
 User Limit for position compare.

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 {
    MEIXmpLimitType         Type;
    void                    *SourceAddress;
    long                    Mask;
    MEIXmpGenericValue      LimitValue;
} MEIXmpLimitCondition;

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

typedef struct {
    MEIXmpLimitCondition    Condition[MEIXmpLimitConditions];
    MEIXmpStatus            Status;
    MEIXmpLogic             Logic;
    MEIXmpLimitOutput       Output;
    long                    Count;
    long                    State;
} MEIXmpLimitData;

MEIXmpLimitTypes 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.

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

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

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

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

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

The other MEIXmpLogic 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 MEIXmpLogic 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 8 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 ! = MEIXmpLogicNEVER).

For example:
 If UserLimit 0 (motor 0) is configured for MEIXmpLogicSINGLE, then the XMP will
    only process the first UserLimit for each motor.
 If UserLimit 3 (motor 0) is configured for MEIXmpLogicSINGLE, 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
 MEIXmpLogicNEVER.

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    UsrLim2Main

argMainRENAME(main, UsrLim2)
#endif

#define MOTION_COUNT        (2)

/* User Limit configurations */
#define EVENT_TYPE          (MEIEventTypeLIMIT_USER0)   /* 0, 1, 2...7 */
#define COMPARE_POSITION    (10000)                     /* Actual Position */

/* Command line arguments and defaults */
long            axisNumber      = 0;
long            motionNumber    = 0;
long            motorNumber     = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-motor",   ArgTypeLONG,    &motorNumber,   },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT] = {
    20000.0,
    0.0,
};

MPITrajectory trajectory[MOTION_COUNT] = {
    /* velocity     accel       decel       jerkPercent */
    { 10000.0,      1000000.0,  1000000.0,  0.0,    },
    { 10000.0,      100000.0,   100000.0,   0.0,    },
};

/* Motion Parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0], &position[0],   },
    {   &trajectory[1], &position[1],   },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0], &position[0],   },
    {   &trajectory[1], &position[1],   },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0], },
    {   &trajectory[1], },
};

/* Function Prototypes */
long CompareLimitSet(MPIAxis axis,
                     MPIMotor motor,
                     long position,
                     MEIEventType 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;

    long    returnValue;    /* return value from library */

    long    index;
    long    motionDone;     /* flag when Done occurs */

    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) ||
        (axisNumber >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motorNumber >= MEIXmpMAX_Motors) ||
        (motionType < MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

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

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

    /* 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);
    meiEventMaskALL(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 */
    meiASSERT(service != NULL);

    /* Configure the Position Compare, using a User Limit */
    returnValue =
        CompareLimitSet(axis,
                        motor,
                        COMPARE_POSITION,
                        EVENT_TYPE);
    msgCHECK(returnValue);

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

    /* Loop repeatedly */
    index       = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MEIEventStatusInfo  *info;

        if (motionDone) {
            MPIMotionParams     motionParams;       /* motion parameters */

            /* fill in the MPIMotionParams structure */
            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            printf("\n\nMotion Start...");

            /* Start Motion */
            returnValue =
                mpiMotionStart(motion,
                               motionType,
                               &motionParams);
            msgCHECK(returnValue);

            motionDone = FALSE;
        }

        /* Wait for events */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        info = (MEIEventStatusInfo *)eventStatus.info;

        switch (eventStatus.type) {
            /* In Coarse Event from axis source */
            case MEIEventTypeIN_POSITION_COARSE: {
                printf("\nInCoarse (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeIN_POSITION_FINE: {
                printf("\nInFine (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeAT_TARGET: {
                printf("\nAtTarget (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* Motion Done Event from motion source */
            case MPIEventTypeMOTION_DONE: {
                printf("\nDone (%ld)",
                       info->data.motion.sampleCounter);

                motionDone = TRUE;

                if (++index >= MOTION_COUNT) {
                    index = 0;
                }
                break;
            }
            /* User Limit Event from motor source */
            case MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    returnValue = mpiAxisDelete(axis);
    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);
}

long CompareLimitSet(MPIAxis axis,
                     MPIMotor motor,
                     long position,
                     MEIEventType eventType)
{
    MEIXmpAxis          *xmpAxis;

    MEIMotorEventConfig motorEventConfig;
    MEIXmpStatus        status;

    long                returnValue;
    MPIEventMask        resetMask;

    returnValue  =
        mpiAxisMemory(axis,
                      (void **)&xmpAxis);

    if (returnValue == MPIMessageOK) {
        returnValue  =
            mpiAxisMemory(axis,
                          (void **)&xmpAxis);
    }

    mpiEventMaskCLEAR(resetMask);

    if (returnValue == MPIMessageOK) {
        switch (eventType) {
            case MEIEventTypeLIMIT_USER0: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER0);
                break;
            }
            case MEIEventTypeLIMIT_USER1: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER1);
                break;
            }
            case MEIEventTypeLIMIT_USER2: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER2);
                break;
            }
            case MEIEventTypeLIMIT_USER3: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER3);
                break;
            }
            case MEIEventTypeLIMIT_USER4: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER4);
                break;
            }
            case MEIEventTypeLIMIT_USER5: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER5);
                break;
            }
            case MEIEventTypeLIMIT_USER6: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER6);
                break;
            }
            case MEIEventTypeLIMIT_USER7: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_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
            MEIXmpLimitTypeGT (greater than).  Thus, when the value in
            SourceAddress is "GT" (greater than) the value in LimitValue.l,
            then the Condition[0] block is TRUE.
        */
        motorEventConfig.Condition[0].Type = MEIXmpLimitTypeGT;
        motorEventConfig.Condition[0].SourceAddress = &(xmpAxis->ActualPosition);
        motorEventConfig.Condition[0].Mask = 0xffffffff;
        motorEventConfig.Condition[0].LimitValue.l = position;

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

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

        /* Disable the output feature */
        motorEventConfig.Output.OutputPtr = NULL;
        motorEventConfig.Output.AndMask = 0x0;
        motorEventConfig.Output.OrMask = 0x0;
        motorEventConfig.Output.Enabled = 0;

        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;
}


usrlim3.c -- Position comparison using User Limits to generate events and outputs.
/* UsrLim3.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.
 */

/*

:Position comparison using User Limits to generate events and outputs.

This sample code shows how to configure the XMP controller's User Limits
 to compare an axis' actual position to a specific position value.  If the
 actual position is greater than or equal to the value specified, then
 the controller will generate a User Event to the Host.  Additionally,
 a Transceiver is configured for an output.  When the User Limit triggers
 an event, an output bit will be set or cleared.

The function CompareLimitSet(...) demonstrates how to configure a
 User Limit for position compare.  There are two positions compared,
 "positionEnable" and "positionDisable" which specify the range in which
 the output is written.  The output bit is specified in the "outputMask"
 and the state is specified by "enableOutput".

Note, each User Limit configuration can only apply a single output AND and
 OR mask.  Thus, to set an output requires a User Limit, and to clear
 an output requires another User Limit.  Be careful not to configure the
 position compare values that would cause more than one User Limit to write
 to the output simultaneously.

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 {
    MEIXmpLimitType         Type;
    void                    *SourceAddress;
    long                    Mask;
    MEIXmpGenericValue      LimitValue;
} MEIXmpLimitCondition;

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

typedef struct {
    MEIXmpLimitCondition    Condition[MEIXmpLimitConditions];
    MEIXmpStatus            Status;
    MEIXmpLogic             Logic;
    MEIXmpLimitOutput       Output;
    long                    Count;
    long                    State;
} MEIXmpLimitData;

MEIXmpLimitTypes 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.

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

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

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

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

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

The other MEIXmpLogic 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 MEIXmpLogic 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 8 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 ! = MEIXmpLogicNEVER).

For example:
 If UserLimit 0 (motor 0) is configured for MEIXmpLogicSINGLE, then the XMP will
    only process the first UserLimit for each motor.
 If UserLimit 3 (motor 0) is configured for MEIXmpLogicSINGLE, 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
 MEIXmpLogicNEVER.

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    UsrLim3Main

argMainRENAME(main, UsrLim3)
#endif

#define MOTION_COUNT        (2)

/* Motor I/O Configurations */
#define OUTPUT_BIT      (MEIMotorTransceiverIdA)    /* A, B, or C */
#define OUTPUT_MASK     (MEIMotorTransceiverMaskA)  /* mask for output bit */
#define OUTPUT_INVERT   (TRUE)                      /* inverted or normal */

/* Compare positions to enable/disable output */
long comparePosition[] = {
    1000,   /* enable */
    2000,   /* disable */
    5000,
    6000,
    10000,
    11000,
    15000,
    16000   /* disable */
};

/* User Limits for compare positions */
MEIEventType eventType[] = {
    MEIEventTypeLIMIT_USER0,
    MEIEventTypeLIMIT_USER1,
    MEIEventTypeLIMIT_USER2,
    MEIEventTypeLIMIT_USER3,
    MEIEventTypeLIMIT_USER4,
    MEIEventTypeLIMIT_USER5,
    MEIEventTypeLIMIT_USER6
};

#define LIMIT_COUNT (sizeof(eventType) / sizeof(long))

/* Command line arguments and defaults */
long            axisNumber      = 0;
long            motionNumber    = 0;
long            motorNumber     = 0;
MPIMotionType   motionType      = MPIMotionTypeS_CURVE;

Arg argList[] = {
    {   "-axis",    ArgTypeLONG,    &axisNumber,    },
    {   "-motion",  ArgTypeLONG,    &motionNumber,  },
    {   "-motor",   ArgTypeLONG,    &motorNumber,   },
    {   "-type",    ArgTypeLONG,    &motionType,    },

    {   NULL,       ArgTypeINVALID, NULL,   }
};

double position[MOTION_COUNT] = {
    25000.0,
    0.0,
};

MPITrajectory trajectory[MOTION_COUNT] = {
    /* velocity     accel       decel       jerkPercent */
    { 1000.0,       1000000.0,  1000000.0,  0.0,    },
    { 10000.0,      100000.0,   100000.0,   0.0,    },
};

/* Motion Parameters */
MPIMotionSCurve sCurve[MOTION_COUNT] = {
    {   &trajectory[0], &position[0],   },
    {   &trajectory[1], &position[1],   },
};

MPIMotionTrapezoidal    trapezoidal[MOTION_COUNT] = {
    {   &trajectory[0], &position[0],   },
    {   &trajectory[1], &position[1],   },
};

MPIMotionVelocity   velocity[MOTION_COUNT] = {
    {   &trajectory[0], },
    {   &trajectory[1], },
};

/* Function Prototypes */
long CompareLimitSet(MPIAxis axis,
                     MPIMotor motor,
                     long positionEnable,
                     long positionDisable,
                     long outputMask,
                     long enableOutput,
                     MEIEventType 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;
    MEIMotorConfig  motorConfigXmp;  /* XMP motor I/O configuration */

    long    returnValue;    /* return value from library */

    long    index;
    long    motionDone;     /* flag when Done occurs */

    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) ||
        (axisNumber >= MEIXmpMAX_Axes) ||
        (motionNumber >= MEIXmpMAX_MSs) ||
        (motorNumber >= MEIXmpMAX_Motors) ||
        (motionType < MPIMotionTypeFIRST) ||
        (motionType >= MEIMotionTypeLAST)) {
        meiPlatformConsole("usage: %s %s\n"
                           "\t\t[-axis # (0 .. %d)]\n"
                           "\t\t[-motion # (0 .. %d)]\n"
                           "\t\t[-motor # (0 .. %d)]\n"
                           "\t\t[-type # (0 .. %d)]\n",
                            argv[0],
                            ArgUSAGE,
                            MEIXmpMAX_Axes - 1,
                            MEIXmpMAX_MSs - 1,
                            MEIXmpMAX_Motors - 1,
                            MEIMotionTypeLAST - 1);
        exit(MPIMessageARG_INVALID);
    }

    switch (motionType) {
        case MPIMotionTypeS_CURVE:
        case MPIMotionTypeTRAPEZOIDAL:
        case MPIMotionTypeVELOCITY: {
            break;
        }
        default: {
            meiPlatformConsole("%s: %d: motion type not available\n",
                                argv[0],
                                motionType);
            exit(MPIMessageUNSUPPORTED);
            break;
        }
    }

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

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

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

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

    /* 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);
    meiEventMaskALL(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 */
    meiASSERT(service != NULL);

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

    motorConfigXmp.Transceiver[OUTPUT_BIT].Config = MEIMotorTransceiverConfigOUTPUT;
    motorConfigXmp.Transceiver[OUTPUT_BIT].Invert = OUTPUT_INVERT;

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

    /* Configure the Position Compares, using User Limits */
    for (index = 0; index < (long)LIMIT_COUNT; index++) {
        long enableOutput = ((index % 2) ? FALSE:TRUE);

        printf("\nEn:%d", enableOutput);

        returnValue =
            CompareLimitSet(axis,
                            motor,
                            comparePosition[index],
                            comparePosition[index + 1],
                            OUTPUT_MASK,
                            enableOutput,
                            eventType[index]);
        msgCHECK(returnValue);
    }

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

    /* Loop repeatedly */
    index       = 0;
    motionDone  = TRUE;
    while (meiPlatformKey(MPIWaitPOLL) <= 0) {
        MPIEventStatus      eventStatus;
        MEIEventStatusInfo  *info;

        if (motionDone) {
            MPIMotionParams     motionParams;       /* motion parameters */

            /* fill in the MPIMotionParams structure */
            switch (motionType) {
                case MPIMotionTypeS_CURVE: {
                    motionParams.sCurve = sCurve[index];
                    break;
                }
                case MPIMotionTypeTRAPEZOIDAL: {
                    motionParams.trapezoidal = trapezoidal[index];
                    break;
                }
                case MPIMotionTypeVELOCITY: {
                    motionParams.velocity = velocity[index];
                    break;
                }
                default: {
                    meiASSERT(FALSE);
                    break;
                }
            }

            printf("\n\nMotion Start...");

            /* Start Motion */
            returnValue =
                mpiMotionStart(motion,
                               motionType,
                               &motionParams);
            msgCHECK(returnValue);

            motionDone = FALSE;
        }

        /* Wait for events */
        returnValue =
            mpiNotifyEventWait(notify,
                               &eventStatus,
                               MPIWaitFOREVER);
        msgCHECK(returnValue);

        info = (MEIEventStatusInfo *)eventStatus.info;

        switch (eventStatus.type) {
            /* In Coarse Event from axis source */
            case MEIEventTypeIN_POSITION_COARSE: {
                printf("\nInCoarse (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeIN_POSITION_FINE: {
                printf("\nInFine (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* In Fine Event from axis source */
            case MEIEventTypeAT_TARGET: {
                printf("\nAtTarget (%ld)",
                       info->data.axis.sampleCounter);
                break;
            }
            /* Motion Done Event from motion source */
            case MPIEventTypeMOTION_DONE: {
                printf("\nDone (%ld)",
                       info->data.motion.sampleCounter);

                motionDone = TRUE;

                if (++index >= MOTION_COUNT) {
                    index = 0;
                }
                break;
            }
            /* User Limit Event from motor source */
            case MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 MEIEventTypeLIMIT_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 = mpiMotorDelete(motor);
    msgCHECK(returnValue);

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

    returnValue = mpiAxisDelete(axis);
    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);
}

long CompareLimitSet(MPIAxis axis,
                     MPIMotor motor,
                     long positionEnable,
                     long positionDisable,
                     long outputMask,
                     long enableOutput,
                     MEIEventType eventType)
{
    MPIControl          control;
    MEIXmpAxis          *xmpAxis;
    MEIXmpData          *firmware;

    MEIMotorEventConfig motorEventConfig;
    MEIXmpStatus        status;

    long                motorIndex;
    long                returnValue;
    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);
    }

    if (returnValue == MPIMessageOK) {
        returnValue  =
            mpiAxisMemory(axis,
                          &(void *)xmpAxis);
    }

    if (returnValue == MPIMessageOK) {
        returnValue  =
            mpiAxisMemory(axis,
                          &(void *)xmpAxis);
    }

    mpiEventMaskCLEAR(resetMask);

    if (returnValue == MPIMessageOK) {
        switch (eventType) {
            case MEIEventTypeLIMIT_USER0: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER0);
                break;
            }
            case MEIEventTypeLIMIT_USER1: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER1);
                break;
            }
            case MEIEventTypeLIMIT_USER2: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER2);
                break;
            }
            case MEIEventTypeLIMIT_USER3: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER3);
                break;
            }
            case MEIEventTypeLIMIT_USER4: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER4);
                break;
            }
            case MEIEventTypeLIMIT_USER5: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER5);
                break;
            }
            case MEIEventTypeLIMIT_USER6: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER6);
                break;
            }
            case MEIEventTypeLIMIT_USER7: {
                status = MEIXmpStatusLIMIT;
                mpiEventMaskSET(resetMask, MEIEventTypeLIMIT_USER7);
                break;
            }
            default:
                printf("\nError, invalid event type\n");
                break;
        }

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

    if (returnValue == MPIMessageOK) {
        /* Write to Output between positionEnable and positionDisable */
        if (positionDisable > positionEnable ) {
            motorEventConfig.Condition[0].Type = MEIXmpLimitTypeGE;
            motorEventConfig.Condition[1].Type = MEIXmpLimitTypeLT;
        }

        /* Write to Output between positionDisable and positionEnable */
        if (positionDisable <= positionEnable ) {
            motorEventConfig.Condition[0].Type = MEIXmpLimitTypeLT;
            motorEventConfig.Condition[1].Type = MEIXmpLimitTypeGE;
        }

        if (enableOutput) {
            /* Enable output */
            motorEventConfig.Output.AndMask = 0xFFFFFFFF;
            motorEventConfig.Output.OrMask = outputMask;
        }
        else {
            /* Disable Output */
            motorEventConfig.Output.AndMask = (~outputMask);
            motorEventConfig.Output.OrMask = 0x0;
        }

        /* Set up the Condition[0] block. */
        motorEventConfig.Condition[0].SourceAddress = &(xmpAxis->ActualPosition);
        motorEventConfig.Condition[0].Mask = 0xffffffff;
        motorEventConfig.Condition[0].LimitValue.l = positionEnable;

        /* Set up the Condition[1] block. */
        motorEventConfig.Condition[1].SourceAddress = &(xmpAxis->ActualPosition);
        motorEventConfig.Condition[1].Mask = 0xffffffff;
        motorEventConfig.Condition[1].LimitValue.l = positionDisable;

        motorEventConfig.Status = status;
        /* Determine logic result from Condition[0] AND Condition[1] */
        motorEventConfig.Logic  = MEIXmpLogicAND;

        motorEventConfig.Output.OutputPtr =
            &firmware->Motor[motorIndex].IO.MotorOutput;    /* output address */
        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;
}


XMP Hardware Index

CONTENTS:
INDEX
A
Active high wiring CH3: Drive Enable Wiring
Active low wiring CH3: Drive Enable Wiring
ADC CH6: Analog Inputs
AGnd CH:3 Analog Inputs
Amp Enable CH3: Drive Enable Wiring
Amp Fault Input CH3: Drive Enable Wiring
Amp Polarity CH3: Drive Enable Wiring
Amp_En_Collector CH3: Drive Enable Wiring
Amp_En_Emitter CH3: Drive Enable Wiring
Amp_Flt_IN CH3: Drive Enable Wiring
Amp_Flt_Rtn CH3: Drive Enable Wiring
Analog Devices:
21061 floating point DSP (SHARC) CH6: SHARC DSP Processor Subsystem
Analog Drives:
amplifier enabling CH3: Drive Enable Wiring
command signal CH3: Connect to Analog Servo Amplifiers
configuring CH3: Configuring Analog Connections
connections to servo motors CH3: Configuring Analog Connections
connections to step motors CH3: Configuring Analog Connections
electrical requirements CH1: Host Computer Electrical Requirements
wiring CH3: Drive Enable Wiring
Analog Inputs CH:3 Analog Inputs
Analog inputs CH6: Analog Inputs
Analog power supply CH6: Architectural Overview
Analog_IN CH:3 Analog Inputs
Auxiliary DAC CH6: Analog Inputs

B
Bi-directional opto-inputs and -outputs CH1: Host Computer Electrical Requirements
Bios CH6: Analog Inputs
Boot-up (motion application) CH6: XMP Data Architecture
Broken wire detection CH3: Connect System I/O
Brush servo motors
connection to XMP controllers CH3: Configuring Analog Connections
Bus interface CH2: Introduction , CH2: PMC Bus , CH6: Host Bus
expansion boards CH2: CPCI-6U Bus
Riptide CH6: XMP Data Architecture
XMP-CPCI-3U CH2: CPCI-3U Bus
XMP-CPCI-6U CH2: CPCI-6U Bus
XMP-PCI CH5: PCI Bus
XMP-PMC CH2: PMC Bus

C
Cable
bend radius limits in SERCOS CH5: SERCOS Connection Hardware
fiber optic CH5: Introduction , CH5: SERCOS Connection Hardware , CH5: XMP-SERCOS Connector Ports
SERCOS CH5: Introduction , CH5: SERCOS Connection Hardware
Cable, VHDCI CH4: Introduction
Capture CH6: XMP Data Architecture
CBL-68 cable CH4: Introduction
Clock generator CH6: Architectural Overview
Cmd_Dac_OUT CH3: Connect to Analog Servo Amplifiers
Command voltage output CH6: Analog Inputs
Common Gnd logic CH3: Connect System I/O
Common Vcc logic CH3: Connect System I/O
Connection
SERCOS CH5: SERCOS Connection Hardware
STC-136 CH3: Introduction
VHDCI CH4: Introduction
XMP-analog I/O CH4: Introduction
Control objects CH6: XMP Data Architecture
CPCI
bus connectors CH2: SERCOS Connection Hardware , CH2: XMP Controller Installation
CPCI-3U
bus connector CH4: CPCI-3U
form factor CH1: XMP Hardware , CH1: XMP Hardware
XMP controller installation CH1: XMP Controller Installation
CPCI-6U
form factor CH1: XMP Hardware , CH1: XMP Hardware
SERCOS CH5: XMP-SERCOS Connector Ports
XMP controller installation CH1: XMP Controller Installation

D
DAC
auxiliary CH6: Analog Inputs
calibration and activation CH6: SHARC DSP Processor Subsystem
circuitry CH6: Analog Inputs
DACs in Motion Blocks CH6: Analog Inputs
output protection CH6: Analog Inputs
output response to resets CH6: Analog Inputs
outputs CH6: Analog Inputs
servo command output CH6: Analog Inputs
DACs CH6: Digital-to-Analog Converter (DAC) Subsystem
Data architecture CH6: Analog Inputs
Dedicated opto-inputs, specifications CH1:Host Computer Electrical Requirements
Dedicated opto-outputs, specifications CH1: Host Computer Electrical Requirements
Delete objects CH6: XMP Data Architecture
Device driver CH6: XMP Data Architecture
Devices window CH6: XMP Data Architecture
Differential encoders CH3: Introduction 3
Digital noise filtering, encoder CH6: Host Bus
Digital-to-analog (DAC)
outputs CH6: Analog Inputs
Digital-to-analog converter (DAC) CH6: Digital-to-Analog Converter (DAC) Subsystem
DSP CH6: SHARC DSP Processor Subsystem
(diagram) CH6: SHARC DSP Processor Subsystem
DSP RAM CH6: SHARC DSP Processor Subsystem
Dual-loop control CH3: Drive Enable Wiring

E
Ejectors, and CPCI boards CH1: XMP Controller Installation , CH1: XMP Controller Installation
Electrical requirements
encoders CH1: Host Computer Electrical Requirements, CH1: Host Computer Electrical Requirements
input voltages CH3: Introduction
XMP controller CH1: Host Computer Electrical Requirements
Electrostatic discharge (ESD)
installation precautions CH1: XMP Controller Installation
Enc CH3: Introduction 3, CH3: Drive Enable Wiring
Encoders
broken wire detection CH3: Connect System I/O , CH6: Host Bus , CH6: SHARC DSP Processor Subsystem
differential CH3: Introduction 3
digital noise filtering CH6: Host Bus
digital quadrature CH3: Introduction 3
dual-loop CH3: Drive Enable Wiring
Encoders (cont.)
electrical requirements CH1: Host Computer Electrical Requirements, CH1: Host Computer Electrical Requirements
illegal state detection CH3: Connect System I/O
inputs CH6: Host Bus
single-ended CH3: Drive Enable Wiring
wiring CH3: Introduction 3
E-Stop input CH3: Connect System I/O
ESTOP_IN CH3: Connect System I/O
Expansion board CH6: Analog Inputs , CH6: Analog Inputs
Expansion boards
bus connectivity CH2: Introduction
connection to main CH2: Introduction

F
Fail safe wiring CH3: Drive Enable Wiring
Fault monitor CH6: Analog Inputs
Field programmable field array (FPGA) CH6: Analog Inputs
Field Programmable Gate Array (FPGA) CH6: XMP Data Architecture
Flash memory CH6: SHARC DSP Processor Subsystem , CH6: Analog Inputs
Form factors
CPCI-3U CH1: XMP Hardware , CH1: XMP Hardware
CPCI-6U CH1: XMP Hardware , CH1: XMP Hardware
PCI CH1: XMP Hardware , CH1: XMP Hardware
PMC CH1: XMP Hardware , CH1: XMP Hardware
FPGA (Field Programmable Field Array) CH6: Analog Inputs
FPGA (Field Programmable Gate Array) CH6: XMP Data Architecture

G
Generator, clock CH6: Architectural Overview

H
Hard reset CH6: Analog Inputs
HFBR-1505 transmitter, specifications CH5: Introduction
HFBR-2505A receiver, specifications CH5: Introduction
Home event CH6: XMP Data Architecture
Home sensors CH3: Connect System I/O
Home_IN CH3: Connect System I/O , CH3: Connect System I/O
HomeLim_Rtn CH3: Connect System I/O , CH3: Connect System I/O , CH3: Connect System I/O , CH3: Drive Enable Wiring
Homing CH6: XMP Data Architecture

I
IDNs CH5: SERCOS Connection Hardware
Illegal state detection CH3: Connect System I/O
Initialization (controller) CH6: SHARC DSP Processor Subsystem
Input-output (I/O)
analog inputs CH6: Analog Inputs
backplane connection CH3: Introduction
bi-directional opto-inputs CH1: Host Computer Electrical Requirements
bi-directional opto-outputs CH1: Host Computer Electrical Requirements
connectors CH4: Introduction
digital-to-analog (DAC) CH6: Analog Inputs
opto-input specifications CH1:Host Computer Electrical Requirements
optoisolation CH3: Introduction
opto-output specifications CH1: Host Computer Electrical Requirements
SERCOS CH5: Introduction CH5: Assistance with SERCOS Networks
STC-136 terminal blocks CH3: Introduction
XMP-CPCI-3U CH4: CPCI-3U
XMP-CPCI-6U CH4: Introduction CH2: PCI Bus
XMP-PCI CH4: XMP-PCI CH5: SERCOS Connection Hardware
XMP-PMC CH4: XMP-SERCOS-PMC, CH5: Introduction CH5: Assistance with SERCOS Networks
Installation
XMP controllers CH1: XMP Hardware CH2: Introduction
XMP-CPCI-3U controllers CH1: XMP Controller Installation
XMP-CPCI-6U controllers CH1: XMP Controller Installation
XMP-PCI controllers CH1: XMP Controller Installation
XMP-PMC controllers CH1: XMP Controller Installation
Interface CPLD CH6: Analog Inputs

J
J0-1 (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J10-11 (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J1CH2: PMC Bus (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J1CH4: XMP-PCI (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J2 (backplane connector on XMP-CPCI-3U) CH4: CPCI-3U
JCH5: PCI Bus (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J3 (backplane connector on XMP-CPCI-6U, expansion) CH4: CPCI-6U Expansion Board, Backplane Connectors
J3 (backplane connector on XMP-CPCI-6U, main) CH4: CPCI-6U
J4 (backplane connector on XMP-CPCI-6U) CH4: XMP-PCI, CH4: CPCI-6U Expansion Board, Backplane Connectors
J4-5 (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J5 (backplane connector on XMP-CPCI-6U, expansion) CH4: CPCI-6U Expansion Board, Backplane Connectors
J5 (backplane connector on XMP-CPCI-6U, main) CH4: XMP-PCI
J6-7 (VHDCI connector on XMP-PCI) CH4: XMP-PCI
J8-9 (VHDCI connector on XMP-PCI) CH4: XMP-PCI

L
Latency for position capture CH6: Host Bus
Lattice CH6: Analog Inputs
Limit sensors CH3: Connect System I/O
Limit switches CH6: XMP Data Architecture

M
Main board CH6: Analog Inputs , CH6: Analog Inputs
Memory map, XMP CH6: Analog Inputs
Motion blocks CH6: Analog Inputs , CH6: Analog Inputs , CH6: SHARC DSP Processor Subsystem
Motion Console
amp enable CH3: Drive Enable Wiring
amp polarity CH3: Drive Enable Wiring
amplifier enabling CH3: Drive Enable Wiring
configuring stepper motors CH3: Configuring Analog Connections
XCVR inversion CH3: Configuring Analog Connections
Motor blocks CH6: Analog Inputs , CH6: Analog Inputs
Motors
brush servo CH3: Configuring Analog Connections
brushless servo CH3:Configuring Analog Connections
open-loop step CH3: Configuring Analog Connections
Multiplexers CH6: Analog Inputs

N
Neg_Lim_IN CH3: Connect System I/O , CH3: Connect System I/O
Nodes, SERCOS CH5: Introduction
Noise filtering, (digital) in encoder CH6: Host Bus

O
Open-loop step motors CH3: Configuring Analog Connections
Optical power, SERCOS CH5: SERCOS Connection Hardware
Origin CH6: XMP Data Architecture

P
PCI CH6: Analog Inputs
form factor CH1: XMP Hardware , CH1: XMP Hardware
XMP-PCI controller installation CH1: XMP Controller Installation
PIDNs CH5: SERCOS Connection Hardware
Platforms
LynxOS CH1: XMP Hardware
PharLap CH1: XMP Hardware
QNX CH1: XMP Hardware
VenturComRTSS CH1: XMP Hardware
VxWorks CH1: XMP Hardware
Windows2000 CH1: XMP Hardware
Windows95/98 CH1: XMP Hardware
WindowsNT CH1: XMP Hardware
PMC
form factor CH1: XMP Hardware , CH1: XMP Hardware
SERCOS CH5: XMP-SERCOS Connector Ports
XMP-PMC controller installation CH1: XMP Controller Installation
Pos_Lim_IN CH3: Connect System I/O , CH3: Connect System I/O
Position capture
for Motion Blocks CH6: Host Bus
in scale interpolation CH6: Host Bus
Position compare, in scale interpolation CH6: Host Bus
Position error CH6: SHARC DSP Processor Subsystem
Power supervisor CH6: Analog Inputs
Power supply, analog CH6: Architectural Overview
Power-up sequence CH6: Analog Inputs

R
Reset
hard CH6: Analog Inputs
soft CH6: Analog Inputs
RESET_IN CH3: Drive Enable Wiring
Resets CH6: Analog Inputs
DAC output response to CH6: Analog Inputs
Ribbon cable (main-expansion boards) CH2: Introduction
Rings, SERCOS CH5: Introduction
Riptide CH6: XMP Data Architecture
RS422 receiver, specifications CH1: Host Computer Electrical Requirements
RS422 transmitter, specifications CH1: Host Computer Electrical Requirements
Rx, SERCOS receiver CH5: XMP-SERCOS Connector Ports

S
Safety precautions
amplifier enabling CH3: Drive Enable Wiring
braking CH3: Drive Enable Wiring
electrostatic discharge (ESD) CH1: XMP Controller Installation
emergency stop CH3: Drive Enable Wiring
E-stop input CH3: Connect System I/O
fail safe wiring CH3: Drive Enable Wiring
installation CH1: XMP Controller Installation
power CH1: XMP Controller Installation
safety zones CH1: XMP Controller Installation
sudden movement CH1: XMP Controller Installation
Scale interpolation
SIM4 module CH1: Expansions and Add-ons
Scale interpolation module CH6: Host Bus
position capture CH6: Host Bus
position compare CH6: Host Bus
sine and cosine levels CH6: Host Bus
SERCOS CH5: Introduction, CH5: Assistance with SERCOS Networks, CH6: Analog Inputs
cable bend radius CH5: SERCOS Connection Hardware
connectors CH5: SERCOS Connection Hardware
data rate CH5: XMP-SERCOS Connector Ports
drive limitations CH5: Introduction
IDNs CH5: SERCOS Connection Hardware
initialization CH5: SERCOS Connection Hardware
input-output (I/O) CH5: Introduction, CH5: Assistance with SERCOS Networks
nodes CH5: Introduction
NRZI bit coding CH5: XMP-SERCOS Connector Ports
optical power CH5: Introduction , CH5: SERCOS Connection Hardware
rings CH5: Introduction
telegrams CH5: Introduction
XMP-CPCI-6U CH5: XMP-SERCOS Connector Ports
XMP-PMC CH5: XMP-SERCOS Connector Ports
Servo command output DAC CH6: Analog Inputs
Servo motors
connection to XMP controller CH3: Configuring Analog Connections
SHARC DSP CH6: SHARC DSP Processor Subsystem , CH6: Analog Inputs
(diagram) CH6: SHARC DSP Processor Subsystem
SIDNs CH5: SERCOS Connection Hardware
SIM4 CH6: Host Bus
SIM4 module CH1: Expansions and Add-ons, CH6: Architectural Overview
Sine and cosine, in scale interpolation CH6: Host Bus
Single-ended encoders CH3: Drive Enable Wiring
Soft reset CH6: Analog Inputs
SRAM, external CH6: SHARC DSP Processor Subsystem
STC-136 terminal blocks CH3: Introduction , CH4: Introduction CH3: Connect to Analog Servo Amplifiers
STC-136 terminal connection block CH3: Introduction
Step motors
connection to XMP controller CH3: Configuring Analog Connections
open-loop CH3: Configuring Analog Connections
Step-and-direction motors
connection to XMP controller CH3:Configuring Analog Connections
Stepper motors
closed loop CH3: Configuring Analog Connections
configuring using Motion Console CH3: Configuring Analog Connections
loopback CH3: Configuring Analog Connections
step/dir & CW/CCW specs CH3: Connect to Digital Quadrature Encoders
supported in MPI CH3: Drive Enable Wiring
System Reset Input CH3: Introduction

T
Telegrams, SERCOS CH5: Introduction
Terminal connection blocks
STC-136 CH3: Introduction
Transceivers
analog XCVR A CH4: XMP-PCI
analog XCVR B CH4: XMP-PCI
analog XCVR C CH4: XMP-PCI
analog XCVR D CH4: XMP-PCI
analog XCVR E CH4: XMP-PCI
analog XCVR F CH4: Transceiver (XCVR) and User I/O Details
as Compare outputs CH3: Connect System I/O
configuring CH3: Connect to Digital Quadrature Encoders , CH4: XMP-PCI
electrical requirements CH1: Host Computer Electrical Requirements
inverting CH3: Configuring Analog Connections
SERCOS CH5: Introduction
Trigger CH6: XMP Data Architecture , CH6: Analog Inputs
Troubleshooting
SERCOS networks CH5: Assistance with SERCOS Networks
SERCOS optical power settings CH5: SERCOS Connection Hardware
wiring CH4: Introduction
Tx, SERCOS transmitter CH5: XMP-SERCOS Connector Ports

U
User I/O CH4: Transceiver (XCVR) and User I/O Details
User I/O outputs CH3: Drive Enable Wiring
UserIO CH3: Drive Enable Wiring
UserIO_Rtn CH3: Drive Enable Wiring

V
VHDCI cabling CH4: Introduction

W
Watchdog timer CH6: Analog Inputs
Wiring, motor CH3: Configuring Analog Connections, CH3: Drive Enable Wiring

X
XCVR A functions CH4: XMP-PCI
XCVR B functions CH4: XMP-PCI
XCVR C functions CH4: XMP-PCI
XCVR D functions CH4: XMP-PCI
XCVR E functions CH4: XMP-PCI
XCVR F functions CH4: Transceiver (XCVR) and User I/O Details
XMP bus interface CH2: Introduction -CH2: PMC Bus
XMP Controller
analog drives CH1: Host Computer Electrical Requirements
bus connectivity CH2: Introduction
bus interface CH6: Host Bus
connection to brush servo motors CH3: Configuring Analog Connections
connection to servo motors CH3: Configuring Analog Connections
connection to step motors CH3: Configuring Analog Connections
connection to step-and-direction motors CH3:Configuring Analog Connections
data architecture CH6: Analog Inputs
device driver CH6: XMP Data Architecture
dual-loop CH3: Drive Enable Wiring
electrical requirements CH1: Host Computer Electrical Requirements
encoders CH1: Host Computer Electrical Requirements, CH1: Host Computer Electrical Requirements
expansion board CH6: Analog Inputs , CH6: Analog Inputs
expansion boards CH1: Expansions and Add-ons, CH3: Connect System I/O
faults CH6: Analog Inputs
hardware CH1: XMP Hardware , CH1: XMP Controller Installation
hardware architecture CH6: Architectural Overview CH6: XMP Data Architecture
homing CH6: XMP Data Architecture
initialization CH6: SHARC DSP Processor Subsystem
installation CH1: XMP Controller Installation , CH1: XMP Controller Installation
main board CH6: Analog Inputs , CH6: Analog Inputs
main-expansion connector CH2: Introduction
memory subsystem CH6: Analog Inputs
model numbers CH1: XMP Controller Configurations
motion blocks CH6: Analog Inputs , CH6: Analog Inputs , CH6: SHARC DSP Processor Subsystem
motor blocks CH6: Analog Inputs , CH6: Analog Inputs
XMP Controller (cont.)
resets CH6: Analog Inputs
safety precautions CH1: XMP Controller Installation
SERCOS networks CH5: Assistance with SERCOS Networks
SIM4 module CH1: Expansions and Add-ons
voltage and current specifications CH1: Host Computer Electrical Requirements
XMP-CPCI-3U bus interface CH2: CPCI-3U Bus
XMP-CPCI-3U input-output (I/O) CH4: CPCI-3U
XMP-CPCI-6U bus interface CH2: CPCI-6U Bus
XMP-CPCI-6U expansion boards CH2: CPCI-6U Bus
XMP-CPCI-6U input-output (I/O) CH4: Introduction, CH2: PCI Bus
XMP-PCI bus interface CH5: PCI Bus
XMP-PCI input-output (I/O) CH4: XMP-PCI , CH5: SERCOS Connection Hardware
XMP-PMC bus interface CH2: PMC Bus
XMP-PMC input-output (I/O) CH4: XMP-SERCOS-PMC
XMP hardware CH1: XMP Hardware -CH1: XMP Controller Installation
XMP interface
XMP-analog CH1: XMP Hardware
XMP-SERCOS CH1: XMP Hardware
XMP-analog
electrical requirements CH1: Host Computer Electrical Requirements
XMP-analog hardware CH4: Introduction, CH4: Transceiver (XCVR) and User I/O Details
XMP-CPCI-3U
bus interface CH2: CPCI-3U Bus
controller installation CH1: XMP Controller Installation
form factor CH1: XMP Hardware , CH1: XMP Hardware
input-output (I/O) CH4: CPCI-3U
XMP-CPCI-6U
bus interface CH2: CPCI-6U Bus
controller installation CH1: XMP Controller Installation
expansion boards CH2: CPCI-6U Bus
form factor CH1: XMP Hardware , CH1: XMP Hardware
input-output (I/O) CH4: Introduction CH2: PCI Bus
XMP-PCI
bus interface CH5: PCI Bus
controller installation CH1: XMP Controller Installation
form factor CH1: XMP Hardware , CH1: XMP Hardware
input-output (I/O) CH4: XMP-PCI , CH5: SERCOS Connection Hardware
XMP-PMC
bus interface CH2: PMC Bus
controller installation CH1: XMP Controller Installation
form factor CH1: XMP Hardware , CH1: XMP Hardware
input-output (I/O) CH4: XMP-SERCOS-PMC


XMP Hardware
XMP Controller Configurations
Expansions and Add-ons
Host Computer Electrical Requirements
XMP Controller Installation
CHAPTER 1
XMP HARDWARE OVERVIEW

XMP Hardware

Because computer-based motion control systems vary widely, the XMP has been designed to accommodate most common industry hardware. This means providing a variety of platform, porting, form factor, and voltage options.

Platform Options

XMP-series motion controllers are ported to accommodate common industry software platforms, including:

  • Windows95/98
  • Windows2000
  • WindowsNT
  • LynxOS
  • VxWorks
  • VenturCom RTSS
  • QNX
  • PharLap

Form Factor Options

"Form factor" refers to the physical shape and size of an XMP controller and the component(s) it is designed to function with. XMP controllers are available in the following form factors:

  • PCI
  • CPCI-3U
  • CPCI-6U
  • PMC

If your application requires a different form factor, please contact MEI.

Various form factors are shown in the figures below. Four types of I/O connectors are utilized: VHDCI; SERCOS; and, CPCI (rear I/O).

  1. Figure 1-1 Controller form factors: PCI, PMC, and CPCI
    (-3U and -6U).

XMP Interface Options: Networked and XMP-analog

XMP control systems accommodate two interface categories: networked and XMP-Analog. The types of hardware associated with each category are show here:

Network
  • SERCOS
XMP-analog
  • Analog ± 10 VDC
  • Pulse (Step / Dir)
  • Quadrature encoder
  • Absolute encoder
XMP-SERCOS Systems

SERCOS (SErial Real-time COmmunication System) is the most common type of networked motion control. All data is transmitted over a fiber-optic ring, with each SERCOS device having both a dedicated input and output. At regular intervals, the XMP controller receives a coded data packet from each device in the ring, reporting its current status. The controller then processes the information, and transmits an updated command data packet to each SERCOS device. Typical SERCOS cycle rates vary between 500-1000 samples per second.

XMP-analog Systems

XMP-analog controllers represent a traditional form of motion control, with command and feedback data transmitted via numerous discrete electrical connections.


XMP Controller Configurations
Expansions and Add-ons
Host Computer Electrical Requirements
XMP Controller Installation
CHAPTER 1
XMP HARDWARE OVERVIEW

XMP Controller Configurations

As demonstrated in the "XMP Hardware Overview" above, XMP controllers come from MEI with a variety of configurable options; however, not all options apply. (For example, SERCOS controllers have no voltage options because they function optically.)

MEI organizes its XMP controllers by form factor, bus, axes, and voltage. Several common controllers are listed in the table below.

Common XMP controllers.

Data Type

Form Factor

Opto Input Voltage

No. of Axes 1

No. of Rings 2

Description

Part No.

XMP-analog

PCI

5

4

XMP-PCI-4-5V

T003-0006

8

XMP-PCI-8-5V

T003-0001

16

XMP-PCI-16-5V

T003-0003

24

4

XMP-PCI-4-24V

T003-0005

8

XMP-PCI-8-24V

T003-0002

16

XMP-PCI-16-24V

T003-0004

CPCI-3U

5

4

XMP-CPCI-3U-4-5V

T001-0010

CPCI-6U

5

4

XMP-CPCI-4-5V

T001-0016

8

XMP-CPCI-8-5V

T001-0003

24

4

XMP-CPCI-4-24V

T001-0017

8

XMP-CPCI-8-24V

T001-0004

12

XMP-CPCI-12-24V

T001-0015

16

XMP-CPCI-16-24V

T001-0006

Network
(XMP-SERCOS)

PCI

N/A

8

1

XMP-SERCOS-PCI-S1

T004-0005

N/A

16

2

XMP-SERCOS-PCI-S2

T004-0004

CPCI-6U

N/A

24

3

XMP-SERCOS-CPCI-S3

T004-0001

PMC

N/A

8

1

XMP-SERCOS-PMC-S1

T004-0002

IMPORTANT NOTE: When ordering parts or service from MEI, please refer to its part number (e.g., "T003-0005").

1. Most basic ("main") XMP analog controllers come configured for 8 axes. Additional axes are configured by adding an expansion board to the controller, boosting the total number to either 12 or 16 axes per controller. (Expansion is not available in XMP-CPCI-3U or PMC form factors.)

2. SERCOS controllers are configured for either 1 or 3 rings, with each ring handling a maximum of 8 SERCOS devices.


Expansions and Add-ons
Host Computer Electrical Requirements
XMP Controller Installation
CHAPTER 1
XMP HARDWARE OVERVIEW

Expansions and Add-ons

Some XMP controllers may be enhanced with additional hardware. These include:

  • Expansion boards -- These expand the number of axes run by a controller by adding up to two motion blocks for a total of 16 axes. Unlike main boards, expansion boards do not contain SHARC DSP processors. They are available for XMP-PCI and XMP-CPCI-6U form factors only (not available for XMP-CPCI-3U and XMP-SERCOS-PMC controllers). An expanded XMP-CPCI-6U controller is shown below.
  • SIM4 modules -- Scale Interpolation Modules (SIMs) are mounted mezzanine-style to motion controllers that use encoders with sinusoidal outputs. These enhance positional resolution significantly and are available for XMP-PCI and XMP-CPCI-6U controllers only. A maximum of two SIM4 modules may be added to each main or expansion board. A SIM4 module is shown below with an XMP-PCI controller.

For detailed information regarding SIM4 modules, please refer to Application Note 206 from Motion Engineering.


Host Computer Electrical Requirements
XMP Controller Installation
CHAPTER 1
XMP HARDWARE OVERVIEW

Host Computer Electrical Requirements

Below is shown a table of basic host computer electrical requirements for XMP controllers.

XMP voltage and current specifications.

Controller

Voltage 1

Current 2
(Typ. amps)

Current
(Max. amps)

XMP-PCI (analog)

+5 VDC ± 5%

1.70 (main)
1.20 (expansion)

3.20 (main)
2.20 (expansion)

+12 VDC ± 10%

0.03 (main)
0.01 (expansion)

0.05 (main)
0.01 (expansion)

-12 VDC ± 10%

0.01 (main)
0.01 (expansion)

0.01 (main)
0.01 (expansion)

SIM4 Module on XMP-PCI

+5 VDC ± 5%

0.18

0.40

+12 VDC ± 10%

0.01

0.01

-12 VDC ± 10%

0.03

0.05

XMP-CPCI-6U (analog)

+3.3 VDC ± 10%

0.90 (main)
0.70 (expansion)

1.40 (main)
1.00 (expansion)

+5 VDC ± 5%

0.90 (main)
0.90 (expansion)

1.90 (main)
1.90 (expansion)

+12 VDC ± 10%

0.03 (main)
0.01 (expansion)

0.05 (main)
0.01 (expansion)

-12 VDC ± 10%

0.01 (main)
0.01 (expansion)

0.01 (main)
0.01 (expansion)

SIM4 Module on XMP-CPCI

+3.3 VDC ± 10%

0.08

0.20

+5 VDC ± 5%

0.12

0.20

+12 VDC ± 10%

0.01

0.01

-12 VDC ± 10%

0.03

0.05

XMP-SERCOS-CPCI-6U

+3.3 VDC ± 10%

0.50

0.75

+5 VDC ± 5%

0.50

0.75

XMP-CPCI-3U (analog)

+3.3 VDC ± 10%

0.50

0.90

+5 VDC ± 5%

0.45

1.15

XMP-SERCOS-PMC

+3.3 VDC ± 10%

0.375

0.50

+5 VDC ± 5%

0.375

0.50

XMP-SERCOS-PCI-S2

+5 VDC ± 5%

0.60

1.00

1. Controller voltage required at computer or card cage.

2. Installed SIM4 modules and encoders also contribute to current demands.

Using the XMP controller to power encoders?

Then make sure that voltage drops in your cabling are NOT a problem. If voltage drops are a problem, power the encoders using an external supply. For every 100 mA of current drawn, the 5V_OUT voltage may drop 0.2 volts or more (due to cable resistance). For example, if two encoders each draw 150 mA, then 5V_OUT may drop to 4.4 volt at the encoders. This could cause your encoder to fail!

SERCOS Drives

SERCOS is a standardized industrial format utilizing fiber-optic technology. The optical power demands of drives vary widely, depending upon the drive itself, length of cables, etc. For more information regarding SERCOS motion drive power demands, please see your drive's manufacturer.

XMP-analog Controllers

XMP-analog systems rely upon traditional copper wiring to pass analog signals between the drive and controller. Two voltages are available for opto-inputs on XMP controllers: 5VDC and 24VDC. To determine whether your controller supports 5V or 24V, look for a sticker on the XMP circuit board. The sticker will say either "5V" or "24V."

Detailed information regarding configuration of analog I/O is provided in Chapter 4. Specifications for transceiver components used in the XMP-Analog controller's I/O are provided in tables below.

RS422 receiver.

Description

Specification

Input High Threshold

VDIFF > 0.2V

Input Low Threshold

VDIFF < -0.2V

Input Current

IIN < 1.0mA @ VIN = 12V
IIN < -0.8mA @ VIN = -7V

NOTE: In addition, encoder inputs have 100 [image] differential termination.

Propagation Delay

Tp < 200 ns

Absolute Maximums 1

ESD Protection ± 15kV
-8V < VIN < +12.8V (input to GND)

RS422 transmitter.

Description

Specification

Differential Output
Voltage

VDIFF < 5V @ I = 0mA
VDIFF > 2V @ I = 20mA

Common Mode
Output Voltage

VOUT (common mode) < 3V (100 [image] load)

Propagation Delay

Tp < 60ns

Absolute Maximums 2

IOUT < 50mA

Dedicated opto-inputs.

Description

Specification

Active Input Guaranteed

IIN > 2mA
5V input (820 [image] current limit resistor):
VIN < 3V @ IIN = 2mA
24V input (6.8k [image] current limit resistor):
VIN < 15V @ IIN = 2mA

Inactive Input Guaranteed

VIN < 0.1mA

Propagation Delay

Tp < 20µs

Absolute Maximums 3

5V input (820 [image] current limit resistor):
VIN < 10V
VIN < 10mA
24V input (6.8k [image] current limit resistor):
VIN < 30V
VIN < 5mA
VISOLATION < 40V

Dedicated opto-outputs.

Description

Specification

Active Output Guaranteed

VOUT < 0.3V @ IOUT < 2mA
VOUT < 1.1V @ IOUT < 10mA

Inactive Output Guaranteed

IOUT < 0.01mA

Propagation Delay

Tp < 100µs (load < 10 k [image])

Absolute Maximums 4

IOUT < 50mA
VOUT < 30V
IREVERSE < 100mA @ VREVERSE 0.4V (protection diode)
VISOLATION < 40V

Bi-directional opto-inputs.

Description

Specification

Active Input Guaranteed

IIN > 2mA
VIN < 1.7V @ IIN = 2mA

Inactive Input Guaranteed

IIN < 0.1mA

Propagation Delay

Tp < 20µs

Absolute Maximums 5

IIN < 50mA
IREVERSE < 30V
VISOLATION < 40V

Bi-directional opto-outputs.

Description

Specification

Active Output Guaranteed

VOUT < 0.3V @ IOUT < 2mA
VOUT < 1.1V @ IOUT < 10mA

Inactive Input Guaranteed

IOUT < 0.01mA

Propagation Delay

Tp < 100µs (load < 10 k [image])

Absolute Maximums 6

IOUT < 50mA
VOUT < 30V
IREVERSE < 50mA @ VREVERSE 1.7V (input circuit)
VISOLATION < 40V

1. Exceeding absolute maximums may damage components.

2. Exceeding absolute maximums may damage components.

3. Exceeding absolute maximums may damage components.

4. Exceeding absolute maximums may damage components.

5. Exceeding absolute maximums may damage components.

6. Exceeding absolute maximums may damage components.


XMP Controller Installation
CHAPTER 1
XMP HARDWARE OVERVIEW

XMP Controller Installation

Depending upon form factor, installation of your XMP controller will vary. However, in all cases, good electrical contact must be ensured at connectors; otherwise, noise and power problems will develop. (Connections should be verified through inspection and testing.)

Standard safety rules prevail during installation of any hardware. Some are summarized below for the XMP. For more information, refer to local occupational safety regulations and the manufacturer of your motion drive.

Turn Off All Power Before Installing Equipment

Before installing any motion control equipment, including XMP controllers, power should be switched OFF. Unplug all power plugs from their sources of power.

Observe ESD Precautions

To prevent damage to controller and drive electronics due to electrostatic discharge (ESD), service personnel are cautioned to observe proper grounding during handling of components.

Grounding straps should be worn at all times when handling XMP controller boards and connection hardware.

Define and Clear a Safety Zone!

During installation and testing of motion control hardware-software, a safety zone should be defined around moving components and kept clear of personnel, hands, fingers, and loose hardware. During repowering of the system, motion control components may behave erratically due to misconnected lines, or wrongly configured software settings.

Sudden and unexpected moves by components can cause injury, property damage or even death! Under NO circumstances, should a motion system be tested or operated while personnel are within the safety zone. Additionally, beware of flying debris from unsecured hardware operating at high speeds. The use of safety shielding is highly recommended.

Install Controller

XMP controllers are designed to fit standard industry buses and card cages (e.g., PCI, CPCI). When installing and removing controllers, verify that good electrical contact is made between the controller and receptacle.

PCI

XMP-PCI controllers are installed into the PCI buses of their host computer's mother boards. During installation, verify the controller is seated firmly in its assigned PCI slot by firmly pressing downward. The I/O bracket should be screwed securely to the expansion bay chassis.

XMP-CPCI-6U and XMP-SERCOS-CPCI-6U

XMP-CPCI-6U controllers are installed in industry standard CPCI slots. They are secured with ejectors. To install, first verify that both ejectors are in the open (rotated outward) position. Align the PC board with the card slot in the CPCI chassis, then press home. To secure, rotate each ejector until claws engage holes in the top-bottom chassis rails and lock the controller into place.

To remove an XMP-CPCI-6U controller from its slot, first loosen the captive screws located at the top and bottom chassis rails. Next, simultaneously pinch each ejector at its flex point to unlock, then rotate outward. The controller should eject.

XMP-CPCI-3U

XMP-CPCI-3U controllers feature one locking ejector at the base of the front panel and a captive screw at the top. The XMP-CPCI-3U chassis has an ejector rail along its bottom and a threaded hole on its top rail to match the captive screw.

To install, first verify that the bottom ejector is in the open (rotated outward) position. Align the PC board with the card slot in the CPCI chassis, then press home. To secure, apply gentle pressure to the edge of the card while rotating the bottom ejector inward. The ejector's claws will engage holes in the bottom chassis rail and lock the controller into place. Secure the captive screw in the chassis at the top of the controller by rotating clockwise.

To remove an XMP-CPCI-3U controller from its slot, first loosen the captive screw by rotating counterclockwise. Pull the red ejector tab outward, then rotate the ejector downward. The controller should eject.

XMP-SERCOS-PMC

XMP-PMC controllers are connected directly to motherboards via mezzanine connectors. The boards are secured to the motherboard using two (2) screws and stand-offs. To prevent damage to the motherboard, do not overtighten the screws.


Introduction
PCI Bus
CPCI-6U Bus
CPCI-3U Bus
PMC Bus
CHAPTER 2
XMP Bus Interface

Introduction

This chapter describes XMP controller-computer bussing, and is organized by form factor. The reader should note that both XMP-analog and XMP-SERCOS controllers utilize identical bus connections for each respective form factor. (For example, a CPCI controller may have the same bus connections, whether the I/O is configured for XMP-analog or -SERCOS.)

"Main" versus "Expansion" Boards (XMP-analog only)

XMP-analog controllers may be configured for varying numbers of axes. Up to 8 axes are controlled by a single "main" controller board. Where more than 8 axes are required, it is necessary to add an "expansion" board.

Expansion boards consist of separate electronics, very similar in appearance and function to main boards. Typically, an expansion board is located on the bus or backplane immediately adjacent to a main board. Both boards (main and expansion) are connected via a short ribbon cable. When connected together, one main and one expansion board constitute a single, unified "controller."

Expansion boards are not available for XMP-SERCOS controllers.

  1. XMP-CPCI-6U main and expansion boards. Connection is via ribbon cable. To release ribbon cable, press clip
    2. 1 while disconnecting connector 2. XMP-PCI connection is similar.


PCI Bus
CPCI-6U Bus
CPCI-3U Bus
PMC Bus
CHAPTER 2
XMP Bus Interface

PCI Bus

PCI buses are found in many common desktop and tower-type computer systems. The standard XMP-PCI controller features a 120-pin edge connector which plugs directly into standard 5VDC PCI bus receptacles. (Refer to figure above.) A "universal" PCI that supports 3.3V or 5V signalling is pending from MEI. Please contact MEI for availability.

All motion control I/O for the XMP-PCI controller is performed via the VHDCI connectors on the rear panel of the controller. For more information on I/O, please refer to Chapter 4.

PCI Connector (Bus)
PCI bus connector (main & expansion boards).

5 V System

Universal System (5 or 3.3 V)

Side B

Side A

Side B

Side A

Pin

Function

Pin

Function

Pin

Function

Pin

Function

Comments

01B

-12V

01A

TRST#

01B

-12V

01A

TRST#

32-bit Connector Start

02B

TCK

02A

+12V

02B

TCK

02A

+12V

03B

GND

03A

TMS

03B

GND

03A

TMS

04B

TDO

04A

TDI

04B

TDO

04A

TDI

05B

+5V

05A

+5V

05B

+5V

05A

+5V

06B

+5V

06A

INTA#

06B

+5V

06A

INTA#

07B

INTB#

07A

INTC#

07B

INTB#

07A

INTC#

08B

INTD#

08A

+5V

08B

INTD#

08A

+5V

09B

PRSNT1#

09A

Reserved

09B

PRSNT1#

09A

Reserved

10B

Reserved

10A

+5V (I/O)

10B

Reserved

10A

+5V (I/O)

11B

PRSNT2#

11A

Reserved

11B

PRSNT2#

11A

Reserved

12 B

Ground

12A

Ground

12B

KEY SLOT

12A

KEY SLOT

13B

Ground

13A

Ground

13B

13A

14B

Reserved

14A

Reserved

14B

Reserved

14A

Reserved

15B

Ground

15A

RST#

15B

Ground

15A

RST#

16B

CLK

16A

+5V (I/O)

16B

CLK

16A

+5V (I/O)

17B

Ground

17A

GNT#

17B

Ground

17A

GNT#

18B

REQ#

18A

Ground

18B

REQ#

18A

Ground

19B

+5V (I/O)

19A

Reserved

19B

+V (I/O)

19A

Reserved

20B

AD[31]

20A

AD[30]

20B

AD[31]

20A

AD[30]

21B

AD[29]

21A

+3.3V

21B

AD[29]

21A

+3.3V

22B

Ground

22A

AD[28]

22B

Ground

22A

AD[28]

23B

AD[27]

23A

AD[26]

23B

AD[27]

23A

AD[26]

24B

AD[25]

24A

Ground

24B

AD[25]

24A

Ground

25B

+3.3V

25A

AD[24]

25B

+3.3V

25A

AD[24]

26B

C/BE[3]#

26A

IDSEL

26B

C/BE[3]#

26A

IDSEL

27B

AD[23]

27A

+3.3V

27B

AD[23]

27A

+3.3V

28B

Ground

28A

AD[22]

28B

Ground

28A

AD[22]

29B

AD[21]

29A

AD[20]

29B

AD[21]

29A

AD[20]

30B

AD[19]

30A

Ground

30B

AD[19]

30A

Ground

31B

+3.3V

31A

AD[18]

31B

+3.3V

31A

AD[18]

32B

AD[17]

32A

AD[16]

32B

AD[17]

32A

AD[16]

33B

C/BE[2]#

33A

+3.3V

33B

C/BE[2]#

33A

+3.3V

34B

Ground

34A

FRAME#

34B

Ground

34A

FRAME#

35B

IRDY#

35A

Ground

35B

IRDY#

35A

Ground

36B

+3.3V

36A

TRDY#

36B

+3.3V

36A

TRDY#

37B

DEVSEL#

37A

Ground

37B

DEVSEL#

37A

Ground

38B

Ground

38A

STOP#

38B

Ground

38A

STOP#

39B

LOCK#

39A

+3.3V

39B

LOCK#

39A

+3.3V

40B

PERR#

40A

SDONE

40B

PERR#

40A

SDONE

41B

+3.3V

41A

SBO#

41B

+3.3V

41A

SBO#

42B

SERR#

42A

Ground

42B

SERR#

42A

Ground

43B

+3.3V

43A

PAR

43B

+3.3V

43A

PAR

44B

C/BE[1]#

44A

AD[15]

44B

C/BE[1]#

44A

AD[15]

45B

AD[14]

45A

+3.3V

45B

AD[14]

45A

+3.3V

46B

Ground

46A

AD[13]

46B

Ground

46A

AD[13]

47B

AD[12]

47A

AD[11]

47B

AD[12]

47A

AD[11]

48B

AD[10]

48A

Ground

48B

AD[10]

48A

Ground

49B

Ground

49A

AD[09]

49B

M66EN

49A

AD[09]

66 MHz / Gnd

50B

KEY SLOT

50A

KEY SLOT

50B

KEY SLOT

50A

KEY SLOT

5 Volt Key

51B

51A

51B

51A

5 Volt Key

52B

AD[08]

52A

C/BE[0]#

52B

AD[08]

52A

C/BE[0]#

53B

AD[07]

53A

+3.3V

53B

AD[07]

53A

+3.3V

54B

+3.3V

54A

AD[06]

54B

+3.3V

54A

AD[06]

55B

AD[05]

55A

AD[04]

55B

AD[05]

55A

AD[04]

56B

AD[03]

56A

Ground

56B

AD[03]

56A

Ground

57B

Ground

57A

AD[02]

57B

Ground

57A

AD[02]

58B

AD[01]

58A

AD[00]

58B

AD[01]

58A

AD[00]

59B

+5V (I/O)

59A

+5V (I/O)

59B

+V (I/O)

59A

+5V (I/O)

60B

ACK64#

60A

REQ64#

60B

ACK64#

60A

REQ64#

61B

+5V

61A

+5V

61B

+5V

61A

+5V

62B

+5V

62A

+5V

62B

+5V

62A

+5V

32-bit Connector End


CPCI-6U Bus
CPCI-3U Bus
PMC Bus
CHAPTER 2
XMP Bus Interface

CPCI-6U Bus

Compact PCI (CPCI) utilizes a card-type computer chassis, having a multi-pin backplane. The main advantage is smaller sizing and simplified access to electronics. There are two sizes of CPCI: -6U and -3U. The CPCI-6U is the larger of the two form factors and connects to the backplane bus via jumper connector J1. The CPCI-6U is described in this section.

The CPCI-3U is described in the next section of this chapter.

CPCI-6U Main Board, Rear Panel Connector J1

NOTE: the CPCI XMP does not use the 64-bit extension.

CPCI backplane connector (main and expansion boards).

Pin

A

B

C

D

E

25

5V

REQ64#

ENUM#

3.3V

5V

24

AD[01]

5V

V(I/O)

AD[00]

ACK64#

23

3.3V

AD[04]

AD[03]

5V

AD[02]

22

AD[07]

GND

3.3V

AD[06]

AD[05]

21

3.3V

AD[09]

AD[08]

M66EN

C/BE[0]#

20

AD[12]

GND

V(I/O)

AD[11]

AD[10]

19

3.3V

AD[15]

AD[14]

GND

AD[13]

18

SERR#

GND

3.3V

PAR

C/BE[1]#

17

3.3V

SDONE

SBO#

GND

PERR#

16

DEVSEL#

GND

V(I/O)

STOP#

LOCK#

15

3.3V

FRAME#

IRDY#

GND

TRDY#

12 - 14

Key Area

11

AD[18]

AD[17]

AD[16]

GND

C/BE[2]#

10

AD[21]

GND

3.3V

AD[20]

AD[19]

9

C/BE[3]#

IDSEL

AD[23]

GND

AD[22]

8

AD[26]

GND

V(I/O)

AD[25]

AD[24]

7

AD[30]

AD[29]

AD[28]

GND

AD[27]

6

REQ#

GND

3.3V

CLK

AD[31]

5

BRSVP1A5

BRSVP1B5

RST#

GND

GNT#

4

BRSVP1A4

GND

V(I/O)

INTP

INTS

3

INTA#

INTB#

INTC#

5V

INTD#

2

TCK

5V

TMS

TDO

TDI

1

5V

-12V

TRST#

+12V

5V

CPCI-6U Expansion Board

Special Note: On CPCI-6U motion control systems having an expansion board, all computer bus data is conveyed via the main board's J1 connector, then relayed via the ribbon cable connector. Expansion boards also utilize a J1 backplane connector; however, it provides only power and ground to the expansion board.


CPCI-3U Bus
PMC Bus
CHAPTER 2
XMP Bus Interface

CPCI-3U Bus

The four-axis CPCI-3U is a smaller version of the -6U board. It connects to the backplane via two connectors: J1 and J2 (see figure above). Motion drive I/O is conveyed via J2, which is described in Chapter 4. Connector J1 is reserved as a computer bus, and is described in this section.

Backplane connector pins are referred to by numbered rows and lettered columns as shown below:

CPCI-3U Main Board, Rear Panel Connector J1: User I/O

NOTE: the CPCI XMP does not use the 64-bit extension.

CPCI backplane connector (main and expansion boards).

Pin

A

B

C

D

E

25

5V

REQ64#

ENUM#

3.3V

5V

24

AD[01]

5V

V(I/O)

AD[00]

ACK64#

23

3.3V

AD[04]

AD[03]

5V

AD[02]

22

AD[07]

GND

3.3V

AD[06]

AD[05]

21

3.3V

AD[09]

AD[08]

M66EN

C/BE[0]#

20

AD[12]

GND

V(I/O)

AD[11]

AD[10]

19

3.3V

AD[15]

AD[14]

GND

AD[13]

18

SERR#

GND

3.3V

PAR

C/BE[1]#

17

3.3V

SDONE

SBO#

GND

PERR#

16

DEVSEL#

GND

V(I/O)

STOP#

LOCK#

15

3.3V

FRAME#

IRDY#

GND

TRDY#

12 - 14

Key Area

11

AD[18]

AD[17]

AD[16]

GND

C/BE[2]#

10

AD[21]

GND

3.3V

AD[20]

AD[19]

9

C/BE[3]#

IDSEL

AD[23]

GND

AD[22]

8

AD[26]

GND

V(I/O)

AD[25]

AD[24]

7

AD[30]

AD[29]

AD[28]

GND

AD[27]

6

REQ#

GND

3.3V

CLK

AD[31]

5

BRSVP1A5

BRSVP1B5

RST#

GND

GNT#

4

BRSVP1A4

GND

V(I/O)

INTP

INTS

3

INTA#

INTB#

INTC#

5V

INTD#

2

TCK

5V

TMS

TDO

TDI

1

5V

-12V

TRST#

+12V

5V


PMC Bus
CHAPTER 2
XMP Bus Interface

PMC Bus

PMC stands for PCI Mezzanine Card. On XMP controllers, PMC bussing is via a "mezzanine" connector, mounted at one corner of the card.

P11 |  |  |  | P12
Pin # | Signal Name | Signal Name | Pin # | Pin # | Signal Name | Signal Name | Pin #
1 | TCK | -12V | 2 | 1 | +12V | TRST# | 2
3 | Ground | INTA# | 4 | 3 | TMS | TDO | 4
5 | INTB# | INTC# | 6 | 5 | TDI | Ground | 6
7 | BUSMODE1# | +5V | 8 | 7 | Ground | PCI-RSVD* | 8
9 | INTD# | PCI-RSVD* | 10 | 9 | PCI-RSVD* | PCI-RSVD* | 10
11 | Ground | PCI-RSVD# | 12 | 11 | BUSMODE2# | +3.3V | 12
13 | CLK | Ground | 14 | 13 | RST# | BUSMODE3# | 14
15 | Ground | GNT# | 16 | 15 | +3.3V | BUSMODE4# | 16
17 | REQ# | +5V | 18 | 17 | PCI-RSVD* | Ground | 18
19 | V (I/O) | AD[31] | 20 | 19 | AD[30] | AD[29] | 20
21 | AD[28] | AD[27] | 22 | 21 | Ground | AD[26] | 22
23 | AD[25] | Ground | 24 | 23 | AD[24] | +3.3V | 24
25 | Ground | C/BE[3]# | 26 | 25 | IDSEL | AD[23] | 26
27 | AD[22] | AD[21] | 28 | 27 | +3.3V | AD[20] | 28
29 | AD[19] | +5V | 30 | 29 | AD[18] | Ground | 30
31 | V (I/O) | AD[17] | 32 | 31 | AD[16] | C/BE[2]# | 32
33 | FRAME# | Ground | 34 | 33 | Ground | PMC-RSVD | 34
35 | Ground | IRDY# | 36 | 35 | TRDY# | +3.3V | 36
37 | DEVSEL# | +5V | 38 | 37 | Ground | STOP# | 38
39 | Ground | LOCK# | 40 | 39 | PERR# | Ground | 40
41 | SDONE# | SBO# | 42 | 41 | +3.3V | SERR# | 42
43 | PAR | Ground | 44 | 43 | C/BE[1]# | Ground | 44
45 | V (I/O) | AD[15] | 46 | 45 | AD[14] | AD[13] | 46
47 | AD[12] | AD[11] | 48 | 47 | Ground | AD[10] | 48
49 | AD[09] | +5V | 50 | 49 | AD[08] | +3.3V | 50
51 | Ground | C/BE[0]# | 52 | 51 | AD[07] | PMC-RSVD | 52
53 | AD[06] | AD[05] | 54 | 53 | +3.3V | PMC-RSVD | 54
55 | AD[04] | Ground | 56 | 55 | PMC-RSVD | Ground | 56
57 | V (I/O) | AD[03] | 58 | 57 | PMC-RSVD | PMC-RSVD | 58
59 | AD[02] | AD[01] | 60 | 59 | Ground | PMC-RSVD | 60
61 | AD[00] | +5V | 62 | 61 | ACK64# | +3.3V | 62
63 | Ground | RE064# | 64 | 63 | Ground | PMC-RSVD | 64


Introduction
Connect to Analog Servo Amplifiers
Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Introduction

This chapter describes basic encoder, amplifier, and limit signal connectivity via 68-pin VHDCI (Very High Density Cable Interconnect, also known as SCSI-5) receptacles for the XMP-PCI, XMP-CPCI-6U and XMP-CPCI-3U controllers. The XMP-CPCI-6U and XMP-CPCI-3U are also offer a rear I/O backplane connection option, which is described in Chapter 4.

I/O via VHDCI Receptacles
STC-136 Terminal Blocks

MEI offers STC-136 terminal blocks to assist in connecting controllers to drives via VHDCI. STC-136 terminal blocks utilize preconfigured cables from VHDCI receptacles. Each cable services one 68-pin VHDCI connector; each STC-136 can service two cables. The STC-136 terminal block provides a simple method for connecting hardware to your controllers using conventional screw terminals. Wires are connected to the terminal by inserting them into slots on the terminal block and tightening lug screws. For ease of use, numbering is identical between VHDCI receptacle pins and STC-136 terminals.

Some users prefer alternatives to the STC-136 for connecting to the XMP controller's VHDCI receptacles. If only a subset of lines are being used, more compact hardware may be preferred. Regardless how your connection scheme is configured, you may use the VHDCI pin-out information in this chapter to design your system.

I/O via Backplane Connection

Some CPCI-6U and -3U controllers perform input-output (I/O) via their backplane connectors. For more information regarding backplane analog I/O on CPCI form factors, please see Chapter 4.

+5 and +24 Volt I/O

XMP controllers accomodate +5VDC or +24VDC optoisolated inputs. Resistors installed on each controller determine which I/O voltage it is configured for; otherwise, they are electronically identical. To determine which voltage your controller is configured for, look for the small, white label.

XMP configurations: +5V and +24V.

CAUTION! Under most conditions, motor axes are NOT freely interchangeable with each other! Always check the compatibility of wiring BEFORE plugging an axis into the connector of a different axis. Otherwise, damage to components and/or the controller may result.

Pay attention to the use of power and ground returns. AGnd should be used for the analog inputs. Digital system grounds (Gnd) are provided for use as a system ground reference. These grounds (AGnd, Gnd) are all tied to a single point on the XMP board.

In-line, fused 5 VDC power is provided for external encoders. Be careful to estimate the additional 5 VDC current required, and the voltage drop across the cables.

Using STC-136 Terminal Blocks

Terminal blocks organize your system wiring, making them especially helpful for lab development. The STC-136 terminal blocks route each CBL-68 pin to a screw terminal on a DIN rail, (Phoenix Contact base). Each STC-136 provides connection to four (4) axes of I/O (a full motion block), and works with both 24 VDC and 5 VDC systems.

Each STC-136 provides connectivity for two (2) axes.

Please note that terminal numbers for the STC-136 are matched one-to-one with VHDCI connector pins. (For example, Pin #1 on the VHDCI is the same as Terminal #1 on the STC-136, and so on.) Therefore, even if you choose not to use STC-136 terminal blocks for connection, you may still use the pin-out information in these chapters to configure your own connectors.

For full STC-136 wiring and pinout diagrams, see Chapter 4.


Connect to Analog Servo Amplifiers
Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Connect to Analog Servo Amplifiers

NOTE: Opto-Isolation of Outputs

A number of controller outputs are optically isolated to protect both the controller and the drive amplifier, such as HOME LIMIT and AMP FAULT.

The XMP's internal logic only controls current to the opto-transistor, thus presenting a "conducting" state between the collector and emitter (of the opto-transistor). Your external wiring determines whether an active low or an active high is presented at the input to your drive.

Note

To maintain electrical isolation between the XMP and external I/O, the power and ground connections should be from an external power source, and should not be tied to the XMP's power or ground connections.
Command Outputs (DAC) Wiring
Connections for command outputs.


Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Drive Enable Wiring

Definition of Fail Safe Wiring

One of the first questions motion system designers must address is how to wire the AmpEnable to a drive for fail safe operation. A fail safe drive enable circuit is one that is disabled when either the controller loses power or control lines are cut.

MEI strongly recommends avoiding any configuration where loss of power leads to a runaway axis. In many cases, the use of automatic, dynamic braking is recommended for high-mass, high-speed loads.

Wiring and Drive Behavior

The actual behavior of a drive enable circuit depends upon two factors:

  • The drive's internal configuration.
  • How the Amp Enable line is wired between the XMP controller and the drive.

Two examples of fail safe wiring are shown below. They do not represent the only correct way to configure drives, but they can be used as guides.

Example 1: Active High

In the case of an active high drive enable input, the drive is "enabled" when the Amp Enable signal is high.

The diagram below shows how to connect a fail-safe circuit. Normally, the controller's output transistor is inactive. When the transistor is inactive (OFF), the resistor pulls Amp Enable Input to ground, disabling the drive. When the transistor is active (ON), the Amp Enable Input is pulled up to +5V or +24V, enabling the drive.

Active high wiring.
Example 2: Active Low

In the case of an active low drive enable input, the drive is "enabled" when the Amp Enable signal is low.

The diagram below shows how to connect a fail-safe circuit. Normally, the controller's output transistor is inactive. When the transistor is inactive (OFF), the resistor pulls the Amp Enable Input up to +5V or +24V, disabling the drive. When the transistor is active (ON), the Amp Enable Input is pulled to ground, enabling the drive.

Active low wiring.
Setting Amp Enable and Polarity from Motion Console

When operating drive amplifiers with Motion Console, you must indicate the following:

          • the state of the amplifier: Enabled or Disabled (unchecked)
          • the polarity of the amplifier: Inverted or Normal (unchecked)

This is done using the Amp Enable and Amp Polarity parameters within the Motor Summary / Config tab page:

The Amp Enable parameter is for use with drives equipped with enable lines. On such drives, the amplifier responds to commands only when the Amp Enable parameter is set to Enabled. If Amp Enable is not enabled, the amplifier will not respond to commands.

For fail-safe operation, the Amp Enable logic is determined by the wiring between the controller and drive. In this case, the Amp Polarity should be set to Inverted.

The Amp Polarity parameter tells the XMP controller whether the output transistor should be normally inactive, to disable the drive (Inverted) or normally active, to disable the drive (Normal). Only the "Inverted" Amp Polarity setting supports fail-safe wiring, and is strongly recommended.

Amp Enable Output

The optically-isolated Amp_Enable outputs provide control of the servo amplifier, allowing the XMP to disable the amplifier under fault conditions.

Active LOW Drive Enable Wiring
Connect Amp Enable output to drive (active LOW).
Active HIGH Drive Enable Wiring
Connect Amp Enable output to drive (+5/24V, active HIGH).
Amplifier Enabling from the MPI

Amplifier enabling is a crucial safety issue in the design of your application. Your system should be designed to anticipate the possibility of a sudden loss of power and/or connectivity to the controller and/or drive.

To make a full accounting of your motion system's safety features, you must also address the system's mecahnical dynamics with a disabled drive. (A disabled drive does NOT necessarily mean that all motion will be stopped!) In many cases, the use of automatic, dynamic braking is recommended for high-mass, high-speed loads.

Determining whether an amplifier remains enabled or disabled with the controller powered OFF depends upon several factors:

  • Does the drive have an Amp Enable line? (Not all drives do. Check this!) Is the drive's Amp Enable line internally configured as active-high or active low?
  • How is the Amp Enable line wired between the controller and the drive? With power OFF to the controller, does wiring pull the drive's Amp Enable line HIGH or LOW?
  • How is the Amp Enable line configured on the controller when it is powered? Is the Amp Enable output transceiver normally ON or OFF? Is the Amp Enable output inverted?
  • Does the application software maintain the Amp Enable line in an enabled state when running? Is the controller's position error limit configured for Abort (disables the drive)? Does the application respond to states, disabling or enabling the drive?
    State logic for active high and active low drives.

    DRIVE

    WIRING

    STATE

    How is the drive's Amp Enable line internally configured?

    With power to the controller OFF, current to the drive's Amp Enable line is...

    When power to the controller is OFF, the drive is...

    Active High

    High

    Enabled

    Low

    Disabled*

    Active Low

    High

    Disabled*

    Low

    Enabled

    * Recommended configuration.

Amp Fault Input
To Pull-up Logic
Connect Amp Fault input to amplifier (pull-up logic).
To Pull-down Logic
Connect Amp Fault input to amplifier (pull-down logic).


Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Connect to Digital Quadrature Encoders

Encoder Wiring

Note

The 100 ohm terminations to the receivers are software-selectable. If you use the Scale Interpolation Module (SIM), you must program the 100 ohm terminations off, i.e., remove them from the circuit. To learn more about encoder termination, please refer to Application Note 206.
Connect to Differential Encoders
Connect to differential encoders (digital).
Connect to Single-ended Encoders

Note

To connect the XMP's differential line receivers to single-ended encoders, you must add a pair of resistors (R1, R2) in the configuration shown, to bias the negative end to the middle of the encoder's output voltage range.
Connect to single-ended encoders (digital).
Broken Wire and Illegal State Detection

The encoder inputs (channel A+, A-, B+, B-) are monitored by the FPGA (an on-board logic component). The encoder inputs are sampled at 20mHz. By default, a digital filter is applied to each encoder input. This digital filter requires that an encoder input (channel A+, A-, B+, B-) be stable for 4 clock cycles (200 nanoseconds) before a transition is recognized, i.e., encoder input states lasting less than 4 clock cycles are filtered out.


Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Connect System I/O

Connect System I/O includes:
Dedicated inputs per axis:
        • Positive and Negative Limit inputs
        • Home input
Global system inputs (one per XMP system)
        • System E-Stop input
        • System Reset input
User I/O (opto-isolated)
        • Individually configurable as input or output
        • There are four user I/Os per 4-axis Motion Block, (or eight user I/Os per board). Each user I/O is individually configurable as input or
          output.
Limit and Home Sensors
Common Ground Logic
Connect home and limit sensors (common ground logic).
Common Vcc Logic
Connect home and limit sensors (common Vcc logic).
System E-Stop Input
To Pull-up Logic
Connect E-stop input to pull-up logic.
To Pull-down Logic
Connect E-stop input to pull-down logic.
System Reset Input
To Pull-up Logic
Connect system reset input to pull-up logic.
To Pull-down Logic
Connect system reset input to pull-down logic.
Opto-isolated User I/O

There are four (4) user I/Os per 4-axis motion block, and each user I/O is individually configurable as input or output.

Connect user I/O input to pull-up logic.

Connect user I/O input to pull-down logic.
As User I/O Outputs
Connect user I/O as outputs to pull-up logic.
Connect user I/O as outputs to pull-down logic.


Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Analog Inputs

There are eight (8) analog inputs per XMP system.

Connect analog inputs.


Connecting XMP Transceiver I/O as a Capture Input

CONTENTS:
Introduction
Connect to Analog Servo Amplifiers
Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Connecting XMP Transceiver I/O as a Capture Input

There are twelve (12) I/Os for each 4-axis motion block.

Connect Transceiver as Differential Capture Input
Connect transceiver as differential input.
Connect Transceiver as Single-ended Capture Input
Connect transceiver as single-ended input.

Transceiver as a Compare Output

Connect Transceiver as Differential Compare Output
Connect transceiver as differential compare output.


Connect Two XMP Boards (12-16 Axes)

CONTENTS:
Introduction
Connect to Analog Servo Amplifiers
Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Connect Two XMP Boards (12-16 Axes)

To create systems with more than eight (8) axes, use two XMP boards, with one board configured as the main, and the other board configured as the expansion.

Typical Connections s
Main/expansion axis assignments: CPCI.

Main/expansion axis assignments: PCI.


Configuring Analog Connections

CONTENTS:
Introduction
Connect to Analog Servo Amplifiers
Drive Enable Wiring
Connect To Digital Quadrature Encoders
Connect System I/O
Analog Inputs
Connect XMP Transceiver I/O as a Capture Input
Connect Two XMP Boards (12-16Axes)
Configuring Analog Connections
CHAPTER 3
Configuring An XMP-analog Motion Control System

Configuring Analog Connections

This section provides more general guidance for configuring analog controllers with various hardware (servo amps; encoders, etc.).

XMP-PCI, XMP-CPCI

Connections to Servo Motors

XMP-series controllers can control brush servo motors, brushless servo motors, or linear brush/brushless motors. Basic connections require an analog output signal (from the controller to the amplifier) and an encoder input (from the motor to the controller).

Most amplifiers support either Velocity mode (voltage control) Torque mode (current control) or both. The XMP controller can be used with either servo motor/amplifier package.

XMP-series controllers accept RS-422 compatible (0V to +5V, 40mA max) encoder input from either differential or single-ended encoders. Differential encoders are preferred due to their excellent noise immunity. The connections for a single-ended encoder are identical to a differential encoder except that references must be connected to channel A- and channel B-.

The controller reads the index pulse (either single-ended or differential ended). Typically, there is one index pulse per revolution of the encoder (rotary type), which can be used for homing. Encoder signals are read in quadrature. Every line on the encoder will produce a rising edge and a falling edge on channels A+ and B+ which is interpreted by the XMP controller as four encoder counts.

Brush Servo Motors

The minimum required connections to brush-type servo are: Analog signal
( ± 10V), +5V, Signal Ground, Encoder Channel A+, Encoder Channel B+. Typical connections for a brush servo motor with a differential encoder follow.

Typical brush servo motor connections.

Note

Any unused lines should be left unconnected.

Brushless Servo Motors

Typical connections for a brushless servo motor with a differential encoder are:

Typical brushless servo motor connections.

Typical brushless servo motor drives of this configuration are "intelligent." If single ended encoders are used, external references will need to be supplied.

Step-and-Direction Controlled Servo Motors

Some brushless servos are controlled by step-and-direction pulses. With this scheme, the position information is communicated by step pulses, and the PID loop is handled internally by the drive itself.

Connections to Step Motors
Open-loop Step Motors

XMP controllers can control step motors in open-loop (no feedback) configurations. The XMP can also be configured for STEP LOOPBACK. When this is enabled, the motor Position Error Limit and Axis Settling will depend on the output steps being read back into the actual position register. If STEP LOOPBACK is disabled, an external feedback device (e.g. encoder) will be needed for determining position error limits and axis settling. In either case, the output is generated regardless of actual position.

Typical open-loop step motor connections for step drives triggering on the rising edge.

For stepper drives that trigger on the falling edge, invert the step output transceiver. This can be done from Motion Console by enabling the XCVR A: Invert (or XCVR B: Invert, etc.) parameter in the Motor Summary / I/O page.

Note

To determine whether your drive triggers on the rising or falling step edge, consult the drive manufacturer's manual.

Connections for Dual-loop Control

XMP-series controllers can be configured for dual-loop control. In dual-loop control, the velocity information for the PID derivative term (Kd) is derived from a rotary encoder on the motor shaft, and the position information for the PID proportional and integral terms is derived from an encoder on the load itself.

The axis that will be used for the rotary encoder is configurable through software and can be any axis that is not controlling a motor. For example, if axis 0 is configured for velocity feedback and axis 1 is configured for positional feedback, your system would be connected as shown in the next figure.

Dual-loop encoder connections with differential encoders.
MPI Support for Steppers

Support for stepper motor control is included within the MPI (Motion Programming Interface).

Transceivers

All transceiver and user I/O are part of the "Motor" object.

Each hardware axis has three (3) transceivers dedicated to it, labeled XCVRA, XCVRB, and XCVRC. The XCVRA, XCVRB, and XCVRC transceivers support:

All three transceivers support input/output, normal/inverted.

Transceiver

Input or Output?

Normal or Inverted?

XCVRA

Yes

Yes

XCVRB

Yes

Yes

XCVRC

Yes

Yes

Additionally, the A and B transceivers support more features than the C transceivers do:

A and B transceivers support more features.

Transceiver

Step or Dir?

CW or CCW?

Quad A or Quad B?

Normal or Inverted?

Compare?

XCVRA

Yes

Yes

Yes

Yes

No

XCVRB

Yes

Yes

Yes

Yes

No

XCVRC

No

No

No

Yes

Yes

Note that only sensible XCVRA/XCVRB configurations are permitted. For example, if XCVRA is configured for Step, then XCVRB should be configured for Dir. If XCVRA is configured for Dir, then XCVRB should be configured for Step. Refer to the next table.

Transceiver configurations that are supported.

XCVRA

XCVRB

XCVRC

Step

Dir

Dir

Step

CW

CCW

CCW

CW

QuadA

QuadB

QuadB

QuadA

Step/Dir & CW/CCW Specifications
Step/dir and CW/CCW specifications.

Pulse width range for Step, CW & CCW

100 nsec to 25.5 microsec

Maximum duty cycle must be less than

50% (or 25.5 microsec)

Minimum separation between Dir edge and rising Step edge (or between CW and CCW edges)

125 nanosec

Maximum step output rate

2.5 MHz

The maximum separation between the Dir edge and the rising Step edge depends upon the sample rate and the commanded motion. A rule of thumb is that the Dir edge occurs at the start of the DSP's trajectory calculator (when the command velocity is non-zero), and the first Step occurs when the command position increments the first whole count. The time separation can be estimated from the commanded acceleration (Accel):

For example, if acceleration is 100,000 cts/sec2, then the separation between the Dir edge and the first Step edge is

which computes to Time = 4.5 milliseconds

The minimum separation between the Dir edge and the first Step edge is 125 nanoseconds. Note that the XMP increments its counter on each rising edge of the Step or CW signal.

Step/dir (and CW/CCW) and motor motion .

Step/dir and velocity.
Stepper Loopback

When the Loopback feature is enabled, the Step/Dir (or CW/CCW) logic is routed back into the encoder inputs. Note that the DSP doesn't use the feedback for control. There are two to three samples of latency between when the DSP's command position is updated and when the actual position (loopback) is updated. Also, loopback is not affected by "inverted" configurations.

The position error limit is still valid for loopback operations. If Loopback is not enabled, you can connect the encoder inputs to actual encoders.

HELPFUL TIP: Stepper loopback is very useful for motor simulation. When real servo motors are not available, the controller's stepper motor and loopback configurations make it possible to develop software.

Closed Loop Steppers

Currently, there is no explicit support for closed loop stepper configurations. But, it is possible to correct the final position based on the actual position via application software, since the encoder inputs are valid with Step/Dir and CW/CCW configurations.

Stepper Configuration using Motion Console

To configure a Stepper using Motion Console, you must set the following parameters:

Parameters used to configure a stepper in Motion Console.

Object

Motion Console Parameter

Setting

Motor

Type

Stepper

Stepper pulse width

2.55 (10-5)

Stepper loopback

Yes

Transceiver A config

Step or CW

Transceiver B config

Dir or CCW

Filter

Algorithm

None


Introduction
PCI
CPCI-6U
CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

Introduction

This chapter describes analog I/O pin-outs for the XMP-PCI, XMP-CPCI-6U, and XMP-CPCI-3U controllers. The first section of this chapter describes connector hardware. The second section of this chapter describes the actual I/O configuration, including pin-outs, organized by form factor.

SERCOS I/O is described in Chapter 5 of this manual.

Identifying Analog I/O Hardware

Your analog XMP controller's I/O hardware type can be easily identified by examining the connection between the XMP controller and drive:

VHDCI Cabling and Terminal Block

XMP-PCI and XMP-CPCI use the same 68-pin cable for all front panel (VHDCI) I/O connections.

STC-136 Terminal Connector Blocks

All VHDCI connectors used with XMP controllers are 68-pin types. Corresponding to this, terminal blocks having 68 terminals per side are preferred. MEI recommends the STC-136, which can accommodate up to two cables. These use screw terminals for analog wiring.

WARNING! Many "controller problems" can be traced to faulty wiring. As with all analog wiring, it is the user's responsibility to verify that wiring is correctly connected per specifications BEFORE applying power. Verify the following when wiring terminal blocks:

At the Terminal Block
  • Verify all wiring is clearly and correctly labeled and color-coded for easy identification. Assembly personnel should have clear and concise wiring diagrams available when wiring.
  • Connect wires to terminal blocks by referencing terminal numbers, NOT by a wire's placement relative to another wire.
  • Strip wires appropriately: removing too much insulation will leave bare wires exposed and susceptible to short-circuits; removing too little insulation will prevent electrical contact inside the lug. Do not pinch or crimp wires when stripping--they will break!
  • Do not insert wire above a terminal block's lug. When the lug is tightened, it will not close on the wire, failing to make contact. Verify that debris does not enter the lug with the bare wire; it may prevent complete closure of the lug.
  • Verify that lugs are tight. Remove all loose wire strands.
  • Discard all terminal blocks with damaged traces.
At the Connectors
  • Verify that connector pins are straight BEFORE attempting to connect cables. Bent pins can short-circuit, or ruin a connector! If connectors resist, do not force them. Check for problems first.
  • Observe electrostatic discharge (ESD) precautions while handling connectors and terminal blocks. High-level ESD can damage circuitry over cables.


PCI
CPCI-6U
CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

PCI

All motion drive I/O for XMP-PCI controllers is performed via VHDCI connectors on the rear end panel of the controller. Each VHDCI connector is connected to a motion drive via cable. Pin-outs are described below:

XMP-PCI, VHDCI Connectors, Main Board
Axis 0-1, VHDCI Connector (XMP-PCI)

Connector for axes 0 and 1 (PCI main board).

Pin

Signal

Signal

Pin

1

Analog_IN_0+

Analog_IN_0-

35

2

Analog_IN_1+

Analog_IN_1-

36

3

Gnd

AGnd

37

4

Enc0_A+

Enc0_A-

38

5

Enc0_B+

Enc0_B-

39

6

Enc0_I+

Enc0_I-

40

7

Home0_IN

5V_OUT

41

8

Pos_Lim0_IN

Gnd

42

9

Neg_Lim0_IN

HomeLim0_Rtn

43

10

Cmd_Dac_OUT_0+

Cmd_Dac_OUT_0-

44

11

Aux_Dac_OUT_0+

Aux_Dac_OUT_0-

45

12

Amp_Flt0_IN

Amp_Flt0_Rtn

46

13

Amp_En0_Collector

Amp_En0_Emitter

47

14

UserIO_A0

UserIO_A0_Rtn

48

15

Xcvr0A+

Xcvr0A-

49

16

Xcvr0B+

Xcvr0B-

50

17

Xcvr0C+

Xcvr0C-

51

18

Enc1_A+

Enc1_A-

52

19

Enc1_B+

Enc1_B-

53

20

Enc1_I+

Enc1_I-

54

21

Home1_IN

5V_OUT

55

22

Pos_Lim1_IN

Gnd

56

23

Neg_Lim1_IN

HomeLim1_Rtn

57

24

Cmd_Dac_OUT_1+

Cmd_Dac_OUT_1-

58

25

Aux_Dac_OUT_1+

Aux_Dac_OUT_1-

59

26

Amp_Flt1_IN

Amp_Flt1_Rtn

60

27

Amp_En1_Collector

Amp_En1_Emitter

61

28

Gnd

Gnd

62

29

Xcvr1A+

Xcvr1A-

63

30

Xcvr1B+

Xcvr1B-

64

31

Xcvr1C+

Xcvr1C-

65

32

UserIO_A1

UserIO_A1_Rtn

66

33

RESET_IN

UserIO_A2

67

34

ESTOP_IN

UserIO_A2_Rtn

68
Axis 2-3 VHDCI Connector (PCI)

Connector for axes 2 and 3 (PCI main board).

Pin

Signal

Signal

Pin

1

EncA_A+

EncA_A-

35

2

EncA_B+

EncA_B-

36

3

EncA_I+

EncA_I-

37

4

Enc2_A+

Enc2_A-

38

5

Enc2_B+

Enc2_B-

39

6

Enc2_I+

Enc2_I-

40

7

Home2_IN

5V_OUT

41

8

Pos_Lim2_IN

Gnd

42

9

Neg_Lim2_IN

HomeLim2_Rtn

43

10

Cmd_Dac_OUT_2+

Cmd_Dac_OUT_2-

44

11

Aux_Dac_OUT_2+

Aux_Dac_OUT_2-

45

12

Amp_Flt2_IN

Amp_Flt2_Rtn

46

13

Amp_En2_Collector

Amp_En2_Emitter

47

14

UserIO_A3

UserIO_A3_Rtn

48

15

Xcvr2A+

Xcvr2A-

49

16

Xcvr2B+

Xcvr2B-

50

17

Xcvr2C+

Xcvr2C-

51

18

Enc3_A+

Enc3_A-

52

19

Enc3_B+

Enc3_B-

53

20

Enc3_I+

Enc3_I-

54

21

Home3_IN

5V_OUT

55

22

Pos_Lim3_IN

Gnd

56

23

Neg_Lim3_IN

HomeLim3_Rtn

57

24

Cmd_Dac_OUT_3+

Cmd_Dac_OUT_3-

58

25

Aux_Dac_OUT_3+

Aux_Dac_OUT_3-

59

26

Amp_Flt3_IN

Amp_Flt3_Rtn

60

27

Amp_En3_Collector

Amp_En3_Emitter

61

28

Gnd

Gnd

62

29

Xcvr3A+

Xcvr3A-

63

30

Xcvr3B+

Xcvr3B-

64

31

Xcvr3C+

Xcvr3C-

65

32

Gnd

AGnd

66

33

Analog_IN_2+

Analog_IN_2-

67

34

Analog_IN_3+

Analog_IN_3-

68
Axis 4-5 VHDCI Connector (PCI)

Connector for axes 4 and 5 (PCI main board).

Pin

Signal

Signal

Pin

1

UserIO_B0

UserIO_B0_Rtn

35

2

UserIO_B1

UserIO_B1_Rtn

36

3

Gnd

Gnd

37

4

Enc4_A+

Enc4_A-

38

5

Enc4_B+

Enc4_B-

39

6

Enc4_I+

Enc4_I-

40

7

Home4_IN

5V_OUT

41

8

Pos_Lim4_IN

Gnd

42

9

Neg_Lim4_IN

HomeLim4_Rtn

43

10

Cmd_Dac_OUT_4+

Cmd_Dac_OUT_4-

44

11

Aux_Dac_OUT_4+

Aux_Dac_OUT_4-

45

12

Amp_Flt4_IN

Amp_Flt4_Rtn

46

13

Amp_En4_Collector

Amp_En4_Emitter

47

14

UserIO_B2

UserIO_B2_Rtn

48

15

Xcvr4A+

Xcvr4A-

49

16

Xcvr4B+

Xcvr4B-

50

17

Xcvr4C+

Xcvr4C-

51

18

Enc5_A+

Enc5_A-

52

19

Enc5_B+

Enc5_B-

53

20

Enc5_I+

Enc5_I-

54

21

Home5_IN

5V_OUT

55

22

Pos_Lim5_IN

Gnd

56

23

Neg_Lim5_IN

HomeLim5_Rtn

57

24

Cmd_Dac_OUT_5+

Cmd_Dac_OUT_5-

58

25

Aux_Dac_OUT_5+

Aux_Dac_OUT_5-

59

26

Amp_Flt5_IN

Amp_Flt5_Rtn

60

27

Amp_En5_Collector

Amp_En5_Emitter

61

28

Gnd

Gnd

62

29

Xcvr5A+

Xcvr5A-

63

30

Xcvr5B+

Xcvr5B-

64

31

Xcvr5C+

Xcvr5C-

65

32

Gnd

AGnd

66

33

Analog_IN_4+

Analog_IN_4-

67

34

Analog_IN_5+

Analog_IN_5-

68
Axis 6-7 VHCDI Connector (PCI)

Connector for axes 6 and 7 (PCI main board).

Pin

Signal

Signal

Pin

1

Analog_IN_6+

Analog_IN_6-

35

2

Analog_IN_7+

Analog_IN_7-

36

3

Gnd

AGnd

37

4

Enc6_A+

Enc6_A-

38

5

Enc6_B+

Enc6_B-

39

6

Enc6_I+

Enc6_I-

40

7

Home6_IN

5V_OUT

41

8

Pos_Lim6_IN

Gnd

42

9

Neg_Lim6_IN

HomeLim6_Rtn

43

10

Cmd_Dac_OUT_6+

Cmd_Dac_OUT_6-

44

11

Aux_Dac_OUT_6+

Aux_Dac_OUT_6-

45

12

Amp_Flt6_IN

Amp_Flt6_Rtn

46

13

Amp_En6_Collector

Amp_En6_Emitter

47

14

UserIO_B3

UserIO_B3_Rtn

48

15

Xcvr6A+

Xcvr6A-

49

16

Xcvr6B+

Xcvr6B-

50

17

Xcvr6C+

Xcvr6C-

51

18

Enc7_A+

Enc7_A-

52

19

Enc7_B+

Enc7_B-

53

20

Enc7_I+

Enc7_I-

54

21

Home7_IN

5V_OUT

55

22

Pos_Lim7_IN

Gnd

56

23

Neg_Lim7_IN

HomeLim7_Rtn

57

24

Cmd_Dac_OUT_7+

Cmd_Dac_OUT_7-

58

25

Aux_Dac_OUT_7+

Aux_Dac_OUT_7-

59

26

Amp_Flt7_IN

Amp_Flt7_Rtn

60

27

Amp_En7_Collector

Amp_En7_Emitter

61

28

Gnd

Gnd

62

29

Xcvr7A+

Xcvr7A-

63

30

Xcvr7B+

Xcvr7B-

64

31

Xcvr7C+

Xcvr7C-

65

32

EncB_A+

EncB_A-

66

33

EncB_B+

EncB_B-

67

34

EncB_I+

EncB_I-

68
XMP-PCI, VHDCI Connectors, Expansion Board
Axis 8-9 VHDCI Connector (PCI)

Connector for axes 8 and 9 (PCI expansion board).

Pin

Signal

Signal

Pin

1

Not Connected

Not Connected

35

2

Not Connected

Not Connected

36

3

Gnd

AGnd

37

4

Enc8_A+

Enc8_A-

38

5

Enc8_B+

Enc8_B-

39

6

Enc8_I+

Enc8_I-

40

7

Home8_IN

5V_OUT

41

8

Pos_Lim8_IN

Gnd

42

9

Neg_Lim8_IN

HomeLim8_Rtn

43

10

Cmd_Dac_OUT_8+

Cmd_Dac_OUT_8-

44

11

Aux_Dac_OUT_8+

Aux_Dac_OUT_8-

45

12

Amp_Flt8_IN

Amp_Flt8_Rtn

46

13

Amp_En8_Collector

Amp_En8_Emitter

47

14

UserIO_C0

UserIO_C0_Rtn

48

15

Xcvr8A+

Xcvr8A-

49

16

Xcvr8B+

Xcvr8B-

50

17

Xcvr8C+

Xcvr8C-

51

18

Enc9_A+

Enc9_A-

52

19

Enc9_B+

Enc9_B-

53

20

Enc9_I+

Enc9_I-

54

21

Home9_IN

5V_OUT

55

22

Pos_Lim9_IN

Gnd

56

23

Neg_Lim9_IN

HomeLim9_Rtn

57

24

Cmd_Dac_OUT_9+

Cmd_Dac_OUT_9-

58

25

Aux_Dac_OUT_9+

Aux_Dac_OUT_9-

59

26

Amp_Flt9_IN

Amp_Flt9_Rtn

60

27

Amp_En9_Collector

Amp_En9_Emitter

61

28

Gnd

Gnd

62

29

Xcvr9A+

Xcvr9A-

63

30

Xcvr9B+

Xcvr9B-

64

31

Xcvr9C+

Xcvr9C-

65

32

UserIO_C1

UserIO_C1_Rtn

66

33

Not Connected

UserIO_C2

67

34

Not Connected

UserIO_C2_Rtn

68
Axis 10-11 VHCDI Connector (PCI)

Connector for axes 10 and 11 (PCI expansion board).

Pin

Signal

Signal

Pin

1

EncC_A+

EncC_A-

35

2

EncC_B+

EncC_B-

36

3

EncC_I+

EncC_I-

37

4

Enc10_A+

Enc10_A-

38

5

Enc10_B+

Enc10_B-

39

6

Enc10_I+

Enc10_I-

40

7

Home10_IN

5V_OUT

41

8

Pos_Lim10_IN

Gnd

42

9

Neg_Lim10_IN

HomeLim10_Rtn

43

10

Cmd_Dac_OUT_10+

Cmd_Dac_OUT_10-

44

11

Aux_Dac_OUT_10+

Aux_Dac_OUT_10-

45

12

Amp_Flt10_IN

Amp_Flt10_Rtn

46

13

Amp_En10_Collector

Amp_En10_Emitter

47

14

UserIO_C3

UserIO_C3_Rtn

48

15

Xcvr10A+

Xcvr10A-

49

16

Xcvr10B+

Xcvr10B-

50

17

Xcvr10C+

Xcvr10C-

51

18

Enc11_A+

Enc11_A-

52

19

Enc11_B+

Enc11_B-

53

20

Enc11_I+

Enc11_I-

54

21

Home11_IN

5V_OUT

55

22

Pos_Lim11_IN

Gnd

56

23

Neg_Lim11_IN

HomeLim11_Rtn

57

24

Cmd_Dac_OUT_11+

Cmd_Dac_OUT_11-

58

25

Aux_Dac_OUT_11+

Aux_Dac_OUT_11-

59

26

Amp_Flt11_IN

Amp_Flt11_Rtn

60

27

Amp_En11_Collector

Amp_En11_Emitter

61

28

Gnd

Gnd

62

29

Xcvr11A+

Xcvr11A-

63

30

Xcvr11B+

Xcvr11B-

64

31

Xcvr11C+

Xcvr11C-

65

32

Gnd

AGnd

66

33

Not Connected

Not Connected

67

34

Not Connected

Not Connected

68
Axis 12-13 VHDCI Connector (PCI)

Connector for axes 12 and 13 (PCI expansion board).

Pin

Signal

Signal

Pin

1

UserIO_D0

UserIO_D0_Rtn

35

2

UserIO_D1

UserIO_D1_Rtn

36

3

Gnd

Gnd

37

4

Enc12_A+

Enc12_A-

38

5

Enc12_B+

Enc12_B-

39

6

Enc12_I+

Enc12_I-

40

7

Home12_IN

5V_OUT

41

8

Pos_Lim12_IN

Gnd

42

9

Neg_Lim12_IN

HomeLim12_Rtn

43

10

Cmd_Dac_OUT_12+

Cmd_Dac_OUT_12-

44

11

Aux_Dac_OUT_12+

Aux_Dac_OUT_12-

45

12

Amp_Flt12_IN

Amp_Flt12_Rtn

46

13

Amp_En12_Collector

Amp_En12_Emitter

47

14

UserIO_D2

UserIO_D2_Rtn

48

15

Xcvr12A+

Xcvr12A-

49

16

Xcvr12B+

Xcvr12B-

50

17

Xcvr12C+

Xcvr12C-

51

18

Enc13_A+

Enc13_A-

52

19

Enc13_B+

Enc13_B-

53

20

Enc13_I+

Enc13_I-

54

21

Home13_IN

5V_OUT

55

22

Pos_Lim13_IN

Gnd

56

23

Neg_Lim13_IN

HomeLim13_Rtn

57

24

Cmd_Dac_OUT_13+

Cmd_Dac_OUT_13-

58

25

Aux_Dac_OUT_13+

Aux_Dac_OUT_13-

59

26

Amp_Flt13_IN

Amp_Flt13_Rtn

60

27

Amp_En13_Collector

Amp_En13_Emitter

61

28

Gnd

Gnd

62

29

Xcvr13A+

Xcvr13A-

63

30

Xcvr13B+

Xcvr13B-

64

31

Xcvr13C+

Xcvr13C-

65

32

Gnd

AGnd

66

33

Not Connected

Not Connected

67

34

Not Connected

Not Connected

68
Axis 14-15 VHDCI Connector (PCI)

Connector for axes 14 and 15 (PCI expansion board).

Pin

Signal

Signal

Pin

1

Not Connected

Not Connected

35

2

Not Connected

Not Connected

36

3

Gnd

AGnd

37

4

Enc14_A+

Enc14_A-

38

5

Enc14_B+

Enc14_B-

39

6

Enc14_I+

Enc14_I-

40

7

Home6_IN

5V_OUT

41

8

Pos_Lim14_IN

Gnd

42

9

Neg_Lim14_IN

HomeLim14_Rtn

43

10

Cmd_Dac_OUT_14+

Cmd_Dac_OUT_14-

44

11

Aux_Dac_OUT_14+

Aux_Dac_OUT_14-

45

12

Amp_Flt14_IN

Amp_Flt14_Rtn

46

13

Amp_En14_Collector

Amp_En14_Emitter

47

14

UserIO_D3

UserIO_D3_Rtn

48

15

Xcvr14A+

Xcvr14A-

49

16

Xcvr14B+

Xcvr14B-

50

17

Xcvr14C+

Xcvr14C-

51

18

Enc15_A+

Enc15_A-

52

19

Enc15_B+

Enc15_B-

53

20

Enc15_I+

Enc15_I-

54

21

Home15_IN

5V_OUT

55

22

Pos_Lim15_IN

Gnd

56

23

Neg_Lim15_IN

HomeLim15_Rtn

57

24

Cmd_Dac_OUT_15+

Cmd_Dac_OUT_15-

58

25

Aux_Dac_OUT_15+

Aux_Dac_OUT_15-

59

26

Amp_Flt15_IN

Amp_Flt15_Rtn

60

27

Amp_En15_Collector

Amp_En15_Emitter

61

28

Gnd

Gnd

62

29

Xcvr15A+

Xcvr15A-

63

30

Xcvr15B+

Xcvr15B-

64

31

Xcvr15C+

Xcvr15C-

65

32

EncD_A+

EncD_A-

66

33

EncD_B+

EncD_B-

67

34

EncD_I+

EncD_I-

68


CPCI-6U
CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

CPCI-6U

VHDCI Connectors, XMP-CPCI-6U

Many XMP-CPCI-6U boards (main and expansion) feature VHDCI connectors on their front panels. I/O for these connectors is identical to those for XMP-PCI controllers. For pin-outs, please refer to the XMP-PCI section in this chapter.

Backplane Connectors, XMP-CPCI-6U

On CPCI-6U controllers using backplane I/O, drive signals are conveyed through connectors J3, J4 and J5.

For main boards, axes 0-3 are controlled through connector J5. Axes 4-7 are controlled through connector J4. User I/O is provided through connector J3.

On expansion boards, axes 8-11 are controlled through connector J5. Axes 12-15 are controlled through connector J4. User I/O is provided through connector J3.

On both main and expansion boards, connector J1 is reserved for computer data bussing. For more information, see Chapter 2.

CPCI-6U Main Board, CPCI Backplane Connector J5

J5 backplane connector (CPCI main board).

Pin

Signal

Signal

Pin

A1

Analog_IN_0+

Analog_IN_3+

D1

A2

Analog_IN_1+

Analog_IN_2+

D2

A3

Enc0_A+

Xcvr3C+

D3

A4

Enc0_B+

Xcvr3B+

D4

A5

Enc0_I+

Xcvr3A+

D5

A6

Cmd_Dac_OUT_0+

Amp_En3_Collector

D6

A7

Aux_Dac_OUT_0+

Amp_Flt3_IN

D7

A8

Amp_Flt0_IN

Cmd_Dac_OUT_3+

D8

A9

Amp_En0_Collector

Aux_Dac_OUT_3+

D9

A10

Xcvr0A+

Enc3_I+

D10

A11

Xcvr0B+

Enc3_B+

D11

A12

Xcvr0C+

Enc3_A+

D12

A13

Enc1_A+

Xcvr2C+

D13

A14

Enc1_B+

Xcvr2B+

D14

A15

Enc1_I+

Xcvr2A+

D15

A16

Cmd_Dac_OUT_1+

Amp_En2_Collector

D16

A17

Aux_Dac_OUT_1+

Amp_Flt2_IN

D17

A18

Amp_Flt1_IN

Cmd_Dac_OUT_2+

D18

A19

Amp_En1_Collector

Aux_Dac_OUT_2+

D19

A20

Xcvr1A+

Enc2_I+

D20

A21

Xcvr1B+

Enc2_B+

D21

A22

Xcvr1C+

Enc2_A+

D22

B1

Analog_IN_0-

Analog_IN_3-

E1

B2

Analog_IN_1-

Analog_IN_2-

E2

B3

Enc0_A-

Xcvr3C-

E3

B4

Enc0_B-

Xcvr3B-

E4

B5

Enc0_I-

Xcvr3A-

E5

B6

Cmd_Dac_OUT_0-

Amp_En3_Emitter

E6

B7

Aux_Dac_OUT_0-

Amp_Flt3_Rtn

E7

B8

Amp_Flt0_Rtn

Cmd_Dac_OUT_3-

E8

B9

Amp_En0_Emitter

Aux_Dac_OUT_3-

E9

B10

Xcvr0A-

Enc3_I-

E10

B11

Xcvr0B-

Enc3_B-

E11

B12

Xcvr0C-

Enc3_A-

E12

B13

Enc1_A-

Xcvr2C-

E13

B14

Enc1_B-

Xcvr2B-

E14

B15

Enc1_I-

Xcvr2A-

E15

B16

Cmd_Dac_OUT_1-

Amp_En2_Emitter

E16

B17

Aux_Dac_OUT_1-

Amp_Flt2_Rtn

E17

B18

Amp_Flt1_Rtn

Cmd_Dac_OUT_2-

E18

B19

Amp_En1_Emitter

Aux_Dac_OUT_2-

E19

B20

Xcvr1A-

Enc2_I-

E20

B21

Xcvr1B-

Enc2_B-

E21

B22

Xcvr1C-

Enc2_A-

E22

C1

AGnd

Gnd

F1

C2

Gnd

Gnd

F2

C3

Home0_IN

Gnd

F3

C4

Pos_Lim0_IN

Gnd

F4

C5

Neg_Lim0_IN

Gnd

F5

C6

HomeLim0_Rtn

Gnd

F6

C7

HomeLim3_Rtn

Gnd

F7

C8

Neg_Lim3_IN

Gnd

F8

C9

Pos_Lim3_IN

Gnd

F9

C10

Home3_IN

Gnd

F10

C11

Not Connected

Gnd

F11

C12

5V_OUT

Gnd

F12

C13

Home1_IN

Gnd

F13

C14

Pos_Lim1_IN

Gnd

F14

C15

Neg_Lim1_IN

Gnd

F15

C16

HomeLim1_Rtn

Gnd

F16

C17

HomeLim2_Rtn

Gnd

F17

C18

Neg_Lim2_IN

Gnd

F18

C19

Pos_Lim2_IN

Gnd

F19

C20

Home2_IN

Gnd

F20

C21

Gnd

Gnd

F21

C22

5V_OUT

Gnd

F22
CPCI-6U Main Board, CPCI Backplane Connector J4

J4 backplane connector (CPCI main board).

Pin

Signal

Signal

Pin

A1

Enc4_A+

Xcvr7C+

D1

A2

Enc4_B+

Xcvr7B+

D2

A3

Enc4_I+

Xcvr7A+

D3

A4

Cmd_Dac_OUT_4+

Amp_En7_Collector

D4

A5

Aux_Dac_OUT_4+

Amp_Flt7_IN

D5

A6

Amp_Flt4_IN

Aux_Dac_OUT_7+

D6

A7

Amp_En4_Collector

Cmd_Dac_OUT_7+

D7

A8

Xcvr4A+

Enc7_I+

D8

A9

Xcvr4B+

Enc7_B+

D9

A10

Xcvr4C+

Enc7_A+

D10

A11

Enc5_A+

Xcvr6C+

D11

A12

Not Connected

Not Connected

D12

A13

D13

A14

D14

A15

Enc5_B+

Xcvr6B+

D15

A16

Enc5_I+

Xcvr6A+

D16

A17

Cmd_Dac_OUT_5+

Amp_En6_Collector

D17

A18

Aux_Dac_OUT_5+

Amp_Flt6_IN

D18

A19

Amp_Flt5_IN

Aux_Dac_OUT_6+

D19

A20

Amp_En5_Collector

Cmd_Dac_OUT_6+

D20

A21

Xcvr5A+

Enc6_I+

D21

A22

Xcvr5B+

Enc6_B+

D22

A23

Xcvr5C+

Enc6_A+

D23

A24

Analog_IN_4+

Analog_IN_7+

D24

A25

Analog_IN_5+

Analog_IN_6+

D25

B1

Enc4_A-

Xcvr7C-

E1

B2

Enc4_B-

Xcvr7B-

E2

B3

Enc4_I-

Xcvr7A-

E3

B4

Cmd_Dac_OUT_4-

Amp_En7_Emitter

E4

B5

Aux_Dac_OUT_4-

Amp_Flt7_Rtn

E5

B6

Amp_Flt4_Rtn

Aux_Dac_OUT_7-

E6

B7

Amp_En4_Emitter

Cmd_Dac_OUT_7-

E7

B8

Xcvr4A-

Enc7_I-

E8

B9

Xcvr4B-

Enc7_B-

E9

B10

Xcvr4C-

Enc7_A-

E10

B11

Enc5_A-

Xcvr6C-

E11

B12

Not Connected

Not Connected

E12

B13

E13

B14

E14

B15

Enc5_B-

Xcvr6B-

E15

B16

Enc5_I-

Xcvr6A-

E16

B17

Cmd_Dac_OUT_5-

Amp_En6_Emitter

E17

B18

Aux_Dac_OUT_5-

Amp_Flt6_Rtn

E18

B19

Amp_Flt5_Rtn

Aux_Dac_OUT_6-

E19

B20

Amp_En5_Emitter

Cmd_Dac_OUT_6-

E20

B21

Xcvr5A-

Enc6_I-

E21

B22

Xcvr5B-

Enc6_B-

E22

B23

Xcvr5C-

Enc6_A-

E23

B24

Analog_IN_4-

Analog_IN_7-

E24

B25

Analog_IN_5-

Analog_IN_6-

E25

C1

5V_OUT

Gnd

F1

C2

Gnd

Gnd

F2

C3

Home4_IN

Gnd

F3

C4

Pos_Lim4_IN

Gnd

F4

C5

Neg_Lim4_IN

Gnd

F5

C6

HomeLim4_Rtn

Gnd

F6

C7

HomeLim7_Rtn

Gnd

F7

C8

Neg_Lim7_IN

Gnd

F8

C9

Pos_Lim7_IN

Gnd

F9

C10

Home7_IN

Gnd

F10

C11

5V_OUT

Gnd

F11

C12

Not Connected

Gnd

F12

C13

Gnd

F13

C14

Gnd

F14

C15

Gnd

F15

C16

Home5_IN

Gnd

F16

C17

Pos_Lim5_IN

Gnd

F17

C18

Neg_Lim5_IN

Gnd

F18

C19

HomeLim5_Rtn

Gnd

F19

C20

HomeLim6_Rtn

Gnd

F20

C21

Neg_Lim6_IN

Gnd

F21

C22

Pos_Lim6_IN

Gnd

F22

C23

Home6_IN

Gnd

F23

C24

Gnd

Gnd

F24

C25

AGnd

Gnd

F25

CPCI-6U Main Board, CPCI Backplane Connector J3: User I/O

J3 backplane connector (CPCI main board).

Pin

Signal

Signal

Pin

A1

D1

A2

D2

A3

D3

A4

D4

A5

D5

A6

Not Connected

Not Connected

D6

A7

D7

A8

D8

A9

D9

A10

D10

A11

D11

A12

D12

A13

UserIO_A1

UserIO_A2_Rtn

D13

A14

ESTOP_IN

UserIO_B1

D14

A15

UserIO_A3

UserIO_B3

D15

A16

UserIO_A0

UserIO_B2

D16

A17

EncA_I+

EncB_I+

D17

A18

EncA_B+

EncB_B+

D18

A19

EncA_A+

EncB_A+

D19

B1

Not Connected

Not Connected

E1

B2

E2

B3

E3

B4

E4

B5

E5

B6

E6

B7

E7

B8

E8

B9

E9

B10

E10

B11

E11

B12

E12

B13

UserIO_A1_Rtn

UserIO_A2

E13

B14

RESET_IN

UserIO_B1_Rtn

E14

B15

UserIO_A3_Rtn

UserIO_B3_Rtn

E15

B16

UserIO_A0_Rtn

UserIO_B2_Rtn

E16

B17

EncA_I-

EncB_I-

E17

B18

EncA_B-

EncB_B-

E18

B19

EncA_A-

EncB_A-

E19

C1

Gnd

Gnd

F1

C2

Not Connected

Gnd

F2

C3

Gnd

Gnd

F3

C4

Not Connected

Gnd

F4

C5

Gnd

Gnd

F5

C6

Not Connected

Gnd

F6

C7

Gnd

F7

C8

Gnd

F8

C9

Gnd

F9

C10

Gnd

F10

C11

UserIO_B0

Gnd

F11

C12

UserIO_B0_Rtn

Gnd

F12

C13

Gnd

Gnd

F13

C14

Gnd

Gnd

F14

C15

Gnd

Gnd

F15

C16

Gnd

Gnd

F16

C17

Gnd

Gnd

F17

C18

Gnd

Gnd

F18

C19

Gnd

Gnd

F19


CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

CPCI-6U Expansion Board, Backplane Connectors

CPCI-6U Expansion Board, CPCI Backplane Connector J5:
Axes 8 - 11

J5 backplane connector (CPCI expansion board).

Pin

Signal

Signal

Pin

A1

Analog_IN_0+

Analog_IN_3+

D1

A2

Analog_IN_1+

Analog_IN_2+

D2

A3

Enc8_A+

Xcvr11C+

D3

A4

Enc8_B+

Xcvr11B+

D4

A5

Enc8_I+

Xcvr11A+

D5

A6

Cmd_Dac_OUT_8+

Amp_En11_Collector

D6

A7

Aux_Dac_OUT_8+

Amp_Flt11_IN

D7

A8

Amp_Flt8_IN

Cmd_Dac_OUT_11+

D8

A9

Amp_En8_Collector

Aux_Dac_OUT_11+

D9

A10

Xcvr8A+

Enc11_I+

D10

A11

Xcvr8B+

Enc11_B+

D11

A12

Xcvr8C+

Enc11_A+

D12

A13

Enc9_A+

Xcvr10C+

D13

A14

Enc9_B+

Xcvr10B+

D14

A15

Enc9_I+

Xcvr10A+

D15

A16

Cmd_Dac_OUT_9+

Amp_En10_Collector

D16

A17

Aux_Dac_OUT_9+

Amp_Flt10_IN

D17

A18

Amp_Flt9_IN

Cmd_Dac_OUT_10+

D18

A19

Amp_En9_Collector

Aux_Dac_OUT_10+

D19

A20

Xcvr9A+

Enc10_I+

D20

A21

Xcvr9B+

Enc10_B+

D21

A22

Xcvr9C+

Enc10_A+

D22

B1

Analog_IN_0-

Analog_IN_3-

E1

B2

Analog_IN_1-

Analog_IN_2-

E2

B3

Enc8_A-

Xcvr11C-

E3

B4

Enc8_B-

Xcvr11B-

E4

B5

Enc8_I-

Xcvr11A-

E5

B6

Cmd_Dac_OUT_8-

Amp_En11_Emitter

E6

B7

Aux_Dac_OUT_8-

Amp_Flt11_Rtn

E7

B8

Amp_Flt8_Rtn

Cmd_Dac_OUT_11-

E8

B9

Amp_En8_Emitter

Aux_Dac_OUT_11-

E9

B10

Xcvr8A-

Enc11_I-

E10

B11

Xcvr8B-

Enc11_B-

E11

B12

Xcvr8C-

Enc11_A-

E12

B13

Enc9_A-

Xcvr10C-

E13

B14

Enc9_B-

Xcvr10B-

E14

B15

Enc9_I-

Xcvr10A-

E15

B16

Cmd_Dac_OUT_9-

Amp_En10_Emitter

E16

B17

Aux_Dac_OUT_9-

Amp_Flt10_Rtn

E17

B18

Amp_Flt9_Rtn

Cmd_Dac_OUT_10-

E18

B19

Amp_En9_Emitter

Aux_Dac_OUT_10-

E19

B20

Xcvr9A-

Enc10_I-

E20

B21

Xcvr9B-

Enc10_B-

E21

B22

Xcvr9C-

Enc10_A-

E22

C1

AGnd

Gnd

F1

C2

Gnd

Gnd

F2

C3

Home8_IN

Gnd

F3

C4

Pos_Lim8_IN

Gnd

F4

C5

Neg_Lim8_IN

Gnd

F5

C6

HomeLim8_Rtn

Gnd

F6

C7

HomeLim11_Rtn

Gnd

F7

C8

Neg_Lim11_IN

Gnd

F8

C9

Pos_Lim11_IN

Gnd

F9

C10

Home11_IN

Gnd

F10

C11

Not Connected

Gnd

F11

C12

5V_OUT

Gnd

F12

C13

Home9_IN

Gnd

F13

C14

Pos_Lim9_IN

Gnd

F14

C15

Neg_Lim9_IN

Gnd

F15

C16

HomeLim9_Rtn

Gnd

F16

C17

HomeLim10_Rtn

Gnd

F17

C18

Neg_Lim10_IN

Gnd

F18

C19

Pos_Lim10_IN

Gnd

F19

C20

Home10_IN

Gnd

F20

C21

Gnd

Gnd

F21

C22

5V_OUT

Gnd

F22

CPCI-6U Expansion Board, Rear Panel Connector J4:
Axes 12 - 15

J4 backplane connector (CPCI expansion board).

Pin

Signal

Signal

Pin

A1

Enc12_A+

Xcvr15C+

D1

A2

Enc12_B+

Xcvr15B+

D2

A3

Enc12_I+

Xcvr15A+

D3

A4

Cmd_Dac_OUT_12+

Amp_En15_Collector

D4

A5

Aux_Dac_OUT_12+

Amp_Flt15_IN

D5

A6

Amp_Flt12_IN

Aux_Dac_OUT_15+

D6

A7

Amp_En12_Collector

Cmd_Dac_OUT_15+

D7

A8

Xcvr12A+

Enc15_I+

D8

A9

Xcvr12B+

Enc15_B+

D9

A10

Xcvr12C+

Enc15_A+

D10

A11

Enc13_A+

Xcvr14C+

D11

A12

Not Connected

Not Connected

D12

A13

D13

A14

D14

A15

Enc13_B+

Xcvr14B+

D15

A16

Enc13_I+

Xcvr14A+

D16

A17

Cmd_Dac_OUT_13+

Amp_En14_Collector

D17

A18

Aux_Dac_OUT_13+

Amp_Flt14_IN

D18

A19

Amp_Flt13_IN

Aux_Dac_OUT_14+

D19

A20

Amp_En13_Collector

Cmd_Dac_OUT_14+

D20

A21

Xcvr13A+

Enc14_I+

D21

A22

Xcvr13B+

Enc14_B+

D22

A23

Xcvr13C+

Enc14_A+

D23

A24

Analog_IN_4+

Analog_IN_7+

D24

A25

Analog_IN_5+

Analog_IN_6+

D25

B1

Enc12_A-

Xcvr15C-

E1

B2

Enc12_B-

Xcvr15B-

E2

B3

Enc12_I-

Xcvr15A-

E3

B4

Cmd_Dac_OUT_12-

Amp_En15_Emitter

E4

B5

Aux_Dac_OUT_12-

Amp_Flt15_Rtn

E5

B6

Amp_Flt12_Rtn

Aux_Dac_OUT_15-

E6

B7

Amp_En12_Emitter

Cmd_Dac_OUT_15-

E7

B8

Xcvr12A-

Enc15_I-

E8

B9

Xcvr12B-

Enc15_B-

E9

B10

Xcvr12C-

Enc15_A-

E10

B11

Enc13_A-

Xcvr14C-

E11

B12

Not Connected

Not Connected

E12

B13

E13

B14

E14

B15

Enc13_B-

Xcvr14B-

E15

B16

Enc13_I-

Xcvr14A-

E16

B17

Cmd_Dac_OUT_5-

Amp_En14_Emitter

E17

B18

Aux_Dac_OUT_5-

Amp_Flt14_Rtn

E18

B19

Amp_Flt13_Rtn

Aux_Dac_OUT_14-

E19

B20

Amp_En13_Emitter

Cmd_Dac_OUT_14-

E20

B21

Xcvr13A-

Enc14_I-

E21

B22

Xcvr13B-

Enc14_B-

E22

B23

Xcvr13C-

Enc14_A-

E23

B24

Analog_IN_4-

Analog_IN_7-

E24

B25

Analog_IN_5-

Analog_IN_6-

E25

C1

5V_OUT

Gnd

F1

C2

Gnd

Gnd

F2

C3

Home12_IN

Gnd

F3

C4

Pos_Lim12_IN

Gnd

F4

C5

Neg_Lim12_IN

Gnd

F5

C6

HomeLim12_Rtn

Gnd

F6

C7

HomeLim15_Rtn

Gnd

F7

C8

Neg_Lim15_IN

Gnd

F8

C9

Pos_Lim15_IN

Gnd

F9

C10

Home15_IN

Gnd

F10

C11

5V_OUT

Gnd

F11

C12

Not Connected

Gnd

F12

C13

Gnd

F13

C14

Gnd

F14

C15

Gnd

F15

C16

Home13_IN

Gnd

F16

C17

Pos_Lim13_IN

Gnd

F17

C18

Neg_Lim13_IN

Gnd

F18

C19

HomeLim13_Rtn

Gnd

F19

C20

HomeLim14_Rtn

Gnd

F20

C21

Neg_Lim14_IN

Gnd

F21

C22

Pos_Lim14_IN

Gnd

F22

C23

Home14_IN

Gnd

F23

C24

Gnd

Gnd

F24

C25

AGnd

Gnd

F25

CPCI-6U Expansion Board, Rear Panel Connector J3: User I/O

J3 backplane connector (CPCI expansion board).

Pin

Signal

Signal

Pin

A1

D1

A2

D2

A3

D3

A4

D4

A5

D5

A6

Not Connected

Not Connected

D6

A7

D7

A8

D8

A9

D9

A10

D10

A11

D11

A12

D12

A13

UserIO_C1

UserIO_C2_Rtn

D13

A14

Not Used

UserIO_D2

D14

A15

UserIO_C3

UserIO_D4

D15

A16

UserIO_C0

UserIO_D3

D16

A17

EncC_I+

EncD_I+

D17

A18

EncC_B+

EncD_B+

D18

A19

EncC_A+

EncD_A+

D19

B1

E1

B2

E2

B3

E3

B4

E4

B5

E5

B6

Not Connected

Not Connected

E6

B7

E7

B8

E8

B9

E9

B10

E10

B11

E11

B12

E12

B13

UserIO_C1_Rtn

UserIO_C2

E13

B14

Not Used

UserIO_D2_Rtn

E14

B15

UserIO_C3_Rtn

UserIO_D4_Rtn

E15

B16

UserIO_A0_Rtn

UserIO_D3_Rtn

E16

B17

EncC_I-

EncD_I-

E17

B18

EncC_B-

EncD_B-

E18

B19

EncC_A-

EncD_A-

E19

C1

Gnd

Gnd

F1

C2

Not Connected

Gnd

F2

C3

Gnd

Gnd

F3

C4

Not Connected

Gnd

F4

C5

Gnd

Gnd

F5

C6

Not Connected

Gnd

F6

C7

Gnd

F7

C8

Gnd

F8

C9

Gnd

F9

C10

Gnd

F10

C11

UserIO_D14

Gnd

F11

C12

UserIO_D1_Rtn

Gnd

F12

C13

Gnd

Gnd

F13

C14

Gnd

Gnd

F14

C15

Gnd

Gnd

F15

C16

Gnd

Gnd

F16

C17

Gnd

Gnd

F17

C18

Gnd

Gnd

F18

C19

Gnd

Gnd

F19


CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

CPCI-3U

The XMP-CPCI-3U boards have two hardware stuff options for bringing out Motor I/O: VHDCI connectors on the front panel or Backplane connectors on the rear panel. The I/O for these connectors is decribed below.

XMP-CPCI-3U, VHDCI Connectors, Front Panel J0-3: Axes 0-3
Axis 0-1, VHDCI Connector (CPCI)

Connector for axes 0 and 1.

Pin

Signal

Signal

Pin

1

No Connect

No Connect

35

2

No Connect

No Connect

36

3

Gnd

Gnd

37

4

Enc0_A+

Enc0_A-

38

5

Enc0_B+

Enc0_B-

39

6

Enc0_I+

Enc0_I-

40

7

Home0_IN

5V_OUT

41

8

Pos_Lim0_IN

Gnd

42

9

Neg_Lim0_IN

HomeLim0_Rtn

43

10

Cmd_Dac_OUT_0+

Cmd_Dac_OUT_0-

44

11

No Connect

Gnd

45

12

Amp_Flt0_IN

Amp_Flt0_Rtn

46

13

Amp_En0_Collector

Amp_En0_Emitter

47

14

UserIO_A0

UserIO_A0_Rtn

48

15

Xcvr0A+

Xcvr0A-

49

16

Xcvr0B+

Xcvr0B-

50

17

Xcvr0C+

Xcvr0C-

51

18

Enc1_A+

Enc1_A-

52

19

Enc1_B+

Enc1_B-

53

20

Enc1_I+

Enc1_I-

54

21

Home1_IN

5V_OUT

55

22

Pos_Lim1_IN

Gnd

56

23

Neg_Lim1_IN

HomeLim1_Rtn

57

24

Cmd_Dac_OUT_1+

Cmd_Dac_OUT_1-

58

25

No Connect

Gnd

59

26

Amp_Flt1_IN

Amp_Flt1_Rtn

60

27

Amp_En1_Collector

Amp_En1_Emitter

61

28

Gnd

Gnd

62

29

Xcvr1A+

Xcvr1A-

63

30

Xcvr1B+

Xcvr1B-

64

31

Xcvr1C+

Xcvr1C-

65

32

UserIO_A1

UserIO_A1_Rtn

66

33

RESET_IN

UserIO_A2

67

34

ESTOP_IN

UserIO_A2_Rtn

68
Axis 2-3 VHDCI Connector (CPCI)

Connector for axes 2 and 3.

Pin

Signal

Signal

Pin

1

EncA_A+

EncA_A-

35

2

EncA_B+

EncA_B-

36

3

EncA_I+

EncA_I-

37

4

Enc2_A+

Enc2_A-

38

5

Enc2_B+

Enc2_B-

39

6

Enc2_I+

Enc2_I-

40

7

Home2_IN

5V_OUT

41

8

Pos_Lim2_IN

Gnd

42

9

Neg_Lim2_IN

HomeLim2_Rtn

43

10

Cmd_Dac_OUT_2+

Cmd_Dac_OUT_2-

44

11

No Connect

Gnd

45

12

Amp_Flt2_IN

Amp_Flt2_Rtn

46

13

Amp_En2_Collector

Amp_En2_Emitter

47

14

UserIO_A3

UserIO_A3_Rtn

48

15

Xcvr2A+

Xcvr2A-

49

16

Xcvr2B+

Xcvr2B-

50

17

Xcvr2C+

Xcvr2C-

51

18

Enc3_A+

Enc3_A-

52

19

Enc3_B+

Enc3_B-

53

20

Enc3_I+

Enc3_I-

54

21

Home3_IN

5V_OUT

55

22

Pos_Lim3_IN

Gnd

56

23

Neg_Lim3_IN

HomeLim3_Rtn

57

24

Cmd_Dac_OUT_3+

Cmd_Dac_OUT_3-

58

25

No Connect

Gnd

59

26

Amp_Flt3_IN

Amp_Flt3_Rtn

60

27

Amp_En3_Collector

Amp_En3_Emitter

61

28

Gnd

Gnd

62

29

Xcvr3A+

Xcvr3A-

63

30

Xcvr3B+

Xcvr3B-

64

31

Xcvr3C+

Xcvr3C-

65

32

Gnd

Gnd

66

33

No Connect

No Connect

67

34

No Connect

No Connect

68

XMP-CPCI-3U, Backplane Connectors, Rear Panel J2: Motor I/O

On CPCI-3U controllers using backplane I/O, Motor I/O is controlled through connector J2. Connector J1 is reserved for computer data bussing. For more information about computer data bussing, see Chapter 2.

CPCI-3U boards do not use expansion boards.

Backplane connector pins are referred to by numbered rows and lettered columns as shown below.

Axis 0-1, VHDCI Connector (CPCI)

NOTE: the CPCI XMP does not use the 64 bit extension.

CPCI backplane connector.

Pin

A

B

C

D

E

F

22

Reserved

Reserved

Reserved

Reserved

Reserved

GND

21

DAC_0+

DAC_1+

XCVR0A+

DAC_2+

DAC_3+

GND

20

DAC_0_RTN

DAC_1_RTN

XCVR0A-

DAC_2_RTN

DAC_3_RTN

GND

19

ENC0_A+

ENC0_A-

XCVR0B+

ENC2_A+

ENC2_A-

GND

18

ENC0_B+

ENC0_B-

XCVR0B-

ENC2_B+

ENC2_B-

GND

17

ENC0_I+

ENC0_I-

XCVR1A+

ENC2_I+

ENC2_I-

GND

16

ENC1_A+

ENC1_A-

XCVR1A-

ENC3_A+

ENC3_A-

GND

15

ENC1_B+

ENC1_B-

XCVR1B+

ENC3_B+

ENC3_B-

GND

14

ENC1_I+

ENC1_I-

XCVR1B-

ENC3_I+

ENC3_I-

GND

13

P2_A13

P2_B13

XCVR2A+

P2_D13

P2_E13

GND

12

P2_A12

P2_B12

XCVR2A-

P2_D12

P2_E12

GND

11

P2_A11

P2_B11

XCVR2B+

P2_D11

P2_E11

GND

10

P2_A10

P2_B10

XCVR2B-

DIR3+

DIR3-

GND

9

HOME_0_IN

HOMELIM_0_RTN

XCVR3A+

HOME_2_IN

HOMELIM_2_RTN

GND

8

HOME_1_IN

HOMELIM_1_RTN

XCVR3A-

HOME_3_IN

HOMELIM_3_RTN

GND

7

AMP_FLT_0_IN

AMP_FLT_0_RTN

XCVR3B+

AMP_FLT_2_IN

AMP_FLT_2_RTN

GND

6

P2_A6

P2_B6

XCVR3B-

P2_D6

P2_E6

GND

5

USERIO_A0

USERIO_A0_RTN

XCVR0C+

USERIO_A2

USERIO_A2_RTN

GND

4

USERIO_A1

USERIO_A1_RTN

XCVR0C-

USERIO_A3

USERIO_A3_RTN

GND

3

AMP_EN_0_COLL

AMP_EN_0_EMIT

P2_C3

AMP_EN_2_COLL

AMP_EN_2_EMIT

GND

2

P2_A2

P2_B2

P2_C2

P2_D2

P2_E2

GND

1

Reserved

Reserved

Reserved

Reserved

Reserved

GND


SERCOS-PMC

CONTENTS:
Introduction
PCI
CPCI-6U
CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

SERCOS-PMC

XMP-SERCOS-PMC controllers use SERCOS I/O. For more information regarding SERCOS, please see Chapter 5.


Transceiver (XCVR) and User I/O Details

CONTENTS:
Introduction
PCI
CPCI-6U
CPCI-6U Expansion Board, Backplane Connectors
CPCI-3U
SERCOS_PMC
Transceiver (XCVR) and I/O Details
CHAPTER 4
XMP-analog I/O

Transceiver (XCVR) and User I/O Details

This section lists the signal names (at the connector pins) and the Motion Block FPGA functions associated with each.

XCVR Functions

The XCVR signals are used for many different functions. The XMP-PCI and XMP-CPCI each offer three XCVRs (A,B,C) per motor, while the XMP-CPCI-3U offers six XCVRs (A,B,C,D,E,F) per motor. The various XMP boards and XCVR combinations are listed in (See XCVRs for various XMP products below).

XCVRs for various XMP products.

Product

Boards

Motion
Blocks

Motors

XCVRs

per Motor

XCVRs per Block

XCVRs Total

XMP-PCI

2

4

16

3 (A-C)

12

48

XMP-CPCI

2

4

16

3 (A-C)

12

48

XMP-CPCI-3U
(non-standard)

1

1

4

6 (A-F)1

23

23

XMP-CPCI-3U
(standard)

1

1

4

3 (A-C)

12

12

1. On non-standard XMP-CPCI-3U controller, Axis 2 XCVR D is not connected to rear I/O, giving a total of 23 XCVRs.
Standard -3U controller has 12 XCVRs.

These multi-purpose XCVR signals may be configured for several different input or output functions. The available XCVR functions for one motor are detailed below; the XCVRs for all other motors are the same.

Note

an option to invert any output function is also available.

XCVR A functions.

MOTOR 0 XCVR A Functions

(connector signal pair XCVR0A+ and XCVR0A-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

STEP

OUTPUT

STEP signal for MOTOR 0 stepper

DIR

OUTPUT

DIRECTION signal for MOTOR 0 stepper

CW

OUTPUT

CLOCKWISE signal for MOTOR 0 stepper

CCW

OUTPUT

COUNTER-CLOCKWISE signal for MOTOR 0 stepper

QUADA

OUTPUT

QUADRATURE A signal for MOTOR 0 stepper

QUADB

OUTPUT

QUADRATURE B signal for MOTOR 0 stepper

INPUT

INPUT

General purpose input -or-

To CAPTURE EVENT 0 input lookup table

XCVR B functions.

MOTOR 0 XCVR B Functions

(connector signal pair XCVR0B+ and XCVR0B-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

STEP

OUTPUT

STEP signal for MOTOR 0 stepper

DIR

OUTPUT

DIRECTION signal for MOTOR 0 stepper

CW

OUTPUT

CLOCKWISE signal for MOTOR 0 stepper

CCW

OUTPUT

COUNTER-CLOCKWISE signal for MOTOR 0 stepper

QUADA

OUTPUT

QUADRATURE A signal for MOTOR 0 stepper

QUADB

OUTPUT

QUADRATURE B signal for MOTOR 0 stepper

INPUT

INPUT

General purpose input -or-

To CAPTURE EVENT 0 input lookup table

XCVR C functions.

MOTOR 0 XCVR C Functions

(connector signal pair XCVR0C+ and XCVR0C-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

COMPARE

OUTPUT

Compare output signal for MOTOR 0

INPUT

INPUT

General purpose input -or-

To CAPTURE EVENT 0 input lookup table

Note

XCVR D, E and F are available only on the XMP-CPCI-3U board. They are not available on the XMP-PCI or XMP-CPCI.

XCVR D functions.

MOTOR 0 XCVR D Functions

(connector signal pair XCVR0D+ and XCVR0D-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

STEP

OUTPUT

STEP signal for MOTOR 0 stepper

DIR

OUTPUT

DIRECTION signal for MOTOR 0 stepper

CW

OUTPUT

CLOCKWISE signal for MOTOR 0 stepper

CCW

OUTPUT

COUNTER-CLOCKWISE signal for MOTOR 0 stepper

QUADA

OUTPUT

QUADRATURE A signal for MOTOR 0 stepper

QUADB

OUTPUT

QUADRATURE B signal for MOTOR 0 stepper

INPUT

INPUT

General purpose input

XCVR E functions.

MOTOR 0 XCVR E Functions

(connector signal pair XCVR0E+ and XCVR0E-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

STEP

OUTPUT

STEP signal for MOTOR 0 stepper

DIR

OUTPUT

DIRECTION signal for MOTOR 0 stepper

CW

OUTPUT

CLOCKWISE signal for MOTOR 0 stepper

CCW

OUTPUT

COUNTER-CLOCKWISE signal for MOTOR 0 stepper

QUADA

OUTPUT

QUADRATURE A signal for MOTOR 0 stepper

QUADB

OUTPUT

QUADRATURE B signal for MOTOR 0 stepper

XCVR F functions.

MOTOR 0 XCVR F Functions

(connector signal pair XCVR0F+ and XCVR0F-)

Function

Signal Direction

Comments

OUTPUT

OUTPUT

General purpose output

STEP

OUTPUT

STEP signal for MOTOR 0 stepper

DIR

OUTPUT

DIRECTION signal for MOTOR 0 stepper

CW

OUTPUT

CLOCKWISE signal for MOTOR 0 stepper

CCW

OUTPUT

COUNTER-CLOCKWISE signal for MOTOR 0 stepper

QUADA

OUTPUT

QUADRATURE A signal for MOTOR 0 stepper

QUADB

OUTPUT

QUADRATURE B signal for MOTOR 0 stepper

User I/O

There is one USER I/O signal associated with each motor (4 per motion block, 8 for an 8-axis board, 16 for a 16-axis system). These general purpose, opto-isolated signals may be used as either an input or an output. Selecting between input or output is done via the electrical polarity of the external circuit: the polarity of an input circuit disables the output (the output transistor cannot turn on with Vcollector < Vemitter), while the reverse polarity enables the output and disables the input (due to a blocking diode). The circuit design guarantees all components remain within operating limits through the full range of possible values (i.e., with Vin = 24 V, both input and output parts are within spec).

User I/O.

Board

Motion
Block

Available functions
(choose one)

Signal Names
at Connector

Main Board

Motion
Block 0

MOTOR0 USER INPUT

OR
MOTOR0 USER OUTPUT

USERIO_A0

AND
USERIO_AO_RTN

MOTOR1 USER INPUT

OR
MOTOR1 USER OUTPUT

USERIO_A1
AND
USERIO_A1_RTN

MOTOR2 USER INPUT
OR
MOTOR2 USER OUTPUT

USERIO_A2
AND
USERIO_A2_RTN

MOTOR3 USER INPUT
OR
MOTOR3 USER OUTPUT

USERIO_A3
AND
USERIO_A3_RTN

Motion
Block 2

MOTOR4 USER INPUT
OR
MOTOR4 USER OUTPUT

USERIO_B0
AND
USERIO_B0_RTN

MOTOR5 USER INPUT
OR
MOTOR5 USER OUTPUT

USERIO_B1
AND
USERIO_B1_RTN

MOTOR6 USER INPUT
OR
MOTOR6 USER OUTPUT

USERIO_B2
AND
USERIO_B2_RTN

MOTOR7 USER INPUT
OR
MOTOR7 USER OUTPUT

USERIO_B3
AND
USERIO_B3_RTN

Expansion

Board

Motion
Block 1

MOTOR8 USER INPUT
OR
MOTOR8 USER OUTPUT

USERIO_C0
AND
USERIO_C0_RTN

MOTOR9 USER INPUT
OR
MOTOR9 USER OUTPUT

USERIO_C1
AND
USERIO_C1_RTN

MOTOR10 USER INPUT
OR
MOTOR10 USER OUTPUT

USERIO_C2
AND
USERIO_C2_RTN

MOTOR11 USER INPUT
OR
MOTOR11 USER OUTPUT

USERIO_C3
AND
USERIO_C3_RTN

Motion
Block 3

MOTOR12 USER INPUT
OR
MOTOR12 USER OUTPUT

USERIO_D0
AND
USERIO_D0_RTN

MOTOR13 USER INPUT
OR
MOTOR13 USER OUTPUT

USERIO_D1
AND
USERIO_D1_RTN

MOTOR14 USER INPUT
OR
MOTOR14 USER OUTPUT

USERIO_D2
AND
USERIO_D2_RTN

MOTOR15 USER INPUT
OR
MOTOR15 USER OUTPUT

USERIO_D3
AND
USERIO_D3_RTN


Introduction
SERCOS Connection Hardware
XMP-SERCOS Connector Ports
Assistance with SERCOS Networks
CHAPTER 5
XMP Controller MotionDrive I/O: Sercos

Introduction

SERCOS (SErial Real-time COmmunication System) is an optical networking standard for motion controllers and drives. It confers a number of advantages over electrically based, analog forms of control. Most notably, its fiber optic mode of communication reduces noise problems seen in electrical systems, while offering very high signal throughput. SERCOS devices are serially connected (i.e., "daisy-chained") in a ring configuration via "nodes," each node having its own dedicated receiving and transmitting ports. Data is sent in "telegrams," which contain either control or status information. These are sent by the controller (master) then received, processed, and relayed by each node (slave) in the ring.

Normally configured XMP-SERCOS systems connect up to eight (8) nodes. An additional four nodes may be connected for a maximum total of twelve (12) nodes. This lends tremendous flexibility to SERCOS-based motion control systems. In the network example above, a single ring is featured with three separate drives, each having its own dedicated node. Almost any combination of nodes and drives is possible; however, the final configuration and number of drives within the system is limited by the required cycle time of each node and the controller. To determine the optimal SERCOS configuration for your motion control application, please contact Motion Engineering.

Besides parsing control data and sending feedback, each drive's on-board processor offers additional capabilities. Depending on the manufacturer, SERCOS drives have the ability to close a position, velocity, and/or torque loop, execute internal homing procedures, as well as latch position based on digital inputs.

Despite the fact that the XMP-SERCOS controller has a different physical interface than the standard XMP controller, the same MPI is used for both controllers. The complexity of the XMP-SERCOS controller's interface has been hidden by the MPI and by the firmware running on the XMP. The same development tools can be used for both controllers. The XMP-SERCOS controller requires an initialization procedure before telegrams can be sent to amplifiers. Once the initialization procedure has successfully executed, XMP-SERCOS controllers act the same as standard, analog XMP controllers.

Design Limitations

Despite its many advantages, SERCOS does not confer "something for nothing." XMP-SERCOS controllers share some of the same limitations as analog controllers:

  • XMP-SERCOS controllers cannot obtain more from a drive than it's designed to deliver. When selecting a SERCOS drive, the designer must scale their selection to the hardware-software requirements of the system. Different drive systems feature different capabilities and processing speeds. SERCOS errors arise when a drive is commanded to do something it cannot do.
  • Although most SERCOS drives share a number of standardized user identification numbers (IDNs), most drive manufacturers assign their own unique IDNs. If you change drives, IDNs can be expected to change also.
  • The selection of cable length and material (acrylic vs. glass), transceiver wavelength and power, connector types, etc. all bear upon the success of a SERCOS network. Hardware flaws at any point in the SERCOS ring will affect the performance of the entire system.
Controller-Drive Compatibility

Depending upon your choice of motion drives to be used with the XMP-SERCOS controller, you should consider some or all of the below parameters:

  • Optical power
  • Data rate
  • Cycle time
  • IDNs
Optical wavelength and power

Motion Engineering's XMP-SERCOS controller uses Agilent Technologies HFBR-1505A/2505A transceivers for transmitting and receiving data.1
Transceivers used on industry SERCOS drives may differ, depending upon the manufacturer.

Transmitter

The XMP-SERCOS controller transmitter , (HFBR-1505) incorporates an LED, transmitting at a nominal wavelength of 650 nm (± 10 nm). Optical peak output power (Pt) is software adjustable from -18.0 to -5.5 dBm. NOTE: power is affected by temperature: higher transmitter temperatures yield slightly decreased power.

Receiver

The Agilent HFBR-2505A receiver's peak input power varies from -20 dBm (Level Logic HIGH) to -42 dBm (Level Logic LOW). Data corruption may result if the receiver is overdriven (inputted optical power too high), or underdriven (inputted optical power too low). These conditions are discussed in the next section.

Data Rate, Cycle Times and Configuring SERCOS

The number of devices capable of being operated by one XMP-SERCOS controller will depend upon the number and cycle times of drives and the number of networked nodes. It may prove advantageous to consolidate two or more drives into a lesser or greater number of nodes, depending upon the task(s) to be accomplished. To receive guidance on optimizing your SERCOS network, please contact Motion Engineering.

1. Agilent Technologies is a subsidiary of Hewlett-Packard. Data sheets for HFBR-1505A/2505A transceivers are available from Agilent via their web site: www.agilent.com.


SERCOS Connection Hardware
XMP-SERCOS Connector Ports
Assistance with SERCOS Networks
CHAPTER 5
XMP Controller MotionDrive I/O: Sercos
IDNs
SIDNs and PIDNs

IDNs, or Identification Numbers, are numbers identifying data that can be transmitted between SERCOS nodes and hosts. Design of a successful SERCOS network requires a thorough knowledge of all IDNs used.

There are two types of IDNs. SIDNs (standard IDNs) are defined by the SERCOS specification. These IDNs represent data that is commonly used in drive implementations. It should be noted that it is up to the manufacturer to decide which SIDNs it will support. PIDNs (product IDNs) are defined by the manufacturer. These IDNs represent data used in the drive for features not discussed in the SERCOS specification. PIDNs vary widely between drives and manufacturers.

Drive Initialization

During initialization of a SERCOS network, many drives require the setting of certain IDNs. Please consult the drive manufacturer's documentation concerning required IDN settings.

SERCOS Connection Hardware

SERCOS Cabling

Variations in cable length and material have a profound influence upon power attenuation within networks:

  • Fiber optic cable length-- the longer the cable, the more optical power it absorbs.
  • Fiber optic cable material (glass vs. acrylic)-- different materials absorb different quantities of light, and react differently to changes in temperature, bend radius, etc.
  • Temperature-- affects transceiver and cable characteristics.
  • Cable movement / bend radius-- as fiber optic cables are moved between motion components, their bend radii will vary. This, in turn, can attenuate optical signals. Generally, the smaller the bend radius, the higher the power attenuation. Cables attain their maximum optical efficiency when they are straight.

Specifications for SERCOS fiber-optic cable are found in Section 5.3.3 of the SERCOS interface standard (IEC 64191); however, network designers should consult their vendors for exact cable characteristics. Depending upon the cable material used (glass vs acrylic), length and bend radius, performance will vary. Section 5.3.5 of IEC 61491 specifies system data of the optical transmission path. Conforming cables must meet this specification.

SERCOS Connectors

XMP-SERCOS controllers utilize screw-on connectors having 1/4 - 36 UNS 2A threads. Typically, transceivers use molded plastic threads, while many cable connectors are steel; therefore, use caution to prevent cross-threading and stripping.

Loose connectors do not efficiently couple the fiber-optic cable's light energy to a transceiver and can cause data corruption. Under no circumstances should connectors be left loose. (This includes situations where a transceiver's power output is too high and can be reduced by loosening the connector; this is NOT a reliable way to adjust power output!)

Setting Transmitter Power

An integral part of building a SERCOS ring is establishing optimal transmitting power for each device in the ring. Starting at the XMP controller, an optical control signal is transmitted at a specified power level. The first device in the ring receives this signal, copies and processes it, then generates a new transmission. The next device in the ring receives this secondary transmission, processes it, and so on. This relay continues through every device until the controller becomes the last device in the ring. The controller processes the telegrams it has received, calculates new control commands, then transmits new telegrams during the next data cycle. The process repeats until halted by the controller, or an interruption in the ring causes a fault.

When building SERCOS networks, it is crucial to match the power of each device's transmitter with the downstream device's receiver. If power levels are set too low or too high, data corruption can quickly result--a common cause of errors and problems in SERCOS networks.


XMP-SERCOS Connector Ports
Assistance with SERCOS Networks
CHAPTER 5
XMP Controller MotionDrive I/O: Sercos

XMP-SERCOS Connector Ports

Connector ports on XMP-SERCOS controllers are labeled "Tx" (transmitter) and "Rx" (receiver). The diagram above shows connector locations for both the XMP-SERCOS-PMC and XMP-CPCI-SERCOS controllers. The XMP-SERCOS-PCI-S1 and -S2 controllers are not shown.

SERCOS cables are connected by inserting them gently into their ports and rotating the metal ferrule until snug. The XMP controller and all SERCOS devices should be configured in a ring (or "daisy chain") such that the "Tx" port of one device is plugged into the "Rx" of a neighboring device in the ring.

Internal SERCOS Controller Hardware and Signal Structure

Both PMC and CPCI XMP-SERCOS controllers are designed to be firmware- and software-compatible with the standard MPI/XMP libraries, while providing control to the SERCOS ASIC. All the motion blocks normally found in the XMP are available on these controllers. The XMP-SERCOS-PMC and XMP-SERCOS-CPCI controllers each contain SERCOS ASICs, opto couplers, and control logic sufficient to control 1 to 4 independent SERCOS rings. Each ring is capable of independently supporting 2, 4, 8, 10, or 16MHz data rates.

Bit Coding

SERCOS signals are conveyed optically as a series of discretely modulated light pulses from each device's transmitter to the adjoining device's receiver. Information is NRZI-coded (Non Return to Zero Inverted), with a retrievable clock signal. Information is encoded using a 0 where there is a transition, and a 1 where there is no transition. To ensure that clock pulses remain retrievable from the transmitted signal, zeros are forced (bit-stuffed) into the data stream every eight bits.

A full description of NRZI coding and SERCOS is included within Section 5.5 of the publication entitled "Electrical Equipment of Industrial Machines--Serial Data Link for Real-time Communication Between Controls and Drives" from the International Electrotechnical Commission.


Assistance with SERCOS Networks

CONTENTS:
Introduction
SERCOS Connection Hardware
XMP-SERCOS Connector Ports
Assistance with SERCOS Networks
CHAPTER 5
XMP Controller MotionDrive I/O: Sercos

For Assistance with SERCOS Networks...

Because of variation in motion control drives and designs, no two SERCOS networks are exactly the same. Motion Engineering's Applications Department has accrued a breadth of experience in the design and troubleshooting of SERCOS networks and is ready to assist you. When contacting MEI, please be prepared to provide the following information:

System

1) Number of drives in system.

2) Type(s) of cable (glass, plastic, etc....).

3) Cable lengths.

Controller

1) Model and hardware version.

2) Firmware version.

3) Software (MPI) version.

4) Sample code demonstrating problem (if any). Sample application can be an MEI application.

Drive

1) Drive manufacturer.

2) Drive model.

3) Drive firmware version.

4) Drive operation mode (position, velocity, torque, etc....).

5) Contact information for drive manufacturer.


Architectural Overview
Host Bus
Encoder Inputs
Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMPData Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Introduction

This chapter presents a general description of the XMP controller's architecture. It is intended to help users better understand the XMP's inner workings, and also explains how hardware functions with external components such as host computers, drives, and encoders. Many components discussed in this chapter are detailed in other sections of the manual. To learn more about a specific component, please refer to the index or perform a keyword search .

Architectural Overview

The XMP controller is a remarkably integrated device, designed to link a host computer with industry-standard motion drives. While many motion controllers heavily task the host computer's CPU to calculate motion paths and execute commands, the XMP performs much like a computer-within-a-computer to free the host of these tasks. Because the controller dedicates itself 100 percent to the task of motion control, the host computer is tasked only with communicating high-level commands; it remains free to oversee other tasks. Meanwhile, your machine's motion drive is ensured the safest, most rapid and precise motion control possible. The XMP controller achieves this feat through a fully integrated architecture, consolidating all essential control components and subsystems onto one board.

Computer Hosts-- XMP controllers can be hosted by both PCI and CompactPCI (CPCI) computers via a 32-bit direct memory interface. Remote hosting via an Ethernet (TCP/IP) connection is also available.

Digital Signal Processor (DSP)-- The hardware centerpiece of the XMP is the SHARC DSP (Super Harvard ARchitecture Computer Digital Signal Processor). By taking full advantage of the DSP's horsepower, efficiency is optimized, by splitting the motion tasks between the host and XMP.

Motor Control-- Each controller is capable of operating up to 16 axes (independently configurable to control a servo or stepper motor) at a sample rate of 5 KHz, or 8 axes at a sample rate of 10 kHz. Included with each axis is a high speed compare output, and a high speed capture or registration input. Each axis can also be configured to sinusoidally commutate servo motors via two analog outputs. Full tuning capability is offered with PID and advanced, post-PID filtering options for each axis, including gain-scheduling and dual-loop control. Stepper output rates can be as high as 2.5 MHz. This direct-digital pulse train can control an open or closed loop motor, enabling frequency-controlled servo operation. Axes can be configured for step-direction or clockwise-counterclockwise operation.

Motion Feedback-- Motion feedback can be standard quadrature from an incremental encoder (10 MHz max, 40 MHz count rate), ±10 volt analog differential signal, or analog encoder signal routed to a 4096x Scale Interpolation Module (SIM4).

Motion Programming Interface (MPI)-- The MPI (Motion Programming Interface) has two built-in software objects for easy real-time motion application control: the Event Manager and Program Sequencer. The Event Manager communicates to the XMP via the bus interface and interrupts. Multi-threaded applications can wake or put to sleep multiple threads based on user-defined events or standard MPI events, such as emergencies. The Event Manager facilitates efficient multi-threaded applications. The Program Sequencer allows onboard autonomous programs to execute instructions during each DSP sample period. Onboard XMP-handled programs require no host intervention for optimal host-processor efficiency and guaranteed time response.

Safety-- Dedicated, DSP-based motion control optimizes safety: the controller's on-board watchdog timers constantly monitor handshaking, and a dedicated, general purpose E-stop input is at the ready. Each axis also has configurable, optically-isolated software and hardware limits up to 24 volts.

Clock-- A phase-locked loop (PLL) clock generator provides the master clock to the DSP, PCI interface, state machines and FPGAs.

Analog Power Supply-- Clean analog power is generated on ±15V power rails from Vcc. Each 8-axis controller has its own analog power supply.

XMP Components

Three key components comprise the XMP family: main boards, expansion boards, and SIM4 modules. Every XMP controller starts with one main board. Other components are added as needs dictate.

XMP main board-- Every XMP controller consists of at least this component; in some cases (XMP-CPCI-3U and XMP-SERCOS-PMC) it is the only component. Each main board includes a SHARC DSP processor subsystem with up to two motion blocks each.

XMP expansion board (optional)-- Connects directly to one main board (XMP-PCI and XMP-CPCI-6U only) via a ribbon cable. Adds up to two more motion blocks, with 4- and 8-axis models available.

SIM4 scale interpolation module (optional)-- Plugs directly into main and/or expansion boards (XMP-PCI and XMP-CPCI-6U only) via mezzanine connectors. Up to two SIM4s may be added to each main or expansion board.

XMP boards and SIM4 modules.


Host Bus
Encoder Inputs
Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Host Bus

Host Bus Interface

Data bussing between XMP controllers and hosting computers is similar in all cases, regardless of whether the controller is configured for PCI, CPCI, or PMC busses, or the choice of operating systems. The host communicates with the XMP using direct memory reads/writes over a 32-bit bus. The full DSP internal memory (128k bytes), external SRAM, and FLASH memory are accessible to the host, in a 32-bit flat memory window of 8 Mbytes in the PCI (or CPCI) memory map. The host bus interface includes system registers for host control of Reset, Write and Interrupt enables, system configuration, control and status.


Encoder Inputs
Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Encoder Inputs

Each motion block provides up to five encoder interfaces (4 axes plus 1 auxiliary), with the following features:

  • 20 MHz maximum count rate (5 MHz quadrature cycle)
  • Digital noise filtering
  • Broken wire and illegal state detection

Having five (5) encoders allows an encoder to each axis, plus a fifth encoder for master-slave, master-cam or dual-loop operations. Each motion block has features for position capture and position compare. Digital noise filtering is enabled by default and limits the maximum count rate to 10 MHz (2.5 MHz quadrature cycle).

Position Capture

Each motion block maintains a set of ten 32-bit data capture registers (in hardware), used to store latched positions. The ten data capture registers are shared among the five encoder interfaces of each motion block. A specific capture register can be associated with any encoder (position) counter. Each capture register can be triggered by one of the five events (one from each of the five encoder interfaces). One event can trigger any number of captures, allowing probe capture of multiple axes.

Events/Data Capture Registers/Position Counters

The free-running, 32-bit position counter for any axis can be latched on the edge of an input. The latency for position capture is sub-microsecond, because the registers are implemented in hardware. The input source and polarity are configurable. The capture event can trigger on any of:

  • Twelve available RS-422 transceiver inputs per motion block
  • Dedicated Index_in (per axis)
  • Dedicated Home_in (per axis)

Additionally, the capture event trigger can be enabled or disabled with software.

Capture logic may be triggered from any one of the five Event look-up tables in a given motion block FPGA (one Event look-up table per axis, plus one spare table). Each Event look-up table has seven inputs. These signals are the three Xcvr signals for that axis plus Home, Pos_LIM, Neg_LIM and Index. The Event look-up table can be configured to use either polarity of any one input or combinations of inputs (for example, capture data if Home is low and Index is high).

Event processing for data capture.

Although the Capture 0 register is normally used to capture the encoder (position) count for Axis 0, you can also use Capture 0 to capture the encoder counts for the other axes in that motion block (Axis 1,2,3), individually or as a group. Note that Capture events cannot cross between motion blocks, although you can work around this by externally wiring the axis inputs among multiple motion blocks.

External wiring between motion blocks.
Position Compare

Each motion block has a hardware register file of sixteen 32-bit registers which are used to provide compare setpoints. The sixteen registers are shared among the four axes. Buffer modes can be set up as FIFO or circular, so that compare events can occur faster than the servo update rate. Compare latency is less than 1µsec.

The compare event can set a Position_Compare output on any of the twelve available RS-422 transceiver outputs. The compare event status is also available to the DSP. The trigger event is software-configurable and will occur when the value loaded in the position compare register is either:

  • greater than the actual position
  • equal to the actual position
  • less than the actual position

In addition, the equality condition can be either transparent or latched. Note that the latched condition can be cleared. The Position_Compare output polarity is programmable and the compare output can be disabled. The register can also be read back by the host.

Scale Interpolation Modules (SIM4)

For encoders with sinusoidal outputs, the scale interpolation module provides increased position resolution for up to four axes. These outputs produce one cycle of sine and cosine analog signals for each encoder's line pair. At every sample, the scale interpolation module reads the sine and cosine levels and determines the angular position within the line pair. The sine and cosine outputs are also routed to the standard quadrature inputs, providing coarse position information.

The quadrature inputs generate 4 counts for every line pair, and the 12-bit interpolated value generates 4096 counts for each line pair. The full interpolated position is obtained by combining the number of quadrant counts divided by 4, with the position between two encoder lines. Essentially, the 12-bit scale interpolation provides a resolution increase of 1024 over the quadrature counters. To maintain accurate phase information, the sine and cosine signals are captured with simultaneous-sampling A/D converters.

Position Compare

To implement the position compare feature, the SIM4 compares the current position to a position latched in the FPGA. The A/D converters convert continuously, with a 10µsec latency.

  • 10 compare registers are available per SIM4 (4 axes).
  • Can compare two positions per servo cycle on 4 axes,
    or can compare 10 positions per servo cycle on 1 axis.
  • Delay from compare event to compare = 10µsec.
Position Capture

To implement the position capture feature, the SIM4 latches the full interpolated position when the user-supplied latch signal is pulsed.

Note

Different axes can be latched independently of each other.
  • 10 capture registers are available per SIM4 (4 axes)
  • Can capture two times per servo cycle on 4 axes,
    or can capture 10 times per servo cycle on 1 axis
  • Delay from capture event to capture = 5 μsec

For detailed information about SIM4 modules, please see Application Note 206.


Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Digital-to-Analog Converter (DAC) Subsystem

The command link from the XMP controller to analog input servo drive is the DAC. (In contrast, stepper drives receive commands from the XMP controller via transceivers; DACs are not used for steppers.) The XMP controller can have up to two DACs per axis. DACs are separated into primary and auxiliary DACs. One channel is used for standard servo control (“primary”) and the other channel is an auxiliary, OR both channels are used for sinusoidal commutation.

Using the firmware's default settings, motors are mapped to DACs according to the table below. The firmware provides for a fully configured, 16-motor controller (consisting of a linked main and expansion board) by mapping all 16 motors to 32 DACs (16 primary, plus 16 auxiliary). If a controller consists only of one main board (8 motors), the expansion hardware to support the additional motor-DAC mappings (motors 8-15, DACs 8-15, and AuxDacs 8-15) does not exist, and the firmware ignores them.

Default firmware motor-DAC assignments.


Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Analog Inputs

Analog signals, from such external devices as optical sensors and LVDTs, can be fed to the XMP controller. They are wired through dedicated analog lines (e.g., ANALOG_IN_0+ and _0-), then converted to digital values by the XMP controller's analog-digital converter (ADC). The ADC used in XMP controllers is an Analog Devices 16-bit AD976A.

The figure below outlines the analog input subsystem for the XMP controller.

The XMP controller accepts analog inputs having a maximum dynamic range of +10V or -10V, and converts these to 16-bit digital values within the ADC. 17 kHz noise filtering at the inputs removes unwanted voltage spikes. Because the highest digital resolution is attained when analog inputs are scaled to 10V, it is advantageous to rescale lower voltage inputs via the integrated programmable gain amplifier (PGA). Gain factors are individually selectable at gain select = 1, 2, 4, and 8, for ±10V, ±5V, ±2.5V, and ±1.25V inputs, respectively.

The multiplexer provides fault protection as well as channel selection. With no power applied, the switches are OFF. Overvoltage clamps become activated at ±13.5V.

ADC Subsystem Specifications

Max. Input Voltage

± 10V

Input Ranges

± 1.25V; ± 2.5V; ± 10V; or, ± (%)V

Resolution

16 bits

Channels

8

Input Impedance

100k

Signal Bandwidth

DC - 17 kHz

Conversion Time

10µs

Conversion Rate

Once per servo cycle (8 channels)1

DC Offset

15mV (max.) on 10V range.

Gain Uncertainty

0.5% (max.) on 10V range.

Nonlinearity

6 LSB

1. Please note that ADC conversion rates vary slightly, depending upon where within the servo cycle an analog change occurs. If an analog input changes near the end of the cycle, the digital conversion may occur sooner after the change than if the change occurs at the very beginning of the servo cycle.
XMP Controller Systems and Subsystems
Main Board and Expansion Board

Each XMP controller contains one main control board, capable of operating up to eight (8) axes. The main board contains the SHARC DSP, which processes all data between the host computer and motion hardware. In addition, one optional expansion board may be connected to a main board to add up to eight (8) more axes. Unlike main boards, expansion boards do NOT have their own SHARC DSP; they rely on the main board's SHARC DSP to do all digital processing.

Motion Block

Each main and expansion board has two (2) "motion blocks." Each motion block, in turn, contains four (4) "motor blocks," each of which controls one motor (see "Motor Block" below). Because motion blocks contain multiple motor blocks and are linked to all other motion blocks on the controller, it is possible to freely map one object to another. This provides the XMP controller with unprecedented flexibility and speed in coordinated motion.

A motion block is not a single piece of hardware, but actually consists of one field programmable gate array (FPGA), plus other hardware components. It is useful to think in terms of motion blocks to best understand how the XMP controller works. The motion block serves as the interface between the SHARC processor subsystem and motion I/O signals, and handles the interface to output peripherals (DACs, XCVRs, and opto-I/O), as well as the interface to feedback peripherals. Each motion block subsystem has a high speed serial interface to the SHARC DSP subsystem.

Motor Block

Contained within each motion block are four (4) "motor blocks." Motor blocks represent the most basic unit of motion control within the XMP environment. Each motor block acts as a dedicated gateway between the host computer and motion control components such as motors and encoders.

List of Figures

The next three pages illustrate overall data flow and component architecture of a typical XMP controller, including:

  • See Overall architecture: main and expansion boards below.
  • See Motion block detail below.
  • See Motor block detail below.

A study of these figures will provide some insight into an XMP controller's component layout and data flow.

Overall architecture: main and expansion boards.
Motion block detail.
Motor block detail.

DAC Circuitry

The D/A converters are 16-bit and DC-specified for high performance.

DAC circuitry.

Four pairs of DACs (eight total) are associated with each motion block. The first DAC of the pair is the Servo Command Output DAC, the second is an Auxiliary DAC for optional two-phase sinusoidal commutation support. The serial stream is shifted out of the first DAC of each pair and into the second DAC. A common latch updates all DACs.

The outputs swing ±10V to provide the Command Output voltage. The reference signal for the Command Output is each individual DAC's analog ground. Each Command Output is capable of driving a load of 10k [image] and 220pF (typical brushless amp input over 6 feet of cable) with a slew rate of 4 V/microsec (20 Volt swing at 20 kHz). See Chapter 3 for specifications on command voltage outputs.

Note

The AD7849BR DAC used on the XMP should not need calibration. The bipolar zero error is specified at ±2 LSBs (0.6 mV) at 25° C. Between -40° C and +85° C, bipolar zero error is ±12 LSBs (3.6 mV). Calibration should not be required. The outputs are fault protected (switched to AGND) for power-on/power-off and emergency conditions.

SERCOS Subsystems

The SERCOS subsystem is an interface between the SHARC processor subsystem and a drive. A drive is generally referred to as a Node. A Node is a SERCOS slave representing a drive, I/O block, etc. A SERCOS subsystem can support up to eight nodes. An XMP-SERCOS controller can support up to four SERCOS subsystems.

The SERCOS subsystem consists of a SERCOS interface and a set of fiber optic transceivers. The fiber optic transceivers allow communication with the SERCOS Nodes via a serial data stream. The SERCOS subsystem supports data streams with rates of 2, 4, or 10 MBaud.

The SERCOS interface is responsible for synchronizing data transmission by transmitting a Master Synchronization Telegram (MST) at a defined interval (Tscyc). Tscyc can be programmed to be a power of 2 of the XMP sample rate.

Each SERCOS subsystem is mapped to a specific location in the SHARC memory space. This allows the SHARC processor to directly access registers and memory in the SERCOS subsystem. This, in turn, allows direct mapping of command and feedback data for each Node. The analog and SERCOS versions of the XMP use the same firmware.

For more information on SERCOS hardware, please refer to Chapter 5.


SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

SHARC DSP Processor Subsystem

The DSP processor subsystem includes the following subsystems:

  • SHARC DSP processor
  • DSP RAM
  • Flash memory
  • Host bus interface
  • Serial ports to motion blocks
  • Fault monitor
  • Clock generator
  • JTAG interface
SHARC DSP processor subsystem.
SHARC DSP Processor

The XMP's main DSP processor is a 32-bit Analog Devices 21061 Floating Point DSP (also known as the SHARC DSP) with a peak performance of 150 MFLOPs. The 21061 provides trajectory planning, coordination, interpolation and position/ velocity loop closure.

DSP RAM

External SRAM is available to the DSP for maintaining message buffers and storing data. The SRAM can be up to 2 Mbytes of zero-wait state RAM. The standard configuration is 64K x 32 bit words (256K bytes).

Flash Memory

An 8-Mbit FLASH memory stores the DSP boot code, FPGA configuration code and nonvolatile system information. The FLASH memory is rated for 100,000 write/erase cycles.

Serial Ports to Motion Blocks

The SHARC DSP communicates with the four peripheral motion blocks over two 40 Mbit/sec serial links. All DSP-to-motion block data transfers occur over these two links.

Each SHARC DSP serial port connects to two motion blocks. The motion blocks are the gateways for all of the controller's I/O to the external system.


Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Memory Organization

The XMP has three memory regions: internal RAM (SRAM), external RAM (also SRAM), and flash memory. Internal RAM is split into two roughly equal sections of about 16K words (32-bit), one for code and the other for data. Another data-only region exists in external RAM. The MEIXmpData structure (defined in xmp.h) just about fills the internal RAM region. The MEIXmpBufferData structure is in the external memory region. (Almost all of the configurable parameters are in the MEIXmpData structure.)

XMP memory organization.

Immediately after power-on or reset, the SHARC loads a small boot loader (~128 words) from the bottom of flash memory into internal RAM, and then branches to the first instruction. This boot loader then loads the rest of the firmware code (~16K words) from the same flash memory page and then jumps to the first firmware instruction. The firmware then copies data into the MEIXmpData (internal RAM) and MEIXmpBufferData (external RAM) structures from identical copies stored in flash memory.

Memory Map
Memory map of XMP-PCI and XMP-CPCI.
Corrupted Flash Memory?

It is very difficult (but not impossible) to corrupt the flash memory, because there are software and hardware locks which make this improbable. If you suspect that the flash memory is being corrupted, make sure that all of your software developers know who is writing updated values to flash memory and when they are doing that. Often, one member of your software developer team is writing updated values to flash, and forgetting to tell the other team members about it.


Faults and Resets

CONTENTS:
Architectural Overview
Host Bus
Encoder Inputs
Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

Faults and Resets

The fault monitor circuitry detects faults and controls reset operations.

Resets

XMP system resets can occur due to hard reset (hardware reset) or soft reset (software reset). The DAC (digital-to-analog converter) outputs are disabled after both Hard Reset and Soft Reset events.

Fault monitor reset scheme.
Hard Reset

Hard resets are caused by:

  • Power-up
  • Low voltage conditions on either 5V, +15V or -15V, +12V or -12V, 3.3V
  • Software reset via the host (through Interface CPLD), or watchdog timeout
  • External reset line (TTL) activation (one dedicated input per board)

Hard reset occurs 400ms after power-on or fail events, and 200ms after software reset or external reset events. The Hard Reset lasts 200-400 msec, leaving the DACs with Vout switched away from the DAC and tied to the DAC's analog ground. The first write from the SHARC to the DAC will cause this switch (Vout) to shift back to the DAC for normal operations.

Soft Reset

Soft resets are caused by a watchdog timeout from the DSP's flag output, or when the host writes a key sequence to the host system registers. External reset is triggered using an external TTL input. Both software and external resets are active low. To guarantee reset when Vcc is low, the triple OR gate will operate down to Vcc = +1V.

The software reset is handled by a Watchdog Timer with an adjustable timeout. The Watchdog Timer is intended to catch malfunctioning firmware. The Watchdog Timer does not monitor Vcc. The timer only responds to a timeout accompanied by a 200 ms reset. The Watchdog Timer is disabled during power-up, and following a reset of the SHARC DSP, allows the DSP to boot and begin instruction execution.

A Soft Reset will:

  • Cause all analog command outputs to switch away from the DAC to a low impedance path (to their associated analog ground).
  • Soft reset the motion blocks, causing them to clear dedicated I/O to their DSP-configured default state, and to reset the position counters and associated registers. Soft Reset will not enable the FPGA configuration to be reloaded. Note that it takes a power-on Hard Reset to cause the FPGAs to reload configurations.
  • Clear the host interface Reset Status register and all other host system registers.
  • Not reset the SHARC DSP. The host driver will soft-boot the DSP.

For the Soft Reset watchdog circuitry, a latched reset is used, which provides an added protection of not allowing a malfunctioning SHARC DSP to mistakenly write to the DAC (the Soft Reset is held until the host clears it, as part of the host's watchdog timeout recovery routine).

Power Fail Control of DAC Outputs

The DAC has embedded analog switches in the output stage. The analog switches G1 and G2 are controlled by the on-chip voltage monitor and by the dedicated reset input pin (Reset IN). A low voltage on the Reset IN input will cause G1 to open and G2 to close, clamping Vout to AGnd via a low impedance path (typically 1K ohms). This condition will remain until the reset input goes high and a valid word is written into the DAC.

DAC output protection.

The Reset IN input is the active low OR'ed condition of Hard Reset or Soft Reset.

A 65K ohm resistor from Vout to AGnd will maintain 0 volts on Vout until the supplies reach +1 volt. What happens if we lose an analog power rail? The Reset IN input will go low once one of our rails crosses the reset threshold. The Reset IN input is valid for Vdd and Vss to +1.2 volts, and below those voltage levels, the 65K ohm pulldown resistor protects the circuit.


XMP Data Architecture

CONTENTS:
Architectural Overview
Host Bus
Encoder Inputs
Digital-to-Analog Converter (DAC) Subsystem
Analog Inputs
SHARC DSP Processor Subsystem
Memory Organization
Faults and Resets
XMP Data Architecture
CHAPTER 6
XMP Controller Motion Drive I/O

XMP Data Architecture

This section provides a dynamic look at the XMP's data architecture, between board components, and between the controller and external devices such as drive amplifiers.

XMP Power-up Sequence

When first powering-up the XMP controller, several actions initialize the controller according to the firmware's settings and prepare it for motion control.

Power is applied

During power-up, the host computer initializes. Power is also supplied via bus lines to the XMP controller and other devices connected to the PCI bus. The XMP controller's power supervisor waits for the bussed power supply to attain voltage thresholds (2.93 for 3.3 VDC power, and 4.63 for 5 VDC power) before powering the controller's components. Until power fully stabilizes, the board is kept in a reset condition.

Once initialized, the CPU bios polls the bus and assigns an address to each device (including the XMP controller).

PCI handshakes with SHARC DSP and Lattice

When the XMP controller's PCI receives a bus address from the host computer's CPU bios, it handshakes with the SHARC and Lattice.

FPGAs loaded

With the FPGA's file format determined, the SHARC loads both FPGAs with the following:

  • DSP variables (including default timing parameters)
  • FPGA image
  • SIM4 FPGA image (if a SIM4 module is installed)
Firmware loaded from flash memory into the DSP

With the FPGAs loaded, the controller is now ready to load the firmware from flash memory to the DSP.

DACs calibrated and activated

At the beginning of the power-up process, the digital-to-analog converters (DACs) are kept grounded (i.e., in an inactive, OFF state) until the controller is ready to switch them in. This avoids erroneous inputs-outputs with the drive. After the DSP is loaded, the DACs are internally calibrated and activated. The system may now accept input from the drives and send commands.

Controller initializes

The controller's boot configuration is based upon parameters stored in flash memory; these determine the controller's (and drive's) start-up behavior. One of the programmer's first tasks is to define what this "hello world" starting state ought to be immediately after power-up. In some instances, it may prove advantageous to keep a default boot configuration in flash memory, then modify it from the application during boot-up. In other instances, it may be better for the application to flash the controller's memory with an entirely new set of parameters during boot-up. The user must determine the best approach.

Controller configuration can be done using Motion Console; however, during development of an application, it is the programmer's responsibility to write code that properly configures the controller for its next session upon exit of the application. The controller should utilize safe amp enabling and hardware I/O to prevent runaway conditions during start-up.

For this example, we will assume the following safety measures:

  • The drive is configured for active high amp enabling. (That is, the drive cannot be enabled without controller input.)
  • The controller is configured to awaken with the Amp Enable line set to low (off). This should keep an active high drive disabled.
  • The controller is configured to trigger an Abort if the Position Error is greater than some specified value. Because the controller's data registers are all set to zero at start-up (including the Command and Actual Position values), any mechanical movement will produce a Position Error. By triggering an Abort based on Position Error, the controller safeguards against uncommanded moves.2
Device Driver and Operating System Loads

At this point, the XMP controller is initialized and ready for use. The next and final phase of the power-up sequence is the loading of the XMP's device driver and operating system on the host computer. This must be completed before any motion control application can be loaded and run.

The XMP controller's device driver is shipped to load manually; however, it can be reconfigured to load automatically. To view the XMP's device driver, access your operating system's Devices window. (In WindowsNT? environments, the XMP controller's device driver is labeled as MeiXMP.)

The operating system completes its loading within several seconds of the XMP's initialization.

Load Motion Control Application
Application boot-up

When a motion control application (e.g., Motion Console) is loaded, it first verifies that the XMP controller is operational. The user interface is displayed and is now available for use.

Create Control Object and Initialize Controller

Before any motion application can move axes, it must create a controller object and initialize communication. This is a standard requirement for any application which intends movement.

Homing the Motion Control System

Homing is the setting of a coordinate system through detection of a known point in space (the "home" point). A home point can be defined using a limit switch, or by detecting a signal from the encoder such as a home or index pulse. This is typically the first act a controller must perform before running the main application code.

Before homing, objects must be created and the controller must be initialized (see above). One example of a homing sequence is shown below, consisting of:

  • Configure a capture to trigger off the home input.
  • Configure a home event action.
  • Arm the capture.
  • Command a velocity move while polling the capture trigger.
  • When the trigger changes (at the home point), set the origin.
  • Move the axis to the origin.

This homing example is taken from the home1.c sample application program, which may be found in the Sample Applications module and should be studied. For sake of clarity, excerpts are included below.

Configure the Capture trigger

After the motion objects are created and the controller is initialized, the MPI must configure and arm a capture. The trigger in this example is a home sensor (limit switch) on a stage.

Define motion parameters

In preparation for commanding moves, there are several motion parameters which must be defined:.

Two types of moves are used for this sample homing routine: a velocity move and a trapezoidal move. The velocity move consists simply of running the axis at a set velocity, hunting for the home point, without regard to its starting and ending positions.

Because a trapezoidal move requires beginning and ending positions (and we don't know the axis coordinates until the home point is detected), the first move must be a velocity move. After coordinates are established through detection of a home point, a trapezoidal move may be used to move the axis to the origin.

Configure the home event action

The "home event" is the what we use to detect the home point. The home event could be an input from a limit switch, triggered when the axis runs into it. The home event could be a home or index pulse on the encoder. For this example, the stage's HOME switch is used as the trigger, and the trigger's input is configured to be TRUE (active edge).

The "home action" is what happens when the home is detected. In this example, the programmer has decided to define the action as a command to STOP the axis.

Arm the trigger

With the home event and action defined, all that is left is to "arm" the trigger by setting the mpiCaptureArm to TRUE. Recall that earlier, this was set to FALSE to "disarm" the system.

Start a velocity move

With the capture event and action defined, and the trigger armed, we are ready to hunt for the home point. This is accomplished by commanding a velocity move. Before the axis can be commanded, however, the XMP controller must first enable the drive. In this example, it is assumed that the drive is wired to be an active high type; therefore, the Amp Enable line is set to high (on). Drive enabling via software must be done as a separate code item and is not shown here:

As the leadscrew rotates, the slide approaches the home sensor.

Poll trigger status

With the trigger armed, the software's next task is to poll the status of the trigger while the axis continues rotating.

Home event detected

As the axis motor continues turning, the leadscrew rotates until the stage makes contact with the home sensor; this acts as the trigger. When the trigger event is detected, the encoder position is captured and a stop action is initiated.

Define the home position as the origin

When the home pulse is detected in our example, another simultaneous action is initiated: the axis's position is captured by the FPGA. At this point, the axis position is recorded in memory. Meanwhile, the axis slows to a stop. The mpiAxisOriginSet command is then used to set the capture position to zero, making it the new origin of the axis's coordinate system.

Move axis to the (new) origin

Our sample homing routine's last task is to move the axis to the origin. Recall that the home pulse was detected while in motion, and that after detection, the axis coasted to a stop. This means that the axis is now somewhere beyond the home point (our new origin).

Because we now have a coordinate system, we can perform a backward trapezoidal move from the current position to the intended position (the origin).

Delete Objects

Finally, the homing routine must delete the objects it has created. This is performed with a number of deletion objects such as mpiMotionDelete,
mpiAxisDelete, mpiMotorDelete, etc.

Internal Data Movement via "Riptide"

Within a typical SHARC timer cycle, data is moved back and forth between the SHARC and the FPGAs and various feedback devices (e.g., encoders, resolvers, etc.). On the XMP controller, this is performed over a proprietary, dedicated data bus called the "Riptide." The Riptide is the serial backbone of all motion data flow. Within a given SHARC cycle, data moves first from the SHARC to the FPGAs, and then to the drives. Within the same cycle, data is moved in the opposite direction (inbound) from the drive and encoder(s) to the SHARC.

As more drives and encoders are added to the motion control system, the required data bandwidth increases across the Riptide, occupying a greater portion of the foreground tasks.

2. IMPORTANT! Use of Position Error and other positional inputs as safeguards assumes: a) good data connection between the encoder(s) and controller; b) normal conditions. If a higher level of safety is required, then extra measures should be utilized, such as broken encoder wire detection.

Return to Hardware's Main Menu


PDF Versions of the Software

The Software Reference has been divided into the 28 different objects. Each object has its own print-friendly .pdf version that includes the descriptions of all the object's Data Types and Methods.

To print out an object's pdf, simply click on one of the links below and print out the pdf from either Adobe Acrobat Reader or a pdf-supported browser.
* - modules

s


Adc Objects

Introduction

An Adc object manages a single analog-to-digital converter on an XMP motion controller. The XMP controller supports 8 channels (0 to 7) of 16 bit analog-to-digital conversions.

To configure the voltage range for an analog input, use the method mpiAdcConfigSet(MPIAdc adc, MPIAdcConfig *config, void *external), where adc is a handle to an MPIAdc object, and config is a pointer to a MPIAdcConfig structure. The MPIAdcConfig structure contains a “range” element, which specifies the analog input’s voltage range. The XMP controller supports voltage ranges of 10.0V, 5.0V, 2.5V, or 1.25V volt ranges (all ranges are bipolar). Set the MPIAdcConfig range to one of the following values:

Bipolar Voltage Range (+/- V)
10.0
5.0
2.5
1.25

To use the ADC, first create an ADC object using mpiAdcCreate(MPIControl control, long number), where control is a handle to an MPIControl object and number is the analog-to-digital converter channel number.

The number of ADCs on the controller can be configured using the method mpiControlConfigSet(MPIControl control, MPIControlConfig *config, void *external). The MPIControlConfig structure contains an element called adcCount, which is used to specify the number of analog-to-digital converter channels. The default setting is for eight (8) axes.

After the ADC has been configured, to read a channel use the method mpiAdc Input(MPIAdc adc, unsigned long *input), where adc is a handle to an MPIAdc object, and input is a pointer to the digitally converted value.
Methods
Create, Delete, Validate Methods
 | mpiAdcCreate | Create Adc object
 | mpiAdcDelete | Delete Adc object
 | mpiAdcValidate | Validate Adc object

Configuration and Information Methods
 | mpiAdcConfigGet | Get Adc configuration
 | mpiAdcConfigSet | Set Adc configuration
 | mpiAdcFlashConfigGet | Get Adc flash config
 | mpiAdcFlashConfigSet | Set Adc flash config
Action Methods
 | mpiAdcInput | Read input level
Memory Methods
 | mpiAdcMemory | Set address to Adc memory
 | mpiAdcMemoryGet | Copy Adc memory to application memory
 | mpiAdcMemorySet | Copy application memory to Adc memory
Relational Methods
 | mpiAdcControl | Return handle of Control object associated with Adc
 | mpiAdcMotorMapGet | Get the object map and write it into the structure pointed to by map
 | mpiAdcNumber | Get index of Adc

Data Types
MPIAdcConfig / MEIAdcConfig
MPIAdcMessage
MEIAdcMux


MPIAdcConfig and MEIAdcConfig

MPIAdcConfig / MEIAdcConfig

MPIAdcConfig

typedef struct MPIAdcConfig {
    double	range;	/* +/- Voltage */
} MPIAdcConfig;
Description
range The voltage range that the ADC can be configured for. All values are measured in volts. Valid values are 2.5, 5.0, and 10.0

MEIAdcConfig

typedef struct MEIAdcConfig {
    MEIAdcMux	mux;
} MEIAdcConfig;

Description
 | mux | is used to configure what signal an MPIAdc object will look at.

See Also | MPIAdc


MPIAdcMessage

MPIAdcMessage

 typedef enum {
        MPIAdcMessageADC_INVALID,
    } MPIAdcMessage;

Description
 | MPIAdcMessageADC_INVALID
 | Meaning | The MPIAdc handle passed to an MPIAdc method is invalid.
 | Possible Causes | Either the handle was never initialized or the mpiAdcCreate method failed.
 | Recommendations | Use mpiAdcValidate after mpiAdcCreate to see if the returned handle is valid.

See Also | mpiAdcValidate | mpiAdcCreate


MEIAdcMux

MEIAdcMux

 typedef enum {
    MEIAdcMuxDAC_CAL,
    MEIAdcMuxPLUS10V,
    MEIAdcMux0V,
    MEIAdcMuxMINUS10V,
    MEIAdcMuxANALOG_IN_0,
    MEIAdcMuxANALOG_IN_1,
    MEIAdcMuxANALOG_IN_2,
    MEIAdcMuxANALOG_IN_3,
    MEIAdcMuxANALOG_IN_4,
    MEIAdcMuxANALOG_IN_5,
    MEIAdcMuxANALOG_IN_6,
    MEIAdcMuxANALOG_IN_7,
} MEIAdcMux;
Description AdcMux is an enumeration used by MEIAdcConfig.mux. It configures what signal a particular MPIAdc object will look at. The following table lists what signal each MEIAdcMux enumeration stands for:
MEIAdcMuxDAC_CAL | Used to calibrate an ADC object from a DAC object. Used by MEI for calibration and testing.
MEIAdcMuxPLUS10V | MEIAdcMuxPLUS10V +10V signal. Used by MEI for calibration and testing.
MEIAdcMux0V | 0V signal. Used by MEI for calibration and testing.
MEIAdcMuxMINUS10V | -10V signal. Used by MEI for calibration and testing.
MEIAdcMuxANALOG_IN_0 | Analog input 0
MEIAdcMuxANALOG_IN_1 | Analog input 1
MEIAdcMuxANALOG_IN_2 | Analog input 2
MEIAdcMuxANALOG_IN_3 | Analog input 3
MEIAdcMuxANALOG_IN_4 | Analog input 4
MEIAdcMuxANALOG_IN_5 | Analog input 5
MEIAdcMuxANALOG_IN_6 | Analog input 6
MEIAdcMuxANALOG_IN_7 | Analog input 7

Note
 | MEIAdcMuxDAC_CAL | These are all specific to XMP Revision 1 boards. The ADC input lines will be floating if these values are used to configure an MPIAdc object.
 | MEIAdcMuxPLUS10V
 | MEIAdcMux0V
 | MEIAdcMuxMINUS10V

See Also | MEIAdcConfig


mpiAdcConfigGet

Declaration
long mpiAdcConfigGet(MPIAdc       adc,
                     MPIAdcConfig *config,
                     void         *external)
Required Header adc.h
Description

AdcConfigGet gets the configuration of an Adc object (adc) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only
 external either points to a structure of type MEIAdcConfig{} or is NULL.
Return Values
MPIMessageOK if AdcConfigGet successfully gets the configuration of an Adc object and writes it to the structure
See Also | mpiAdcConfigSet | MEIAdcConfig


mpiAdcConfigSet

Declaration
long mpiAdcConfigSet(MPIAdc       adc,
                     MPIAdcConfig *config,
                     void         *external)
Required Header stdmpi.h
Description

AdcConfigSet sets the configuration of an Adc object (adc) using the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only
 external either points to a structure of type MEIAdcConfig{} or is NULL.
Return Values
MPIMessageOK if AdcConfigSet successfully sets the configuration of the Adc object using data from the structure
See Also | mpiAdcConfigGet | MEIAdcConfig


mpiAdcControl

Declaration
const MPIControl mpiAdcControl(MPIAdc   adc)
Required Header stdmpi.h
Description

AdcControl returns a handle to the motion controller (Control) with which an Adc (adc) is associated.

adc | a handle to the Adc object

Return Values
MPIHandleVOID | if adc is invalid
MPIControl | handle to a Control object

See Also | mpiAdcCreate | mpiControlCreate


mpiAdcCreate

Declaration
const MPIAdc mpiAdcCreate(MPIControl  control,
                          long        number)
Required Header stdmpi.h
Description

AdcCreate creates an Adc object associated with the analog-to-digital converter identified by number located on motion controller control. AdcCreate is the equivalent of a C++ constructor.

control | a handle to the motion controller.
number | the adc number

Return Values
MPIHandleVOID | if the object could not be created
handle | to an Adc object

See Also | mpiAdcDelete | mpiAdcValidate


mpiAdcDelete

Declaration
long mpiAdcDelete(MPIAdc  adc)
Required Header adc.h
Description

AdcDelete deletes an Adc object and invalidates its handle (adc). AdcDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if AdcDelete successfully deletes the Adc object and invalidates its handle
See Also | mpiAdcCreate | mpiAdcValidate


mpiAdcFlashConfigGet

Declaration
long mpiAdcFlashConfigGet(MPIAdc        adc,
                          void          *flash,
                          MPIAdcConfig  *config,
                          void          *external
Required Header stdmpi.h
Description

AdcFlashConfigGet gets the flash configuration of an Adc object (adc) and writes it into the structure pointed to by config, and also writes it in the implementation-specific structure pointed to by external (if external is not NULL).

XMP Only
 external either points to a structure of type MEIAdcConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if AdcFlashConfigGet successfully gets the Adc’s flash configuration and writes it into the structure(s)
See Also | mpiAdcFlashConfigSet | MEIAdcConfig | MEIFlash


mpiAdcFlashConfigSet

Declaration
long mpiAdcFlashConfigSet(MPIAdc        adc,
                          void          *flash,
                          MPIAdcConfig  *config,
                          void          *external)
Required Header stdmpi.h
Description

AdcFlashConfigSet sets the flash configuration of an Adc object (adc) using the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

XMP Only
 external either points to a structure of type MEIAdcConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if AdcFlashConfigSet successfully sets the Adc’s flash configuration using data from the structure(s)
See Also | MEIFlash | mpiAdcFlashConfigGet


mpiAdcInput

Declaration
long mpiAdcInput(MPIAdc         adc,
                 unsigned long  *input)
Required Header stdmpi.h
Description

AdcInput gets the value of an Adc’s (adc) input and writes it into the location pointed to by input.

Return Values
MPIMessageOK if AdcInput successfully gets the value of the Adc’s input and writes it to the location
See Also


mpiAdcMemory

Declaration
long mpiAdcMemory(MPIAdc    adc,
                  void      **memory)
Required Header stdmpi.h
Description

AdcMemory writes an address [used to access an Adc’s memory (adc)] to the contents of memory. This address, or an address calculated from it, can be passed as the src argument to mpiAdcMemoryGet(...) and the dst argument to mpiAdcMemorySet(...).

Return Values
MPIMessageOK if AdcMemory successfully writes the Adc’s address to the contents of memory
See Also | mpiAdcMemoryGet | mpiAdcMemorySet


mpiAdcMemoryGet

Declaration
long mpiAdcMemoryGet(MPIAdc    adc,
                     void      *dst,
                     void      *src,
                     long      count)
Required Header stdmpi.h
Description

AdcMemoryGet copies count bytes of an Adc’s memory (adc, starting at address src) and to application memory (starting at address dst).

Return Values
MPIMessageOK if AdcMemoryGet successfully copies Adc memory to application memory
See Also | mpiAdcMemorySet | mpiAdcMemory


mpiAdcMemorySet

Declaration
long mpiAdcMemorySet(MPIAdc   adc,
                     void     *dst,
                     void     *src,
                     long     count)
Required Header stdmpi.h
Description

AdcMemorySet copies count bytes of application memory (starting at address src) to an Adc’s memory (adc, starting at address dst).

Return Values
MPIMessageOK if AdcMemorySet successfully copies application memory to Adc memory
See Also | mpiAdcMemoryGet | mpiAdcMemory


mpiAdcMotorMapGet

Declaration
long mpiAdcMotorMapGet(MPIAdc        adc,
                       MPIObjectMap  *map)
Required Header stdmpi.h
Description AdcMotorMapGet gets the object map [of the Motors associated with an Adc (adc)] and writes it into the structure pointed to by map.
Return Values
MPIMessageOK if AdcMotorMapGet successfully gets the object map of the Motors associated with an Adc and writes it into the structure
See Also


mpiAdcNumber

Declaration
long mpiAdcNumber(MPIAdc   adc,
                  long     *number)
Required Header stdmpi.h
Description AdcNumber writes the index of an Adc object (adc, on the motion controller that the Adc object is associated with) to the contents of number.
Return Values
MPIMessageOK if AdcNumber successfully writes the Adc’s index to the contents of number
See Also


mpiAdcValidate

Declaration long mpiAdcValidate(MPIAdc adc)
Required Header stdmpi.h
Description AdcValidate validates the Adc object and its handle (adc).
Return Values
MPIMessageOK if Adc is a handle to a valid object.
See Also | mpiAdcCreate | mpiAdcDelete


Axis Objects

Introduction

An Axis object manages a single physical axis on a motion controller. It represents a reference line in a coordinate system. The controller calculates an axis's command position every sample based on the motion commanded by the Motion Supervisor. The Axis object contains command, actual, and error position data, plus status.

An Axis can have one or more Filters associated with it and each Filter can have one or more Motors associated with it. The Filter and Motor objects ensure the Axis command path is followed and that the control signals get to the correct motor. Complex mechanical systems with two (or more) motors can be mapped to a single axis of motion, abstracting the details of the physical hardware and making motion software much easier to develop.

For simple systems, there is a one to one relationship between the Axis, Filter and Motor objects.
Methods
Create, Delete, Validate Methods
 | mpiAxisCreate | Create Axis object
 | mpiAxisDelete | Delete Axis object
 | mpiAxisValidate | Validate Axis object

Configuration and Information Methods
 | mpiAxisActualPositionGet | Get actual position
 | mpiAxisActualPositionSet | Set actual position
 | mpiAxisActualVelocity | Set actual velocity
 | mpiAxisConfigGet | Get Axis configuration
 | mpiAxisConfigSet | Set Axis configuration
 | mpiAxisCommandPositionGet | Get command position
 | mpiAxisCommandPositionSet | Set command position
 | mpiAxisFlashConfigGet | Get Axis flash config
 | mpiAxisFlashConfigSet | Set Axis flash config
 | mpiAxisOriginGet | Get Axis origin
 | mpiAxisOriginSet | Set Axis origin
 | mpiAxisPositionError | Get position error of an Axis
 | mpiAxisStatus | Get Axis status
 | mpiAxisTrajectory | Get Axis trajectory
Event Methods
 | mpiAxis EventNotifyGet | Get event mask
 | mpiAxis EventNotifySet | Set event mask
 | mpiAxis EventReset |
Memory Methods
 | mpiAxisMemory | Set Axis memory address
 | mpiAxisMemoryGet | Copy bytes of Axis memory to application memory
 | mpiAxisMemorySet | Copy bytes of application memory to Axis memory
Relational Methods
 | mpiAxisControl | Return handle of Control associated with Axis
 | mpiAxisFilterMapGet | Get object map of Filters
 | mpiAxisFilterMapSet | Set object map of Filters
 | mpiAxisMotorMapGet | Get object map of Motors
 | mpiAxisNumber | Get index of Axis

Data Types
MPIAxisConfig / MEIAxisConfig
MPIAxisInPosition
MPIAxisMessage


Configuration of IN_POSITION and DONE Events
after STOP or E-STOP Events

Two fields, settleOnStop and settleOnEstop are incorporated into the MPIAxisInPosition{} structure. These fields control the generation and use of IN_FINE_POSITION, and DONE status bits and events. A value of FALSE in these fields causes the IN_FINE_POSITION to be held false after STOP (or E-STOP) events and DONE to be based solely on command velocity (i.e. DONE is true as soon as the command velocity reaches 0). A value of TRUE in these fields causes IN_FINE_POSITION and DONE to be calculated in the same manner as that for normal motion, except that the position where the command velocity reaches zero is used for a target rather than the original Target Position.

The following table shows the generation of these status bits with settleOnStop (settleOnEstop) = FALSE (the default value):

Motion Status | After S-curve or Trapezoidal Move | During Velocity Move | After STOP (E-STOP) | After ABORT
IN_FINE_POSITION | Based on target distance (see note 3) | FALSE | FALSE | FALSE
IN_COARSE_POSITION | Based on target distance | FALSE | FALSE | FALSE
AT_TARGET | TRUE when command = target | FALSE | FALSE | FALSE
DONE | TRUE if both TC and IN_FINE_POSITION are true | FALSE | TRUE when command velocity = 0 | TRUE
The following table shows the generation of these status bits with settleOnStop (settleOnEstop) = TRUE:

Motion Status | After S-curve or Trapezoidal Move | During Velocity Move | After STOP (E-STOP) | After ABORT
IN_FINE_POSITION | Based on target distance (see note 3) | FALSE | Based on position error (see note 1) | FALSE
IN_COARSE_POSITION | Based on target distance | FALSE | FALSE | FALSE
AT_TARGET | TRUE when command = target | FALSE | FALSE | FALSE
DONE | TRUE if both TC and IN_FINE_POSITION are true | FALSE | Same as IN_FINE_ POSITION | TRUE

NOTE 1: IN_FINE_POSITION is based on four criteria:

  • The trajectory has completed (see note 2).
  • |command position – actual position| < fine position tolerance.
  • Target velocity – actual velocity| < velocity tolerance (the default setting for velocity tolerance so large that this criteria is ignored).
  • The above 3 criteria have been satisfied for the duration specified by the settling time parameter.

NOTE 2: The reference to “TC” above refers to TRAJECTORY_COMPLETE, an internal status that is set when all of the current motion segments (frames) have completed.

NOTE 3: The criteria used for calculation of IN_FINE_POSITION after s-curve or trapezoidal motion has changed to the following: (This is the same as the MPI-1 criteria.)

  • The trajectory has completed (see note 2).
  • |target position – actual position| < fine position tolerance.
  • |command velocity – actual velocity| < velocity tolerance (the default setting for velocity tolerance so large that this criteria is ignored).
  • The above 3 criteria have been satisfied for a duration specified by the settling time parameter.

Return to MPIAxisInPosition


MPIAxisConfig and MEIAxisConfig

MPIAxisConfig / MEIAxisConfig

MPIAxisConfig

typedef struct MPIAxisConfig {
    MPIAxisInPosition	inPosition;
    MPIObjectMap	filterMap;
}MPIAxisConfig;

Description
 | inPosition | See MPIAxisInPosition.
 | filterMap | bitmap indicating which Filter objects are mapped to the Axis. See MPIObject for more details.

MEIAxisConfig

typedef struct MEIAxisConfig {
    MEIXmpAPosInput	APos [MEIXmpAxisAPosInputs];
    MEIXmpAxisFilter	Filter;
    MEIXmpAxisGear	Gear;
}MEIAxisConfig;
Description
APos - an array of structures that set Actual position inputs. The structure has two elements:
  • Ptr - Pointer to Actual position input register. Default value is corresponding encoder input.
  • Coeff - Value of Actual position input register
Filter
  • Input
  • Output
  • Delta
  • Delay
  • Timer
  • Pointer
Gear - Coefficients for gearing off a position input
  • Ptr - pointer to gear master
  • Ratio.A - numerator of multiplier
  • Ratio.B - denominator of multiplier
  • Ratio.Old -
  • Ratio.Remainder -
  • Position - final geared position

See Also | mpiAxisConfigGet | mpiAxisConfigSet | MPIAxisInPosition | MPIObject


MPIAxisInPosition

MPIAxisInPosition

typedef struct MPIAxisInPosition {
    struct {
        float	positionFine;
        long	positionCoarse;
        float	velocity;
    } tolerance;
        float	settlingTime;	/* seconds */
        long	settleOnStop;
        long	settleOnEstop;
} MPIAxisInPosition;

Description
 | tolerance |  | Includes the following 3 elements that determine settling criteria for an axis.
 | positionFine |  | Value, in counts, from the move target position at which the DSP sets the IN_FINE_POSITION flag. This parameter is used as part of the Axis settling criteria to determine Motion Done.
 | positionCoarse |  | Value, in counts, from a move target position at which the DSP sets the IN_COARSE_POSITION flag.
 | velocity |  | Value, in counts/second, from the final move velocity at which the DSP set the AT_VELOCITY flag. Only used with Velocity type moves.
 | settlingTime | Duration that PositionFine, PositionCoarse, or Velocity must be TRUE before flag is set.
 | settleOnStop | If TRUE, DSP will use settling criteria when Stop Event occurs.
 | settleOnEstop | If TRUE, DSP will use settling criteria when E-Stop Event occurs.

See Also | Special Note on Configuration of IN_POSITION and Done Events after STOP or E_STOP Events


MPIAxisMessage

MPIAxisMessage

typedef enum {
    MPIAxisMessageAXIS_INVALID,
    MPIAxisMessageCOMMAND_NOT_SET,
}MPIAxisMessage;
Description

AxisMessage is an enumeration of Axis error messages that can be returned by the MPI library.

MPIAxisMessageAXIS_INVALID | Indicates Axis handle is invalid.
See Also


mpiAxisActualPositionGet

Declaration
long mpiAxisActualPositionGet(MPIAxis  axis,
                              double   *actual)
Required Header stdmpi.h
Description
axis | a handle to an Axis object
*actual | a pointer to the Axis actual position returned by the method.
Return Values
MPIMessageOK if AxisActualPositionGet successfully gets and writes the value of the actual postion of axis to the location.
See Also | mpiAxisActualPositionSet | Using the Origin Variable


mpiAxisActualPositionSet

Declaration
long mpiAxisActualPositionSet(MPIAxis  axis,
                              double   actual)
Required Header stdmpi.h
Description AxisActualPositionSet sets the value of the actual position of an Axis (axis) to actual.
axis | a handle to the Axis object
actual | value to which the Axis actual position will be set
Return Values
MPIMessageOK if AxisActualPositionSet successfully sets the value of the actual postion of an Axis to actual
See Also | AxisCommandPositionSet | Using the Origin Variable


mpiAxisActualVelocity

Declaration
long mpiAxisActualVelocity(MPIAxis   axis,
                           double    *actual)
Required Header stdmpi.h
Description AxisActualVelocity reads the value of the actual velocity on an Axis (axis) and writes it in the location pointed to by actual.
Return Values
MPIMessageOK if AxisActualVelocity succesfully gets and writes the value of the actual velocity of axis to the location.
See Also


mpiAxisConfigGet

Declaration
long mpiAxisConfigGet(MPIAxis       axis,
                      MPIAxisConfig *config,
                      void          *external)
Required Header stdmpi.h
Description

AxisConfigGet gets the configuration of an Axis (axis) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

axis | a handle to the Axis object
*config | pointer to the MPIAxisConfig structure
*external | pointer to an external. See remarks below

Remarks
 | For XMP controllers, external either points to a structure of type MEIAxisConfig{} or is NULL.
Return Values
MPIMessageOK if AxisConfigGet successfully gets the Axis configuration and writes it into the structure(s)
See Also | MPIAxisConfig | mpiAxisConfigSet | MEIAxisConfig


mpiAxisConfigSet

Declaration
long mpiAxisConfigSet(MPIAxis       axis,
                      MPIAxisConfig *config,
                      void          *external)
Required Header stdmpi.h
Description

AxisConfigSet sets the configuration of an Axis (axis) using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

axis | a handle to the Axis object
*config | pointer to an MPIAxisConfig structure.
*external | pointer to an external. See remarks below.
XMP Only
 external either points to a structure of type MEIAxisConfig{} or is NULL.
Return Values
MPIMessageOK if AxisConfigSet successfully sets the Axis configuration
See Also | mpiAxisConfigGet | MEIAdcConfig


mpiAxisCommandPositionGet

Declaration
long mpiAxisCommandPositionGet(MPIAxis axis,
                               double  *command)
Required Header stdmpi.h
Description

AxisCommandPositionGet gets the value of the command position of an Axis (axis) and puts it in the location pointed to by command.

axis | a handle to the Axis object
*command | a pointer to the Axis command position returned by the method
Return Values
MPIMessageOK if AxisCommandPositionGet successfully gets the value of the command position of axis and puts it in the location
See Also | mpiAxisCommandPositionSet


mpiAxisCommandPositionSet

Declaration
long mpiAxisCommandPositionSet(MPIAxis  axis,
                               double   command)
Required Header stdmpi.h
Description

AxisCommandPositionSet sets the value of the command position of an Axis (axis) from command.

axis | a handle to the Axis object
command | value to which the Actual command position will be set

Remarks
Setting the Axis Command Position may cause the axis to jump. See the discussion of the Axis Origin before using the AxisActualPositionSet and AxisCommandPositionSet methods.
Return Values
MPIMessageOK if AxisCommandPositionSet successfully sets the value of the command position of axis from command
See Also


mpiAxisControl

Declaration
const MPIControl mpiAxisControl(MPIAxis  axis)
Required Header stdmpi.h
Description

AxisControl returns a handle to the motion controller (Control) with which an Axis (axis) is associated.
axis a handle to the Axis object
Return Values
MPIHandleVOID if axis is invalid
See Also


mpiAxisCreate

Declaration
const MPIAxis mpiAxisCreate(MPIControl  control,
                            long       *number)
Required Header stdmpi.h
Description

AxisCreate creates an axis object associated with the axis identified by number located on motion controller control. AxisCreate is the equivalent of a C++ constructor.

control | a handle to Axis object.
number | the number specifies which Axis object is being created. The number corresponds to an Axis object in XMP memory.

Remarks
 | An Axis represents a physical axis in space such as X, Y, Z, Theta, or other axes. An Axis may be comprised of one or more motors, such as with a gantry system.

Return Values
handle | to an Axis object
MPIHandleVOID | if the object could not be created

See Also | mpiAxisDelete | mpiAxisValidate


mpiAxisDelete

Declaration
long mpiAxisDelete(MPIAxis  axis)
Required Header stdmpi.h
Description

AxisDelete deletes an Axis object and invalidates its handle (axis).
AxisDelete is the equivalent of a C++ destructor.

axis | the Axis handle to be deleted

Remarks
All objects that are created in an application should be deleted in reverse order at the end of the code.
Return Values
MPIMessageOK if AxisDelete successfully deletes an Axis object and invalidates its handle
See Also | mpiAxisCreate | mpiAxisValidate


mpiAxisEventNotifyGet

Declaration
long mpiAxisEventNotifyGet(MPIAxis        axis,
                           MPIEventMask   *eventMask,
                           void           *external)
Required Header stdmpi.h
Description

AxisEventNotifyGet writes the event mask (that specifies the event type(s) for which host notification has been requested) to the location pointed to by eventMask, and also writes it into the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventMask, i.e, the event notification information in eventMask and in external is not the same information. Note that eventMask or external can be NULL (but not both NULL).

axis | a handle to the Axis object
*eventMask | pointer to an MPIEventMask
*external | pointer to an external. See remarks below
XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL.

The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).

Return Values
MPIMessageOK if AxisEventNotifyGet successfully writes the event mask to the location(s)
See Also | MEIEventNotifyData | MEIEventStatusInfo | mpiAxisEventNotifySet


mpiAxisEventNotifySet

Declaration
long mpiAxisEventNotifySet(MPIAxis       axis,
                           MPIEventMask  eventMask,
                           void          *external)
Required Header stdmpi.h
Description

AxisEventNotifySet requests host notification of the event(s) that are generated by axis and specified by eventMask, and also specified by the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventMask, i.e, the event notification information in eventMask and in external is not the same information. Note that eventMask or external can be NULL (but not both NULL).

axis | a handle to the Axis object
eventMask | pointer to an MPIEventMask
*external | pointer to an external
XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL.

The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).

To... | Then...
enable host notification of all events | configure eventmask with mpiEventMaskALL(eventMask)
disable host notification of all events | configure eventmask with mpiEventMaskCLEAR(eventMask)
Return Values
MPIMessageOK if AxisEventNotifySet successfully requests host notification of the event(s) that are specified by eventMask and generated by motion
See Also | MEIEventNotifyData | MEIEventStatusInfo | MPIEventMask | MPIEventType | mpiEventMaskALL | mpiEventMaskCLEAR | mpiAxisEventNotifyGet | MEIEventNotifyData


mpiAxisEventReset

Declaration
long mpiAxisEventReset(MPIAxis      axis,
                       MPIEventMask eventMask)
Required Header stdmpi.h
Description

To... | Then...
enable host notification of all events | configure eventmask with mpiEventMaskALL(eventMask)
disable host notification of all events | configure eventmask with mpiEventMaskCLEAR(eventMask)
Return Values
MPIMessageOK if AxisEventNotifySet successfully requests host notification of the event(s) that are specified by eventMask and generated by motion
Remarks

Event notification is enabled for event types specified in eventMask, a bit mask generated by the logical OR of the MPIEventMask bits associated with the desired MPIEventType values. Configuration of the eventMask should be done with Event macros. Event notification is disabled for event types that are not specified in eventMask.

The mask of event types generated by a Motion object consists of bits from MPIEventMaskMOTION and MPIEventMaskAXIS.

See Also
MEIEventNotifyData | MEIEventStatusInfo | MPIEventType | mpiEventMaskALL
mpiEventMaskCLEAR | MPIEventMaskMOTION | MPIEventMaskAXIS | MPIEventMask


mpiAxisFlashConfigGet

Declaration
long mpiAxisFlashConfigGet(MPIAxis       axis,
                           void          *flash,
                           MPIAxisConfig *config,
                           void          *external)
Required Header stdmpi.h
Description

AxisFlashConfigGet gets the flash configuration for an Axis (axis) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by sexternal (if external is not NULL).

The Axis flash configuration information in external is in addition to the Axis flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

axis | a handle to the Axis object
*flash |
*config | pointer to an MPIAxisConfig structure
*external | pointer to an external. See remarks below.
Remarks
 | For XMP controllers, external either points to a structure of type MEIAxisConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if AxisEventNotifySet successfully requests host notification of the event(s) that are specified by eventMask and generated by motion
See Also | MEIFlash | mpiAxisFlashConfigSet |MEIAxisConfig


mpiAxisFlashConfigSet

Declaration
long mpiAxisFlashConfigSet(MPIAxis        axis,
                           void           *flash,
                           MPIAxisConfig  *config,
                           void           *external)
Required Header stdmpi.h
Description

AxisFlashConfigSet sets the flash configuration for for an Axis (axis) using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Axis flash configuration information in external is in addition to the Axis flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

axis | a handle to the Axis object
*flash |
*config | pointer to an MPIAxisConfig structure
*external | pointer to an external. See remarks below.
XMP Only

external either points to a structure of type MEIAxisConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.

Return Values
MPIMessageOK if AxisFlashConfigSet successfully sets the Axis flash configuration using data from the structure(s)
See Also | MEIFlash | mpiAxisFlashConfigGet | MEIAxisConfig


mpiAxisFilterMapGet

Declaration
long mpiAxisFilterMapGet(MPIAxis      axis,
                         MPIObjectMap *map)
Required Header stdmpi.h
Description

AxisFilterMapGet gets the object map of the Filters [associated with an Axis (axis)] and writes it into the structure pointed to by map.

axis | a handle to the Axis object
*map | a pointer to an ObjectMap of Filters mapped to the axis
Remarks
MPIObjectMap is a long that maps the Filters in controller memory to each bit. E.g. A map value of 1 would indicate Filter 0 is mapped the Axis. A value of 6 would indicate that Filters 2 and 3 are mapped to the Axis.
Return Values
MPIMessageOK if AxisFilterMapGet successfully gets and writes the object map to the structure
See Also | mpiAxisFilterMapSet


mpiAxisFilterMapSet

Declaration
long mpiAxisFilterMapSet(MPIAxis      axis,
                         MPIObjectMap map)
Required Header stdmpi.h
Description

AxisFilterMapSet sets the Filters [associated with an Axis (axis)] using data from the object map specified by map.

axis | a handle to the Axis object
map | a list of Filters to be mapped to the axis
Remarks
MPIObjectMap is a long that maps the Filters in controller memory to each bit. E.g. A map value of 1 will map Filter 0 to the Axis. A value of 6 will map both Filters 2 and 3 to the Axis.
Return Values
MPIMessageOK if AxisFilterMapSet successfully sets the Filters using data from the object map
See Also | mpiAxisFilterMapGet | MPIObjectMap


mpiAxisMemory

Declaration
long mpiAxisMemory(MPIAxis axis,
                   void    **memory)
Required Header stdmpi.h
Description

AxisMemory writes an address (that is used to access Axis memory) to the contents of memory. This address (or an address calculated from it) is passed as the src argument to mpiAxisMemoryGet(...) and as the dst argument to mpiAxisMemorySet(...).

axis | a handle to the Axis object
Return Values
MPIMessageOK if AxisMemory successfully writes the Axis memory address to the contents of memory
See Also | mpiAxisMemoryGet | mpiAxisMemorySet


mpiAxisMemoryGet

Declaration
long mpiAxisMemoryGet(MPIAxis axis,
                      void    *dst,
                      void    *src,
                      long    count)
Required Header stdmpi.h
Description

AxisMemoryGet copies count bytes of Axis (axis) memory (starting at address src) to application memory (starting at address dst).

axis | a handle to the Axis object
*dst | pointer to the destination location to where the memory will be written
*src | pointer to the source location of memory being read
count | size of memory to be read
Return Values
MPIMessageOK if AxisMemory successfully writes the Axis memory address to the contents of memory
See Also | mpiAxisMemory | mpiAxisMemorySet


mpiAxisMemorySet

Declaration
long mpiAxisMemorySet(MPIAxis axis,
                      void    *dst,
                      void    *src,
                      long    count)
Required Header stdmpi.h
Description

AxisMemorySet copies count bytes of application memory (starting at address src) to Axis (axis) memory (starting at address dst).

axis | a handle to the Axis object
*dst | pointer to the destination location to where the memory will be written
*src | pointer to the source location of memory being read
*count | size of memory to be written
Return Values
MPIMessageOK if AxisMemorySet successfully copies count bytes of application memory to Axis memory
See Also | mpiAxisMemory | mpiAxisMemoryGet


mpiAxisMotorMapGet

Declaration
long mpiAxisMotorMapGet(MPIAxis      axis,
                        MPIObjectMap *map)
Required Header stdmpi.h
Description

AxisMotorMapGet gets the object map [of the Motors associated with an Axis (axis)] and writes it into the structure pointed to by map.

axis | a handle to the Axis object.
*map | a pointer to an ObjectMap of Motors mapped to the axis
Remarks

MPIObjectMap is a long that maps the Motors in controller memory to each bit. E.g. A map value of 1 would indicate Motor 0 is mapped the Axis. A value of 6 would indicate that Motors 2 and 3 are mapped to the Axis.

Remember that Motors are mapped to Axes through the Filter object. To configure the Axis/Motor map, the application will need to set the AxisFilterMap and FilterMotorMap.

Return Values
MPIMessageOK if AxisMotorMapGet successfully gets the object map and writes it into the structure
See Also


mpiAxisNumber

Declaration
long mpiAxisNumber(MPIAxis  axis,
                   long     *number)
Required Header stdmpi.h
Description

AxisNumber writes the index of an Axis (axis, on the motion controller that the Axis is associated with) to the contents of number.

axis | a handle to the Axis object
*number | pointer to the number
Return Values
MPIMessageOK if AxisNumber successfully writes the index of Axis to the contents of number
See Also


mpiAxisOriginGet

Declaration
long mpiAxisOriginGet(MPIAxis  axis,
                      double   *origin)
Required Header stdmpi.h
Description

AxisOriginGet gets the value of the origin of an Axis (axis) and writes it into the location pointed to by origin.

axis | a handle to the Axis object.
*origin | pointer to the Origin value returned by the method
Return Values
MPIMessageOK if AxisOriginGet successfully gets the value of the origin of the Axis and writes it to the location
See Also | mpiAxisOriginSet | Using the Origin Variable


mpiAxisOriginSet

Declaration
long mpiAxisOriginSet(MPIAxis  axis,
                      double   origin)
Required Header stdmpi.h
Description

AxisOriginSet sets the value of the origin of an Axis (axis) to origin.

axis | a handle to the Axis object
origin | Value to which the Axis Origin will be set
Return Values
MPIMessageOK if AxisOriginSet successfully sets the origin of an Axis to origin
See Also | mpiAxisOriginGet | Using the Origin Variable


mpiAxisPositionError

Declaration
long mpiAxisPositionError(MPIAxis  axis,
                          double   *error)
Required Header stdmpi.h
Description

AxisPositionError gets the value of the position error of an Axis (axis) and puts it in the location pointed to by error. The position error is equal to (command position - actual position).

axis | a handle to the Axis object
*error | a pointer to the Axis position error returned by the method
Return Values
MPIMessageOK if AxisPositionError successfully gets and writes the value of the position error into *error
See Also | mpiAxisCommandPositionGet | mpiAxisActualPositionGet


mpiAxisStatus

Declaration
long mpiAxisStatus(MPIAxis    axis,
                   MPIStatus  *status,
                   void       *external)
Required Header stdmpi.h
Description

AxisStatus gets the status of an Axis (axis) and writes it into the structure pointed to by status.

axis | a handle to the Axis object
*status | pointer to MPIStatus structure.
*external | pointer to an external.
XMP Only

external should always be set to NULL.

Return Values
MPIMessageOK if AxisStatus successfully gets the Axis status and writes it into the structure(s)
See Also


mpiAxisTrajectory

Declaration
long mpiAxisTrajectory(MPIAxis       axis,
                       MPITrajectory *trajectory)
Required Header stdmpi.h
Description

AxisTrajectory reads the default trajectory of axis and writes it into the structure pointed to by trajectory.

axis | a handle to the Axis object.
*trajectory | pointer to the MPITrajectory structure
Remarks
The default MPITrajectory structure can be used by the mpiMotionStart(...) and mpiMotionModify() methods.
Return Values
MPIMessageOK if AxisTrajectory successfully gets the Axis trajectory and writes it into the structure
See Also | mpiMotionStart | mpiMotionModify | MPITrajectory


mpiAxisValidate

Declaration
long mpiAxisValidate(MPIAxis   axis)
Required Header stdmpi.h
Description

AxisValidate validates the Axis object and its handle (axis). AxisValidate should be called immediately after an object is created.

axis | a handle to the Axis object to be validated
Return Values
MPIMessageOK if Axis is a handle to a valid object.
See Also | mpiAxisCreate | mpiAxisDelete


Capture Objects

Capture Object

Introduction

A Capture object manages a single capture in an XMP motion controller. A capture is a hardware latch of a motor position triggered by a motor input. The XMP controller supports ten (10) Capture objects per motion block.

The default mapping for Capture objects on the first motion block is as follows:

Capture Number | Encoder
0 | 0 Motor (0)
1 | Auxiliary
2 | 1 Motor (1)
3 | Auxiliary
4 | 2 Motor (2)
5 | Auxiliary
6 | 3 Motor (3)
7 | Auxiliary
8 | Auxiliary
9 | Auxiliary
Methods
Create, Delete, Validate Methods
 | mpiCaptureCreate | Create Capture object
 | mpiCaptureDelete | Delete Capture object
 | mpiCaptureValidate | Validate Capture object
Configuration and Information Methods
 | mpiCaptureConfigGet | Get Capture configuration
 | mpiCaptureConfigSet | Set Capture configuration
 | mpiCaptureFlashConfigGet | Get flash configuration for Capture
 | mpiCaptureFlashConfigSet | Set flash configuration for Capture
 | mpiCaptureStatus | Get status of Capture
Action Methods
 | mpiCaptureArm | Arm capture object
Memory Methods
 | mpiCaptureMemory | Set address to Capture memory
 | mpiCaptureMemoryGet | Copy Capture memory to application memory
 | mpiCaptureMemorySet | Copy application memory to Capture memory
Relational Methods
 | mpiCaptureControl | Return handle of Control object associated with Adc
 | mpiCaptureNumber | Get index of Capture (for Control list)

Data Types
MPICaptureConfig / MEICaptureConfig
MPICaptureLatch
MPICaptureMessage
MPICaptureSIMConfig
MPICaptureState
MPICaptureStatus
Constants
MPICaptureLatchCountMAX


MPICaptureConfig and MEICaptureConfig

MPICaptureConfig / MEICaptureConfig

MPICaptureConfig

typedef struct MPICaptureConfig {
    MPIIoTrigger     trigger;
    long             latchCount;
    MPICaptureLatch  latch[MPICaptureLatchCountMAX];
} MPICaptureConfig;

Description
 | trigger | Type, source, mask, and pattern are used to select the capture bit and input state upon which to trigger a capture. For more information about setting the trigger please see MPIIoTrigger.
 | latchCount | The number of valid latches in latch[] array.
 | latch | Array containing capture latch register number to motor number mapping for each capture object. Latch registers are numbered sequentially across all Capture objects. This mapping is currently fixed. Performing a CaptureConfigSet will return the error message, MPIMessagePARAM_INVALID if modified by the application program.

MEICaptureConfig

typedef struct MEICaptureConfig {
    MEICaptureSIMConfig	 SIM;
} MEICaptureConfig;

Description
 | SIM | Structure that contains the Sinusoidal Interpolation Module (SIM) capture configuration. See the SIM4 hardware application note 206 for more information.

See Also | MPIIoTrigger


MPICaptureLatch

MPICaptureLatch

typedef struct MPICaptureLatch {
    long	number;
    long	motorNumber;
} MPICaptureLatch;
Description CaptureLatch is an enumeration that is explained in MPICatpureConfig.
See Also


MPICaptureLatchCountMAX

MPIObjectCaptureLatchCountMAX

#define MPICaptureLatchCountMAX (16)
    /* Maximum latches/capture */
Description CaptureLatchCountMax is an enumeration that is explained in MPICatpureConfig.
See Also


MPICaptureMessage

MPICaptureMessage

typedef enum {

    MPICaptureMessageCAPTURE_INVALID,
} MPICaptureMessage;

Description
 | MPICaptureMessageCAPTURE_INVALID | capture handle is invalid
See Also


MEICaptureSIMConfig

MEICaptureSIMConfig

typedef struct MEICaptureSIMConfig {
    long 	enable;
} MEICaptureSIMConfig;
Description

CaptureSIMConfig contains the Sinusoidal Interpolation Mode (SIM) capture configuration.

enable | TRUE for SIM capture or FALSE for non-interpolated capture.

Remarks
 | Sinusoidal Interpolation Mode (SIM) mode requires the specialized SIM4 mezzanine board for the XMP.

See Also | Please refer to the SIM4 hardware application note 206 for further information.


MPICaptureState

MPICaptureState

typedef enum {
    MPICaptureStateINVALID,
    MPICaptureStateIDLE,
    MPICaptureStateARMED,
    MPICaptureStateCAPTURED,
} MPICaptureState;

Description
 | MPICaptureStateIDLE | Not armed or captured
 | MPICaptureStateARMED | Looking for capture I/O trigger
 | MPICaptureStateCAPTURED | I/O has triggered a capture.

See Also | MPICaptureStatus


MPICaptureStatus

MPICaptureStatus

typedef struct MPICaptureStatus {
    MPICaptureState	state;
    double              latch[MPICaptureLatchCountMAX];;
} MPICaptureStatus;

Description
 | state | Contains the current state of the capture register:
 | latch | Array containing the controller's captured position value(s).
See Also


mpiCaptureArm

Declaration
long mpiCaptureArm(MPICapture  capture,
                   long        arm)
Required Header stdmpi.h
Description CaptureArm arms or disarms capture.
Value of "arm" | Action of mpiCaptureArm
FALSE | Disarms capture and sets the state of capture to MPICaptureStateIDLE
TRUE | Arms capture and sets the state of capture to MPICaptureStateARMED
Return Values
MPIMessageOK if the Capture object is successfully armed or disarmed
See Also | MPICaptureState


mpiCaptureConfigGet

Declaration
long mpiCaptureConfigGet(MPICapture       capture,
                         MPICaptureConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

CaptureConfigGet gets a Capture object’s (capture) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The a Capture object’s configuration information in external is in addition to the Capture object’s configuration information in config, i.e, the Capture object’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICaptureConfig{} or is NULL.

Return Values
MPIMessageOK if CaptureConfigGet successfully writes the Capture object’s configuration to the structure(s)
See Also | mpiCaptureConfigSet | MEICaptureConfig


mpiCaptureConfigSet

Declaration
long mpiCaptureConfigSet(MPICapture       capture,
                         MPICaptureConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

CaptureConfigSet sets a Capture object’s (capture) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Capture object’s configuration information in external is in addition to the Capture object’s configuration information in config, i.e, the Capture object’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEICaptureConfig{} or is NULL.

Return Values
MPIMessageOK if CaptureConfigSet successfully sets the Capture object’s configuration using data from the structure(s)
See Also | mpiCaptureConfigGet | MEICaptureConfig


mpiCaptureControl

Declaration
const MPIControl mpiCaptureControl(MPICapture  capture)
Required Header stdmpi.h
Description

CaptureControl returns a handle to the motion controller (Control object) that a Capture object (capture) is associated with.

Return Values
handle | to a Control object that a Capture object is associated with
MPIHandleVOID | if the Capture object is invalid
See Also


mpiCaptureCreate

Declaration
const MPICapture mpiCaptureCreate(MPIControl  control,
                                  long        number)
Required Header stdmpi.h
Description

CaptureCreate creates a Capture object associated with a number (number), that is located on a motion controller (control).

CaptureCreate is the equivalent of a C++ constructor. Each motion block supports 10 capture registers. The default configuration is two capture registers per motor, while the last two (8,9) on each motion block are reserved for the Auxiliary Encoder (not supported). The capture registers are default mapped as follows: 0 and 1 for Motor0; 2 and 3 for Motor1; 10 and 11 for Motor4; etc. The first Capture for each motor uses the default (primary) encoder input for position capture. The second uses the AUX encoder input.

Return Values
handle | to a Capture object
MPIHandleVOID | if the object could not be created

See Also | mpiCaptureDelete | mpiCaptureValidate


mpiCaptureDelete

Declaration
long mpiCaptureDelete(MPICapture  capture)
Required Header stdmpi.h
Description

CaptureDelete deletes a Capture object and invalidates its handle (capture). CaptureDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if CaptureDelete successfully deletes the Capture object and invalidates its handle
See Also | mpiCaptureCreate | mpiCaptureValidate


mpiCaptureFlashConfigGet

Declaration
long mpiCaptureFlashConfigGet(MPICapture       capture,
                              void             *flash,
                              MPICaptureConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

CaptureFlashConfigGet gets a Capture object’s (capture) flash configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Capture object’s flash configuration information in external is in addition to the Capture object’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICaptureConfig{} or is NULL.

Return Values
MPIMessageOK

if CaptureFlashConfigGet successfully writes the Capture object’s flash configuration to the structure(s)

flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.

See Also | MEIFlash | mpiCaptureFlashConfigSet | MEICaptureConfig


mpiCaptureFlashConfigSet

Declaration
long mpiCaptureFlashConfigSet(MPICapture       capture,
                              void             *flash,
                              MPICaptureConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

CaptureFlashConfigSet sets a Capture object’s (capture) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Capture object’s flash configuration information in external is in addition to the Capture object’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICaptureConfig{} or is NULL.

Return Values
MPIMessageOK if CaptureFlashConfigSet successfully sets the Capture object’s flash configuration using data from the structure(s) flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiCaptureFlashConfigGet | MEICaptureConfig


mpiCaptureMemory

Declaration
long mpiCaptureMemory(MPICapture  capture,
                      void        **memory)
Required Header stdmpi.h
Description

CaptureMemory writes an address [which is used to access a Capture object’s (capture) memory] to the contents of memory. This address, or an address calculated from it, can be passed as the src parameter to mpiCaptureMemoryGet(...) and as the dst parameter to mpiCaptureMemorySet(...).

Return Values
MPIMessageOK if CaptureMemory successfully writes the Capture object’s memory address to the contents of memory
See Also | mpiCaptureMemoryGet | mpiCaptureMemorySet


mpiCaptureMemoryGet

Declaration
long mpiCaptureMemoryGet(MPICapture  capture,
                         void        *dst,
                         void        *src,
                         long        count)
Required Header stdmpi.h
Description

CaptureMemoryGet copies count bytes of a Capture object’s (capture) memory (starting at address src) and writes them into application memory (starting at address dst).

Return Values
MPIMessageOK if CaptureMemoryGet successfully copies data from Capture memory to application memory
See Also | mpiCaptureMemory | mpiCaptureMemorySet


mpiCaptureMemorySet

Declaration
long mpiCaptureMemorySet(MPICapture capture,
                         void       *dst,
                         void       *src,
                         long       count)
Required Header stdmpi.h
Description

CaptureMemorySet copies count bytes of application memory (starting at address src) and writes them into a Capture object’s (capture) memory (starting at address dst).
Return Values
MPIMessageOK if CaptureMemorySet successfully copies count bytes of application memory to Capture memory
See Also | mpiCaptureMemory | mpiCaptureMemoryGet


mpiCaptureNumber

Declaration
long mpiCaptureNumber(MPICapture capture,
                      long       *number)
Required Header stdmpi.h
Description

CaptureNumber writes the index of a Capture object (capture, on the motion controller that capture is associated with) to the contents of number.

Return Values
MPIMessageOK if CaptureNumber successfully writes the index of a Capture object to the contents of number
See Also


mpiCaptureStatus

Declaration
long mpiCaptureStatus(MPICapture         capture,
                      MPICaptureStatus   *status,
                      void               *external)
Required Header stdmpi.h
Description

CaptureStatus writes a Capture object’s (capture) status into the structure pointed to by status, and also into the implementation-specific structure pointed to by external (if external is not NULL).

The Capture object’s status information in external is in addition to the Capture object’s status information in status, i.e, the status configuration information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICaptureStatus{} or is NULL.

Return Values
MPIMessageOK if CaptureStatus successfully writes the status of a Capture object to the structure(s)
See Also


mpiCaptureValidate

Declaration
long mpiCaptureValidate(MPICapture  capture)
Required Header stdmpi.h
Description

CaptureValidate validates the Capture object and its handle (capture).

Return Values
MPIMessageOK if Capture is a handle to a valid object.
See Also | mpiCaptureCreate | mpiCaptureDelete


Command Objects

Introduction |
 | The Command object specifies one of a variety of program Sequence commands. These include motion, conditional branch, computational, and time delay commands.
Methods
Create, Delete, Validate Methods
 | mpiCommandCreate | Create Command object
 | mpiCommandDelete | Delete Command object
 | mpiCommandValidate | Validate Command object

Configuration and Informational Methods
 | mpiCommandLabel | Get pointer to Command label
 | mpiCommandParams | Get Command parameters
 | mpiCommandType | Return Command type

Other Methods
 | mpiCommandAxisListGet | Get the axisCount and axisList from a Command object.
Data Types
MPICommandAddress
MPICommandConstant
MPICommandExpr
MPICommandMessage
MPICommandMotion
MPICommandOperator
MPICommandParams
MPICommandType


MPICommandAddress

MPICommandAddress

typedef union {
    long    *l;
    float   *f;
} MPICommandAddress;
Description

CommandAddress defines a generic pointer that can specify either a long or a float pointer.

*l | is used to access the long pointer of MPICommandAddress.
*f | is used to access the float pointer of MPICommandAddress.

See Also | MPICommandConstant


MPICommandConstant

MPICommandConstant

typedef union {
    long    l;
    float   f;
} MPICommandConstant;
Description

CommandConstant defines a generic variable that can specify either a long or float value.

l | is used to access the long value of MPICommandConstant.
f | is used to access the float value of MPICommandConstant.

See Also | MPICommandAddress


MPICommandExpr

MPICommandExpr

 typedef struct MPICommandExpr {
    MPICommandOperator	oper;
    MPICommandAddress	address;
    union {
        MPICommandConstant	value;	/* [*'address'] 'oper' ['value'] */
        MPICommandAddress	ref;	/* [*'address'] 'oper' [*'ref']  */
    } by;
} MPICommandExpr;
Description

CommandExpr is a structure that represents an expression for an MPICommand object.

The expression is evaluated as either:
 | *address oper value
 | *address oper *ref
depending on the command type.

See Also | MPICommand | MPICommandParams | MPICommandType


MPICommandMessage

MPICommandMessage

 typedef enum {
    MPICommandMessageCOMMAND_INVALID,
    MPICommandMessageTYPE_INVALID,
    MPICommandMessagePARAM_INVALID,
} MPICommandMessage;

Description
 | MPICommandMessageCOMMAND_INVALID | is currently not supported and is reserved for future use.
 | MPICommandMessageTYPE_INVALID | The MPICommandType passed to the mpiCommandCreate method is invalid.

See Also | MPICommandType


MPICommandMotion

MPICommandMotion

typedef enum {
    MPICommandMotionINVALID,

    MPICommandMotionABORT,
    MPICommandMotionE_STOP,
    MPICommandMotionE_STOP_ABORT,
    MPICommandMotionMODIFY,
    MPICommandMotionRESET,
    MPICommandMotionRESUME,
    MPICommandMotionSTART,
    MPICommandMotionSTOP,
} MPICommandMotion;
Description

CommandMotion specifies what type of motion action a motion MPICommand object will perform. Please refer to MPIAction for more information on particular actions.

MPICommandMotionABORT | Commands an ABORT action.
MPICommandMotionE_STOP | Commands an E-STOP action.
MPICommandMotionE_STOP_ABORT | Commands an E-STOP_ABORT action.
MPICommandMotionMODIFY | Modifies a particular motion profile. This is currently not supported and is reserved for future use.
MPICommandMotionRESET | Commands an Reset action.
MPICommandMotionRESUME | Commands an Resume action.
MPICommandMotionSTART | Starts a motion profile.
MPICommandMotionSTOP | Commands an STOP action.

See Also | MPIAction | MPICommand | MPICommandParams


MPICommandOperator

MPICommandOperator

 typedef enum {
    MPICommandOperatorINVALID,

    /* Arithmetic operators */
    MPICommandOperatorADD,
    MPICommandOperatorSUBTRACT,
    MPICommandOperatorMULTIPLY,
    MPICommandOperatorDIVIDE,

    MPICommandOperatorAND,
    MPICommandOperatorOR,
    MPICommandOperatorXOR,

    /* Logical operators */
    MPICommandOperatorALWAYS,

    MPICommandOperatorEQUAL,
    MPICommandOperatorNOT_EQUAL,

    MPICommandOperatorGREATER_OR_EQUAL,
    MPICommandOperatorGREATER,

    MPICommandOperatorLESS_OR_EQUAL,
    MPICommandOperatorLESS,

    MPICommandOperatorBIT_CLEAR,
    MPICommandOperatorBIT_SET,
} MPICommandOperator;
Description

The following are operators used by the MPICommand and MPICompare objects.

Arithmetic Operators
MPICommandOperatorADD | Performs an addition. Equivalent to the C operator (+).
MPICommandOperatorSUBTRACT | Performs a subtraction. Equivalent to the C operator (-).
MPICommandOperatorMULTIPLY | Performs a multiplication. Equivalent to the C operator (*).
MPICommandOperatorDIVIDE | Performs a divison. Equivalent to the C operator (/).
MPICommandOperatorAND | Performs a logical AND. Equivalent to the C operator (&).
MPICommandOperatorOR | Performs a logical OR. Equivalent to the C operator ( | ).
MPICommandOperatorXOR | Performs a logical XOR. Equivalent to the C operator (^).

Logical Operators
MPICommandOperatorALWAYS | Always evaluates TRUE. Equivalent in C to (1) or TRUE.
MPICommandOperatorEQUAL | Performs an equality comparison. Equivalent to the C operator (= =)
MPICommandOperatorGREATER_OR_EQUAL | Performs an inequality comparison. Equivalent to the C operator (!=)
MPICommandOperatorGREATER_OR_EQUAL | Performs a greater than or equal to comparison. Equivalent to the C operator (>=)
MPICommandOperatorGREATER | Performs a greater than comparison. Equivalent to the C operator (>)
MPICommandOperatorLESS_OR_EQUAL | Performs a less than or equal to comparison. Equivalent to the C operator (< =)
MPICommandOperatorLESS | Performs a less than comparison. Equivalent to the C operator (<)
MPICommandOperatorBIT_CLEAR | Clears specified bits. Equivalent in C to the statement: variable &= ~(bits)
MPICommandOperatorBIT_SET | Sets specified bits. Equivalent in C to the statement: variable | = (bits)

See Also | MPICommand | MPICommandExpr | MPICommandParams | MPIComparePosition | MPICompareParams


MPICommandParams

MPICommandParams

typedef union {
    struct {	/* *'dst' = 'value' */
        MPICommandAddress	dst;
        MPICommandConstant	value;
        MPIControl		control;	/* Ignored by Sequence */
    } assign;

    struct {	/* branch to 'label' on 'expr' */
        char		*label;		/* NULL => stop sequence */
        MPICommandExpr	expr;		/* expr.oper => MPICommandOperatorLogical */
        MPIControl	control;	/* Ignored by Sequence */
    } branch;

    struct {	/* branch to 'label' on MPIEventMask('handle') 'oper' 'mask' */
        char			*label;		/* NULL => stop sequence */
        MPIHandle		handle;		/* [MPIMotor|MPIMotion|...] */
        MPICommandOperator	oper;		/* EQUAL/NOT_EQUAL/BIT_CLEAR/BIT_SET */
        MPIEventMask		mask;		/* MPIEventMask('handle') 'oper' 'mask' */
    } branchEvent;

    struct {	/* branch to 'label' on Io.input 'oper' 'mask' */
        char			*label;		/* NULL => stop sequence */
        MPIIoType		type;		/* MOTOR,   USER */
        MPIIoSource		source;		/* MPIMotor	index */
        MPICommandOperator	oper;		/* EQUAL/NOT_EQUAL/BIT_CLEAR/BIT_SET */
        long			mask;		/* [motor|user]Io.input 'oper' 'mask' */
    } branchIO;

    struct {	/* *'dst' = 'expr' */
        MPICommandAddress	dst;
        MPICommandExpr		expr;		/* expr.oper => MPICommandOperatorArithmetic */
        MPIControl		control;	/* Ignored by Sequence */
    } compute;

    struct {	/* Io.output = Io.output 'oper' 'mask' */
    MPIIoType			type;		/* MOTOR,   USER */
        MPIIoSource		source;		/* MPIMotor	index */
        MPICommandOperator	oper;		/* AND/OR/XOR */
        long	mask;
    } computeIO;

    struct {	/* memcpy(dst, src, count) */
        void		*dst;
        void		*src;
        long		count;
        MPIControlcontrol;	/* Ignored by Sequence */
    } copy;

    float	delay;	/* seconds */

    struct {
        long		value;	/* MPIEventStatus.type    = MPIEventTypeEXTERNAL */
                /*		 .source  = MPISequence/MPIProgram */
                /*		 .info[0] = value */
        MPIEventMgr	eventMgr;	/* Ignored by Sequence */
    } event;

    struct {	/* mpiMotion[Abort|EStop|Reset|Resume|Start|Stop](motion[, type, params]) */
        MPICommandMotion	motionCommand;
        MPIMotion		motion;
        MPIMotionType		type;	/* MPICommandMotionSTART */
        MPIMotionParams		params;	/* MPICommandMotionSTART */
    } motion;

    struct {	/* wait until 'expr' */
        MPICommandExpr		expr;	/* expr.oper => MPICommandOperatorLogical */
        MPIControl		control;/* Ignored by Sequence */
    } wait;

    struct {	/* wait until MPIEventMask('handle') 'oper' 'mask' */
        MPIHandle		handle;	/* [MPIMotor|MPIMotion|...] */
        MPICommandOperator	oper;	/* EQUAL/NOT_EQUAL/BIT_CLEAR/BIT_SET */
        MPIEventMask		mask;	/* MPIEventMask('handle') 'oper' 'mask' */
    } waitEvent;

    struct {	/* wait until Io.input 'oper' 'mask' */
        MPIIoType		type;	/* MOTOR,   USER */
        MPIIoSource		source;	/* MPIMotor	index */
        MPICommandOperator	oper;	/* EQUAL/NOT_EQUAL/BIT_CLEAR/BIT_SET */
        long			mask;	/* [motor|user]Io.input 'oper' 'mask' */
    } waitIO;
} MPICommandParams;

Description
 | assign | Assign a value to a particular controller address: *dst = value assign.control is currently not supported and is reserved for future use.
 | branch | Branch to a particular command (similar to a goto statement) if a particular comparison evaluates to TRUE: branch to label on expr If label = NULL, then no more commands will be executed if the comparison evaluates to TRUE. branch.control is currently not supported and is reserved for future use.
 | branchEvent | Branch to a particular command (similar to a goto statement) if a particular event occurs or has occured: branch to label on MPIEventMask(handle) oper mask If label = NULL, then no more commands will be executed if a particular event occurs or has occured.
 | branchIO | Branch to a particular command (similar to a goto statement) if a particular i/o state matches a specified condition: branch to label on Io.input oper mask If label = NULL, then no more commands will be executed if a particular i/o state matches a specified condition.
 | compute | perform some computation and place the result at some controller address: *dst = expr compute.control is currently not supported and is reserved for future use.
 | computeIO | Performs a computation on a set of i/o bits: Io.output = Io.output oper mask
 | copy | Copies controller memory from one place to another: memcpy(dst, src, count); Remember: count represents the number of bytes copied, NOT the number of controller words. event.control is currently not supported and is reserved for future use.
 | delay | Delays execution of the next command delay seconds.
 | event | Generates an event: MPIEventStatus.type = MPIEventTypeEXTERNAL MPIEventStatus.source = MPISequence MPIEventStatus.info[0] = value event.eventMgr is currently not supported and is reserved for future use.
 | motion | Commands a motion action (See MPICommandMotion): mpiMotionStart (motion, type, params]); or mpiMotionAction(motion, MPIAction[ABORT | E_STOP | E_STOP_ABORT | RESET | RESUME | STOP]);
 | wait | Delays execution of the next command until a particular comparison evaluates to TRUE: wait until expr wait.control is currently not supported and is reserved for future use.
 | waitEvent | Delays execution of the next command until a particular event occurs: wait until MPIEventMask(handle) oper mask
 | waitIO | Delays execution of the next command until a particular i/o state matches a specified condition: wait until Io.input oper mask

See Also | MPICommand | MPICommandType | mpiCommandCreate | mpiCommandParams


MPICommandType

MPICommandType

typedef enum {
    MPICommandTypeASSIGN,
    MPICommandTypeASSIGN_FLOAT,

    MPICommandTypeBRANCH,
    MPICommandTypeBRANCH_REF,
    MPICommandTypeBRANCH_FLOAT,
    MPICommandTypeBRANCH_FLOAT_REF,
    MPICommandTypeBRANCH_EVENT,
    MPICommandTypeBRANCH_IO,

    MPICommandTypeCOMPUTE,
    MPICommandTypeCOMPUTE_REF,
    MPICommandTypeCOMPUTE_FLOAT,
    MPICommandTypeCOMPUTE_FLOAT_REF,
    MPICommandTypeCOMPUTE_IO,

    MPICommandTypeCOPY,

    MPICommandTypeDELAY,

    MPICommandTypeEVENT,

    MPICommandTypeMOTION,

    MPICommandTypeWAIT,
    MPICommandTypeWAIT_REF,
    MPICommandTypeWAIT_FLOAT,
    MPICommandTypeWAIT_FLOAT_REF,
    MPICommandTypeWAIT_EVENT,
    MPICommandTypeWAIT_IO,
} MPICommandType;

Description
 | MPICommandTypeASSIGN |
 | MPICommandTypeASSIGN_FLOAT | These commands assign a value to a particular controller address. MPICommandTypeASSIGN assigns a long value while MPICommandTypeASSIGN_FLOAT assigns a float value.
 | MPICommandTypeBRANCH | These commands branch to a particular command (similar to a goto statement) if a particular comparison evaluates to TRUE. MPICommandTypeBRANCH compares a controller address to a specified constant long value. MPICommandTypeBRANCH_REF Compares a controller address to a long value at a specified controller address.
 | MPICommandTypeBRANCH_FLOAT | Compares a controller address to a specified constant float value.
 | MPICommandTypeBRANCH_FLOAT_REF | Compares a controller address to a float value at a specified controller address.
 | MPICommandTypeBRANCH_EVENT | Branch to a particular command (similar to a goto statement) if a particular event occurs or has occured.
 | MPICommandTypeBRANCH_IO | Branch to a particular command (similar to a goto statement) if a particular i/o state matches a specified condition.
 | MPICommandTypeCOMPUTE | These commands perform some computation and place the result at some controller address.. MPICommandTypeCOMPUTE performs a computation of some controller address and a constant long value.
 | MPICommandTypeCOMPUTE_REF | Performs a computation of some controller address and a long value at a specified controller address.
 | MPICommandTypeCOMPUTE_FLOAT | Performs a computation of some controller address and a constant float value.
 | MPICommandTypeCOMPUTE_FLOAT_REF | Performs a computation of some controller address and a float value at a specified controller address.
 | MPICommandTypeCOMPUTE_IO | Performs a computation on a set of i/o bits.
 | MPICommandTypeCOPY | Copies controller memory from one place to another.
 | MPICommandTypeDELAY | Delays execution of the next command.
 | MPICommandTypeEVENT | Generate an event.
 | MPICommandTypeMOTION | Commands a motion action. See MPICommandMotion.
 | MPICommandTypeWAIT | These delays execution of the next command until a particular comparison evaluates to TRUE. MPICommandTypeWAIT compares a controller address to a specified constant long value. MPICommandTypeWAIT_REF Compares a controller address to a long value at a specified controller address.
 | MPICommandTypeWAIT_FLOAT | Compares a controller address to a specified constant float value.
 | MPICommandTypeWAIT_FLOAT_REF | Compares a controller address to a float value at a specified controller address.
 | MPICommandTypeWAIT_EVENT | Delays execution of the next command until a particular event occurs.
 | MPICommandTypeWAIT_IO | Delays execution of the next command until a particular i/o state matches a specified condition.

See Also | MPICommand | MPICommandMotion | MPICommandParams | mpiCommandCreate | mpiCommandType


meiCommandAxisListGet

Declaration
long meiCommandAxisListGet(MPICommand  command,
                           long        *axisCount
                           MPIAxis     *axisList)
Required Header stdmpi.h
Description

CommandAxisListGet reads number of axes and the list of axes associated with a motion type Command object (command) and writes them into the long pointed to by axisCount and the array of axis objects pointed to by axisList.

command | a handle to the Command object
*axisCount | a pointer to a long, representing the number of axes returned by the method
*axisList | a pointer to an array of axis objects returned by the method
Return Values
MPIMessageOK if CommandAxisListGet successfully gets the axisCount and axisList from a Command object.
See Also | MPICommand | MPIAxis | MPIMotion


mpiCommandCreate

Declaration
const MPICommand mpiCommandCreate(MPICommandType   type,
                                  MPICommandParams *params,
                                  const char       *label)
Required Header stdmpi.h
Description

CommandCreate creates a Command object. The command type is specified by type. The type-specific parameters are specified by params. If label is not Null (i.e., something meaningful), then branch commands can call this Command (by using the label). CommandCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Command object
MPIHandleVOID | if the object could not be created

See Also | mpiCommandDelete | mpiCommandValidate


mpiCommandDelete

Declaration
long mpiCommandDelete(MPICommand  command)
Required Header stdmpi.h
Description

CommandDelete deletes a Command object and invalidates its handle (command). CommandDelete is the equivalent of a C++ destructor.

Return Values
MPIMessageOK if CommandDelete successfully deletes the Command object and invalidates its handle
See Also | mpiCommandCreate | mpiCommandValidate


mpiCommandLabel

Declaration
long mpiCommandLabel(MPICommand  command,
                     char        **label)
Required Header stdmpi.h
Description

CommandLabel gets the string from a Command and puts it in the location pointed to by label.

command | a handle to the Command object
**label | a pointer to a string returned by the method

Return Values
pointer | to a Command’s (command) label (that is in the location pointed to by label)
MPIMessageOK | if CommandLabel successfully returns a pointer to the Command’s label that is in the location pointed to by **label

See Also | mpiCommandCreate


mpiCommandParams

Declaration
long mpiCommandParams (MPICommand       command,
                       MPICommandParams *params)
Required Header stdmpi.h
Description

CommandParams gets the parameters from a Command and puts it in the location pointed to by params.

command | a handle to the Command object
*params | a pointer to a MPICommandParams structure returned by the method

Return Values
Command (command) parameters | in the structure pointed to by params
MPIMessageOK | if CommandParams successfully gets and writes the command parameters into *params

See Also | mpiCommandCreate | MPICommandParams


mpiCommandType

Declaration
long mpiCommandType(MPICommand      command,
                    MPICommandType  *type)
Required Header stdmpi.h
Description

CommandType gets the type from a Command and puts it in the location pointed to by type.

command | a handle to the Command object
*type | a pointer to a MPICommandType returned by the method

Return Values
Command (command) parameters | in the location pointed to by type
MPIMessageOK | if CommandType successfully gets and writes the command type into *type

See Also | mpiCommandCreate | MPICommandType


mpiCommandValidate

Declaration
long mpiCommandValidate(MPICommand  command)
Required Header stdmpi.h
Description

CommandValidate validates the Command object and its handle (command).

Return Values
MPIMessageOK if the Command object and its handle are valid
See Also | mpiCommandCreate | mpiCommandValidate


Compare Objects

Introduction

A Compare object manages a compare engine in the motion controller hardware. The compare engine compares the actual position feedback from a motor to a preloaded position value. When the actual position feedback exceeds the value, the compare engine sets an output bit to the specified state. Since the compare occurs in hardware, the latency is minimal.

Typically, the MPI is used to configure the compare engine, load the compare value, and arm the compare. The condition of the compare engine can be determined by reading its status.
Methods
Create, Delete, Validate Methods
 | mpiCompareCreate | Create Compare object
 | mpiCompareDelete | Delete Compare object
 | mpiCompareValidate | Validate Compare object

Configuration and Information Methods
 | mpiCompareConfigGet | Get Compare configuration
 | mpiCompareConfigSet | Set Compare configuration
 | mpiCompareFlashConfigGet | Get flash configuration for Compare
 | mpiCompareFlashConfigSet | Set flash configuration for Compare
 | mpiCompareStatus | Get Compare's status

Memory Methods
 | mpiCompareMemory | Set Compare memory address
 | mpiCompareMemoryGet | Copy bytes of Compare memory to application memory
 | mpiCompareMemorySet | Copy bytes of application memory to Compare memory

Action Methods
 | mpiCompareArm | Arm Compare object
 | mpiCompareLoad |
Relational Methods
 | mpiCompareControl | Return handle of Control that is assoiciated with Compare
 | mpiCompareNumber | Get index of Compare (for Control list)
Data Types
MPICompareConfig / MEICompareConfig
MPICompareMessage
MPICompareParams
MPIComparePosition
MPICompareState
MPICompareStatus
Constants
MPIComparePositionCountMAX


MPICompareConfig and MEICompareConfig

MPICompareConfig / MEICompareConfig

MPICompareConfig

typedef struct MPICompareConfig {
    MPIIoTrigger    trigger;    /* which output to use... */
} MPICompareConfig;
Description
trigger type, source, mask, and pattern used to select the state of the compare output bit upon reaching the compare position. For more information about setting the trigger please see MPIIoTrigger.

MEICompareConfig

typedef struct MEICompareConfig {
    long                    continuous;
    MEICompareDivByNConfig  divByN;
} MEICompareConfig;
Description

Event compare mode (default) uses a handshake to ensure hardware/software synchronization. A single rising edge and single falling edge on the compare output is guaranteed. This mode is useful when re-arming compare objects is required for multiple compare position. There is system overhead to re-arm compare events.

Continuous compare mode constantly compares the compare position register to the position counter. The compare output is toggled based on compare logic, without software system notification and without the need to re-arm. This mode is useful when a single compare position is required for a valid compare output whenever the position is past some limit. If the position feedback during a move is not monotonic at the compare value (jitters back and forth), the compare output will change state each time the position crosses the compare value.

See Also | MPIIoTrigger | mpiCompareConfigGet | mpiCompareConfigSet


MPICompareMessage

MPICompareMessage

typedef enum {
    MPICompareMessageCOMPARE_INVALID,
} MPICompareMessage;

Description
 | MPICompareMessageCOMPARE_INVALID | compare handle is invalid
See Also


MPICompareParams

MPICompareParams

typedef struct MPICompareParams {
    long		position;
    long		outputState;
    MPICommandOperator	commandOperator;
} MPICompareParams;

Description
 | position | actual position at which to toggle output bit.
 | outputState | state of output bit upon reaching the compare position. Set to TRUE (on) or FALSE (off).
 | commandOperator | logical operator for compare position.
Remarks

Valid values for commandOperator are MPICommandOperatorLESS_OR_EQUAL and
MPICommandOperatorGREATER. Based on the commandOperator, the specified outputState of the bit will be set on one side or the other of the compare position.

The commandOperator logic is usually set depending on the direction of travel toward the compare position.

See Also


MPIComparePosition

MPIComparePosition

typedef struct MPIComparePosition {
    long                number;
    long                motorNumber;
    long                position;
    MPICommandOperator  commandOperator;
} MPIComparePosition;

Description - This structure is currently not supported and is reserved for future use.
 | number | capture number
 | motorNumber | number of the motor whose position to compare
 | position | compare position on which to set the output bit
 | commandOperator | logical operator for the compare position
See Also


MPIComparePositionCountMAX

Declaration
#define MPIComparePositionCountMAX (10)
/* Maximum latches/compare */
Required Header stdmpi.h
Description

See MPICompareStatus for a description.
See Also


MPICompareState

MPICompareState

typedef enum {
    MPICompareStateINVALID,

    MPICompareStateIDLE,
    MPICompareStateARMED,
    MPICompareStateCOMPARED,
} MPICompareState;

Description
 | MPICompareStateIDLE | Not armed or compared
 | MPICompareStateARMED | Looking for compare position(s)
 | MPICompareStateCOMPARED | Compare position found

See Also | MPICompareStatus


MPICompareStatus

MPICompareStatus

#define MPIComparePositionCountMAX (10)  /* Maximum latches/compare */

typedef enum {
    MPICompareStateINVALID,

    MPICompareStateIDLE,
    MPICompareStateARMED,
    MPICompareStateCOMPARED,
} MPICompareState;

typedef struct MPICompareStatus {
    MPICompareState	state;
    double		position[MPIComparePositionCountMAX];
} MPICompareStatus;

Description
 | State- contains the current state of the compare register:
 |  | Idle | Not armed or compared
 |  | Armed | Looking for compare position(s)
 |  | Compared | Compare position found
 | Position- array containing the controller's compared position value(s).

See Also | MPICompareState


mpiCompareArm

Declaration
long mpiCompareArm(MPICompare  compare,
                   long        arm)
Required Header stdmpi.h
Description

CompareArm sets the MPICompareState to MPICompareStateIDLE (arm = FALSE), or MPICompareStateARMED (arm = TRUE).

Return Values
MPIMessageOK if the Compare object is successfully armed or disarmed.
See Also | MPICompareState


mpiCompareConfigGet

Declaration
long mpiCompareConfigGet(MPICompare       compare,
                         MPICompareConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

CompareConfigGet gets a Compare object’s (compare) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The a Compare object’s configuration information in external is in addition to the Compare object’s configuration information in config, i.e, the Compare object’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICompareConfig{} or is NULL.

Return Values
MPIMessageOK if CompareConfigGet successfully writes the Compare object’s configuration to the structure(s)
See Also | mpiCompareConfigSet | MEICompareConfig


mpiCompareConfigSet

Declaration
long mpiCompareConfigSet(MPICompare       compare,
                         MPICompareConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

CompareConfigSet sets a Compare object’s (compare) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Compare object’s configuration information in external is in addition to the Compare object’s configuration information in config, i.e, the Compare object’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEICompareConfig{} or is NULL.

Return Values
MPIMessageOK if CompareConfigSet successfully sets the Compare object’s configuration using data from the structure(s)
See Also | mpiCompareConfigGet | MEICompareConfig


mpiCompareControl

Declaration
const MPIControl  mpiCompareControl(MPICompare compare)
Required Header stdmpi.h
Description

CompareControl returns a handle to the motion controller (Control object) that a Compare object (compare) is associated with.

Return Values
handle | to a Control object that a Compare object is associated with
MPIHandleVOID | if the Compare object is invalid
See Also


mpiCompareCreate

Declaration
const MPICompare mpiCompareCreate(MPIControl   control,
                                  long         number)
Required Header stdmpi.h
Description

CompareCreate creates a Compare object associated with a number (number), that is located on a motion controller (control).

CompareCreate is the equivalent of a C++ constructor. Each motion block supports 10 compare registers. The default configuration is two compare registers per motor, while the last two (8,9) on each motion block are reserved for the Auxiliary Encoder (not supported). The compare registers are default mapped as follows: 0 and 1 for Motor0; 2 and 3 for Motor1; 10 and 11 for Motor4; etc. The first Compare for each motor uses the default (primary) encoder input for position compare. The second uses the AUX encoder input.

Return Values
handle | to a Compare object
MPIHandleVOID | if the object could not be created

See Also | mpiCompareCreate | mpiCommandValidate


mpiCompareDelete

Declaration
long mpiCompareDelete(MPICompare  compare)
Required Header stdmpi.h
Description

CompareDelete deletes a Compare object and invalidates its handle (compare). CompareDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if CompareDelete successfully deletes the Compare object and invalidates its handle
See Also | mpiCommandCreate | mpiCommandValidate


mpiCompareFlashConfigGet

Declaration
long mpiCompareFlashConfigGet(MPICompare       compare,
                              void             *flash,
                              MPICompareConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

CompareFlashConfigGet gets a Compare object’s (compare) flash configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Compare object’s flash configuration information in external is in addition to the Compare object’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICompareConfig{} or is NULL.

Return Values
MPIMessageOK if CompareFlashConfigGet successfully writes the Compare object’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiCompareFlashConfigSet | MEICompareConfig


mpiCompareFlashConfigSet

Declaration
long mpiCompareFlashConfigSet(MPICompare       compare,
                              void             *flash,
                              MPICompareConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

CompareFlashConfigSet sets a Compare object’s (compare) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Compare object’s flash configuration information in external is in addition to the Compare object’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEICompareConfig{} or is NULL.

Return Values
MPIMessageOK if CompareFlashConfigSet successfully sets the Compare object’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiCompareFlashConfigGet | MEICompareConfig


mpiCompareLoad

Declaration
long mpiCompareLoad(MPICompare       compare,
                    MPICompareParams *params,
                    void             *external)
Required Header stdmpi.h
Description

CompareLoad loads a Compare object’s (compare) parameters using data from the structure pointed to by params, and also using data from the implementation-specific structure.

Return Values
MPIMessageOK if CompareLoad successfully loads the Compare object's parameters using the data from the structure.
See Also


mpiCompareMemory

Declaration
long mpiCompareMemory(MPICompare   compare,
                      void         **memory)
Required Header stdmpi.h
Description

CompareMemory writes an address [which is used to access a Compare object’s (compare) memory] to the contents of memory. This address, or an address calculated from it, can be passed as the src parameter to mpiCompareMemoryGet(...) and as the dst parameter to mpiCompareMemorySet(...).

Return Values
MPIMessageOK if CompareMemory successfully writes the Compare object’s memory address to the contents of memory
See Also | mpiCompareMemoryGet | mpi CompareMemorySet


mpiCompareMemoryGet

Declaration
long mpiCompareMemoryGet(MPICompare  compare,
                         void        *dst,
                         void        *src,
                         long        count)
Required Header stdmpi.h
Description

CompareMemoryGet copies count bytes of a Compare object’s (compare) memory (starting at address src) and writes them into application memory (starting at address dst).

Return Values
MPIMessageOK if CompareMemoryGet successfully copies data from Compare memory to application memory
See Also | mpiCompareMemorySet | mpiCompareMemory


mpiCompareMemorySet

Declaration
long mpiCompareMemorySet(MPICompare  compare,
                         void        *dst,
                         void        *src,
                         long        count)
Required Header stdmpi.h
Description

CompareMemorySet copies count bytes of application memory (starting at address src) and writes them into a Compare object’s (compare) memory (starting at address dst).

Return Values
MPIMessageOK if CompareMemoryGet successfully copies data from application memory to Compare memory
See Also | mpiCompareMemoryGet | mpiCompareMemory


mpiCompareNumber

Declaration
long mpiCompareNumber(MPICompare   compare,
                      long         *number)
Required Header stdmpi.h
Description

CompareNumber writes the index of a Compare object (compare, on the motion controller that compare is associated with) to the contents of number.

Return Values
MPIMessageOK if CompareNumber successfully writes the index of a Compare object to the contents of number
See Also


mpiCompareStatus

Declaration
long mpiCompareStatus(MPICompare        compare,
                      MPICompareStatus  *status,
                      void              *external)
Required Header stdmpi.h
Description

CompareStatus writes a Compare object’s (compare) status into the structure pointed to by status, and also into the implementation-specific structure pointed to by external (if external is not NULL).

The Compare object’s status information in external is in addition to the Compare object’s status information in status, i.e, the status configuration information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEICompareStatus{} or is NULL.

Return Values
MPIMessageOK if CompareStatus successfully writes the status of a Compare object to the structure(s)
See Also


mpiCompareValidate

Declaration
long mpiCompareValidate(MPICompare  compare)
Required Header compare.h
Description

CompareValidate validates the Compare object and its handle (compare).

Return Values
MPIMessageOK if Compare is a handle to a valid object.
See Also | mpiCompareCreate | mpiCompareDelete


Control Objects

Introduction

A Control object manages a motion controller device. The device is typically a single board residing in a PC or an embedded system. A control object can read and write device memory through one of a variety of methods: I/O port, memory mapped or device driver.

For the case where the application and the motion controller device exist on two physically separate platforms connected by a LAN or serial line, the application creates a client control object which communicates via remote procedure calls with a server.

Unlike the methods of all other objects in the MPI, Control object methods are not thread-safe.

Are you using TCP/IP and Sockets? If yes, click here.
Methods
Create, Delete, Validate Methods
 | mpiControlCreate | Create Control object
 | mpiControlDelete | Delete Control object
 | mpiControlValidate | Validate Control object

Configuration and Information Methods
 | mpiControlAddress | Get original address of Control object (when it was created)
 | mpiControlConfigGet | Get Control config
 | mpiControlConfigSet | Set Control config
 | meiControlExtMemAvail |
 | mpiControlFlashConfigGet | Get Control flash config
 | mpiControlFlashConfigSet | Set Control flash config
 | meiControlGateGet | Get the closed state (TRUE or FALSE)
 | meiControlGateSet | Set the closed state (TRUE or FALSE)
 | meiControlSampleCounter |
 | meiControlSamplestoSeconds | Converts samples to seconds
 | meiControlSecondstoSamples | Converts seconds to samples
 | mpiControlType | Get type of Control object (used to create Command object)
 | meiControlVersionGet | Read the version of XMP firmware
 | meiControlVersionSet | Write the version of XMP firmware

Memory Methods
 | mpiControlMemory | Get address of Control memory
 | mpiControlMemoryAlloc | Allocate bytes of firmware memory
 | mpiControlMemoryCount | Get number of bytes available in firmware
 | mpiControlMemoryFree | Free bytes of firmware memory
 | mpiControlMemoryGet | Copy count bytes of Control memory to application memory
 | mpiControlMemorySet | Copy count bytes of application memory to Control memory

Action Methods
 | mpiControlCycleWait | Wait for Control to execute count cycles
 | mpiControlInit | Initialize Control object
 | mpiControlInterruptEnable | Enable interrupts to Control object
 | mpiControlInterruptWait | Wait for controller interrupt
 | mpiControlInterruptWake | Wake all threads waiting for controller interrupt
 | mpiControlReset | Reset controller hardware
 | meiControlSampleWait | Specify how many samples the host waits for, while the XMP executes

Relational Methods
 | meiControlPlatform
Data Types
MPIControlAddress
MPIControlConfig / MEIControlConfig
MPIControlIo
MEIControlInput
MPIControlMessage / MEIControlMessage
MEIControlOutput
MPIControlType
MEIControlVersion


 Dynamic Allocation of External Memory Buffers

In previous versions, the XMP external memory was statically allocated at firmware compile time.

In version 20010119 and later, specific buffers of the XMP external memory are dynamically allocated. The dynamic allocation feature allows an application to efficiently use the XMP controller's on-board memory and allows for future expansion. The dynamically allocated buffers currently include the Frame Buffer, Record Buffer, and SERCOS buffer. Each of these buffers sizes are recalculated during a call to mpiControlConfigSet(...) if there is a change in any of the associated ControlConfig values.

The Frame Buffer is used for motion on each axis. The Frame Buffer is directly associated with the number of EnabledAxes in the MPIControlConfig structure. The Frame Buffer will be allocated to the minimum size required to support the number of enabled axes. The default number of EnabledAxes is eight (8).

The Record Buffer is used for the on-board data recorder. The Record Buffer is directly associated with the number of EnabledRecord in the MPIControlConfig structure. The Record Buffer will be allocated to the minimum size required to support the number of enabled records. The default number of EnabledRecords is 3064. Each record is the size of one memory word.

The Sercos Buffer is used for motion on each SERCOS ring network. The Sercos Buffer is directly associated with the number of EnabledSercos in the MPIControlConfig structure. The Sercos Buffer will be allocated to the minimum size required to support the number of enabled Sercos rings. The default number of EnabledSercosRings, for a non-sercos controller is zero (0).

The meiControlExtMemAvail(...) method has been added to discover how much memory is available on your controller.

MPI_DEF1 long MPI_DEF2
     meiControlExtMemAvail(MPIControl  control,
                           long        *size)

The meiControlExtMemAvail(...) method will return the number of memory words available. Since each record size is one memory word, the size returned from the above function can be used to increase the Record Buffer to maximum size possible. This greatly improves client/server operation of Motion Scope and any application used for data collection.

WARNING! Due to the nature of dynamic allocation and the clearing of external memory buffers mpiControlConfigSet(...) should ONLY be called at motion application initialization time and NOT during motion.

Return to Control Objects page


 TCP/IP and Sockets for Control Objects

The MPI implements network functionality as client/server. The xmp\util\server.c program implements a basic server. You just create a Control object of type MPIControlTypeCLIENT and specify the server's host in the MPIControlAddress{}.client{} structure.

You can try “MPI networking” on a single machine by starting up the server program in a DOS window, and then running a sample application in another DOS window. Note that you can specify the host name and port of the server as command line arguments to all sample applications and utilities.

The way the MPI client/server works internally is that low-level mpiControlMemory and mpiControlInterrupt methods are intercepted just before they read/write XMP memory. The methods are packaged up as remote procedure calls and sent to the server for execution. The server sends the results back to the client.

There are 2 channels of communication - one channel to wait for interrupts, and another channel to do everything else. All MPI methods that communicate with the XMP do so by calling (eventually) the low level mpiControlMemory methods, so no application code needs to be changed other than the initial call to mpiControlCreate(...). This is all implemented on WinNT using WinSock.

Note that it would be possible to implement the client/server scenario above using an RS-232 line rather than TCP/IP WinSock. The MPI’s client/server protocol only requires a reliable transport mechanism (WinSock, RS-232) between a client and server.

Return to Control Objects page


MPIControlAddress

MPIControlAddress

typedef struct MPIControlAddress {
    long	number;	/* controller number */

    union {
        void		  *mapped;	/* memory address */
        unsigned long	  ioPort;	/* I/O port number */
        char		  *device;   	/* device driver name */
        struct {
            char		*name;	/* image file name */
            MPIControlFileType   type;	/* image file type */
        } file;
        struct {
            char	*server;	/* IP address: host.domain.com */
            long	port;	   	/* socket number */
        } client;
    } type;
} MPIControlAddress;
Description

ControlAddress is a structure that specifies the location of the controller that to be accessed when mpiControlCreate() is called. Please refer to the documentation for mpiControlCreate() to see how to use this structure.

number | The controller number in the computer
type | A union that holds information about controllers on non-local computers.
See Also


MPIControlConfig and MEIControlConfig

MPIControlConfig / MEIControlConfig

MPIControlConfig

typedef struct MPIControlConfig {
    long	adcCount;
    long	axisCount;
    long	captureCount;
    long	compareCount;
    long	cmdDacCount;
    long	auxDacCount;
    long	filterCount;
    long	motionCount;
    long	motorCount;
    long	recordCount;
    long	sequenceCount;
    long	sercosCount;
    long	userVersion;
    long	sampleRate;

} MPIControlConfig;

Description
 | adcCount | represents the number of ADC(analog to digital converter) objects configured for the controller.
 | axisCount | represents the number of axis objects configured for the controller.
 | captureCount | represents the number of capture objects to be configured for the controller. A capture object manages a single capture in an XMP motion controller. A capture is a hardware latch of a motor position triggered by a motor input. The XMP controller supports ten (10) capture objects per motion block. The default configuration is two capture registers per motor, while the last two (8,9) on each motion block are reserved for the auxiliary encoder (not supported).
 | compareCount | represents the number of compare objects to be configured for the controller. The XMP controller supports ten (10) compare objects per motion block. The default configuration is two compare registers per motor, while the last two (8,9) on each motion block are reserved for the auxiliary encoder (not supported).
 | cmdDacCount | represents the number of DAC(digital to analog converter) objects to be configured for the controller. There is one DAC per motor and one auxiliary DAC per motor.
 | auxDacCount | represents the number of Auxiliary DAC objects to be configured for the controller. There is one DAC per motor and one auxiliary DAC per motor.
 | filterCount | represents the number of filter objects to be configured for the controller.
 | motionCount | represents the number of motion supervisor objects to be configured for the controller.
 | motorCount | represents the number of motor objects to be configured for the controller.
 | recordCount | represents the number of recorder objects to be configured for the controller. This element allows the application to change the size of the recorder object's data buffer using the mpiControlConfigGet/Set(...) methods. A larger data buffer size can improve the performance of Motion Scope running on a slow host or running in Client/Server mode over a congested network.
 | sequenceCount | represents the number of sequence objects to be configured for the controller.
 | sercosCount | represents the number of sercos objects to be configured for the controller.
 | userVersion | allows the user to mark a firmware image with a user-defineable version number.
 | sampleRate | represents the number of servo cycles the controller will be configured for. The default value is 2000Hz. This means that one servo cycle takes 0.5milliseconds.
Description

ControlConfig is the structure that contains the controller configuration information.

MEIControlConfig

typedef struct MEIControlConfig {
    long		preFilterCount;
    long		compensatorCount;
    MEIXmpPreFilter	PreFilter[MEIXmpMAX_PreFilters];
    MEIXmpCompensator	Compensator[MEIXmpMAX_Compensators];
    long		CompensationTable[MEIXmpCompTableSize];
    MEIXmpUserBuffer	UserBuffer;
} MEIControlConfig;

Description
 | preFilterCount | This value defines the number of enabled pre-filters.
 | compensatorCount | This value defines the number of enabled compensators.
 | PreFilter | This array defines the configuration for each pre-filter.
 | Compensator | This array defines the configuration for each compensator.
 | CompensationTable | This array defines the compensation values for the compensators.
 | UserBuffer | This structure defines the controller's user buffer. This is used for custom features that require a controller data buffer.

See Also | mpiControlConfigGet | mpiControlConfigSet | meiControlExtMemAvail | Special Note on Dynamic Allocation of External Memory Buffers.


MPIControlIo

MPIControlIo

typedef struct MPIControlIo {
    unsigned long   input[MPIControlIoWords];
    unsigned long   output[MPIControlIoWords];;
} MPIControlIo;
Description

ControlIo is used to hold the status of all the controller i/o lines on a board. This does not include any CAN i/o lines.

INPUT | all user i/o inputs are stored in bits of input[0]. User i/o input 0 corresponds to bit 0. Control i/o input 1 corresponds to bit 1.
OUTPUT | all user i/o outputs are stored in bits of output[0]. User i/o output 0 corresponds to bit 0. Control i/o output 1 corresponds to bit 1.

See Also | MEIControlOutput | MEIControlInput | mpiControlIoGet | mpiControlIoSet


MEIControlInput

MEIControlInput

typedef enum {
    MEIControlInputUSER_0   = MEIXmpControlIOMaskUSER0_IN,
    MEIControlInputUSER_1   = MEIXmpControlIOMaskUSER1_IN,
    MEIControlInputUSER_2   = MEIXmpControlIOMaskUSER2_IN,
    MEIControlInputUSER_3   = MEIXmpControlIOMaskUSER3_IN,
    MEIControlInputUSER_4   = MEIXmpControlIOMaskUSER4_IN,
    MEIControlInputUSER_5   = MEIXmpControlIOMaskUSER5_IN,
} MEIControlInput;
Description

ControlInput contains bit mask definitions for generic MPIControlIo input words.

See Also | MEIControlOutput | MPIControlIo | mpiControlIoGet | mpiControlIoSet


MPIControlMessage and MEIControlMessage

MPIControlMessage / MEIControlMessage

MPIControlMessage

typedef enum {
    MPIControlMessageLIBRARY_VERSION,   /* Keep as first control message */
    MPIControlMessageADDRESS_INVALID,
    MPIControlMessageCONTROL_INVALID,
    MPIControlMessageTYPE_INVALID,
    MPIControlMessageINTERRUPTS_DISABLED,
    MPIControlMessageEXTERNAL_MEMORY_OVERFLOW,
    MPIControlMessageADC_COUNT_INVALID,
    MPIControlMessageAXIS_COUNT_INVALID,
    MPIControlMessageCAPTURE_COUNT_INVALID,
    MPIControlMessageCOMPARE_COUNT_INVALID,
    MPIControlMessageCMDDAC_COUNT_INVALID,
    MPIControlMessageAUXDAC_COUNT_INVALID,
    MPIControlMessageFILTER_COUNT_INVALID,
    MPIControlMessageMOTION_COUNT_INVALID,
    MPIControlMessageMOTOR_COUNT_INVALID,
} MPIControlMessage;

Description
 | MPIControlMessageADDRESS_INVALID | Not used.
 | MPIControlMessageCONTROL_INVALID | Not used.
 | MPIControlMessageTYPE_INVALID | An invalid control type has been specified.
 | MPIControlMessageINTERRUPTS_DISABLED | Use of interrupt requested, when interrupts are disabled.

MEIControlMessage

typedef enum {
    MEIControlMessageFIRMWARE_INVALID = MEIControlMessageLAST,
    MEIControlMessageFIRMWARE_VERSION,
} MEIControlMessage;

Description
 | MEIControlMessageFIRMWARE_INVALID | This message code occurs when the firmware executing in the controller is not valid. This could be caused by incompatible firmware code, corrupted code, or a hardware problem.
 | MEIControlMessageFIRMWARE_VERSION | This message code occurs when the firmware version is not compatible with the host library version.
See Also


MEIControlOutput

MEIControlOutput

typedef enum {
    MEIControlOutputUSER_0  = MEIXmpControlIOMaskUSER0_OUT,
    MEIControlOutputUSER_1  = MEIXmpControlIOMaskUSER1_OUT,
    MEIControlOutputUSER_2  = MEIXmpControlIOMaskUSER2_OUT,
    MEIControlOutputUSER_3  = MEIXmpControlIOMaskUSER3_OUT,
    MEIControlOutputUSER_4  = MEIXmpControlIOMaskUSER4_OUT,
    MEIControlOutputUSER_5  = MEIXmpControlIOMaskUSER5_OUT,
} MEIControlOutput;
Description

ControlOutput contains bit mask definitions for generic MPIControlIo output words.

See Also | MEIControlOutput | MPIControlIo | mpiControlIoGet | mpiControlIoSet


MPIControlType

MPIControlType

typedef enum {
    MPIControlTypeDEFAULT,
    MPIControlTypeMAPPED,
    MPIControlTypeIOPORT,
    MPIControlTypeDEVICE,
    MPIControlTypeCLIENT,
    MPIControlTypeFILE,
} MPIControlType;
Description

ControlType is an enumeration that specifies the type of controller that needs to be accessed when mpiControlCreate() is called. Please refer to the documentation for mpiControlCreate() to see how to use this enumeration.

See Also | MPIControl | mpiControlCreate | mpiControlType


MEIControlVersion

MEIControlVersion

typedef struct MEIControlVersion {
    struct {	/* control.c */
        long	version;	/* MEIControlVersionMPI (YYYYMMDD) */

        struct {	/* xmp.h */
            long	version;	/* MEIXmpVERSION */
            long	option;		/* MEIXmpOPTION */
        } firmware;
    } mpi;

    struct {
        long	version;	/* hardware version */

        struct {	/* MEIXmpData.SystemData{} */
            long	version;	/* MEIXmpVERSION_EXTRACT(SoftwareID) */
            char	revision;	/* ('A' - 1) + MEIXmpREVISION_EXTRACT(SoftwareID) */
            long	subRevision;	/* MEIXmpSUB_REV_EXTRACT(Option) */
            long	developmentId;	/* MEIXmpDEVELOPMENT_ID_EXTRACT(Option) */
            long	option;		/* MEIXmpOPTION_EXTRACT(Option) */
            long	userVersion;
        } firmware;

        struct	{
            long	FPGA[MEIXmpFPGAsPerBlock];
        } motionBlock[MEIXmpMaxMotionBlocks];

        struct {
            struct	{
                long	version;
                long	option;
            } busInterface;
        } board[MEIXmpMaxBoards];
    } xmp;
} MEIControlVersion;
Description

ControlVersion is a structure that specifies the version information for the MPI and the controller's firmware, FPGAs, and the bus interface.

mpi | A structure that contains the version information of the MPI
mpi.version | A string representing the version of the MPI. The version of the MPI is broken down by date, branch, and revision (MPIVersion.branch.revision). For ex: 20021220.1.2 means MPI version 20021220, branch 1, revision 2.
mpi.firmware | The firmware version information that the current version of the MPI will work with. A new field has been added to the XMP's firmware to identify and differentiate between intermediate branch software revisions. The branch value is represented as a hex number between 0x00000000 and 0xFFFFFFFF. Each digit represents an instance of a branch (0x1 to 0xF). A single digit represents a single branch from a specific version, two digits represent a branch of a branch, three digits represent a branch of a branch of a branch, etc.
xmp | A structure that contains the version information of the XMP controller
xmp.firmware | The XMP's firmware version information.
xmp.motionBlock[] | An array of structures that contain version information about the motion blocks on the XMP.
xmp.board | An array of structures that contain version information about the XMP controller boards.

See Also | MPIControl


mpiControlAddress

Declaration
long mpiControlAddress(MPIControl        control,
                       MPIControlAddress *address)
Required Header stdmpi.h
Description When a Control object (control) is created, an address is used. ControlAddress writes this address to the contents of address.
Return Values
MPIMessageOK if ControlAddress successfully writes the address (used when control was created) to the contents of address
See Also


mpiControlConfigGet

Declaration
long mpiControlConfigGet(MPIControl       control,
                         MPIControlConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

ControlConfigGet gets the configuration of a Control object (control) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIControlConfig{} or is NULL.
Return Values
MPIMessageOK if ControlConfigGet successfully gets the control configuration and writes it in the structure(s)
See Also | mpiControlConfigSet | MEIControlConfig | Special Note on Dynamic Allocation of External Memory Buffers.


mpiControlConfigSet

Declaration
long mpiControlConfigSet(MPIControl       control,
                         MPIControlConfig *config,
                         void             *external)
Required Header stdmpi.h
Description

ControlConfigSet sets (writes) the Control object’s (control) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIControlConfig{} or is NULL.

Return Values
MPIMessageOK if ControlConfigSet successfully writes the Control object’s configuration using data from the structure(s)
See Also | mpiControlConfigGet | MEIControlConfig | Special Note on Dynamic Allocation of External Memory Buffers.


mpiControlCreate

Declaration
const MPIControl mpiControlCreate(MPIControlType     type,
                                  MPIControlAddress  *address)
Required Header stdmpi.h
Description

ControlCreate creates a Control object of the specified type and type-specific address. ControlCreate is the equivalent of a C++ constructor.
The type parameter determines the form of the address parameter:
If the "type" parameter is | Then the form of the "address" parameter is
MPIControlTypeDEFAULT | implementation-specific
MPIControlTypeMAPPED | MPIControlAddress.mapped
MPIControlTypeIOPORT | MPIControlAddress.ioPort
MPIControlTypeDEVICE | MPIControlAddress.device
MPIControlTypeCLIENT | MPIControlAddress.client
Note: This constructor does not reset or initialize the motion control device.
About MPIControlTypes:
If MPIControlType is | And MPIControlAddress is | Then the Board Number is | And the “address” parameter to be used is
DEFAULT1 | Null address | 0 address.number | default address parameter default address parameter
DEVICE2 | Null address | 0 address.number | default device driver address.type.device (if address.type.device is Null, then default device driver)
A valid type | address | address.number | N/A (if address parameter is not defined or Null, then an error is generated)
  1. If the type is DEFAULT, then the address structure (if supplied) is referenced only for the board number. Note that even if the default type is DEVICE, the default device driver will be used and address.type.device will not be used.
  2. If the type is explicitly DEVICE, and the address is provided, then address.number will be used. If address.type.device is NULL, then the default device driver will be used. If address.type.device is not NULL, then the specified driver (DEVICE) will be used.

Sample Code

In general, if the caller specifies an explicit type (i.e., not DEFAULT), then the caller must
completely fill out the address.type structure.

A simple case that will work for almost anyone who wants to use board  #0:

mpiControlCreate(MPIControlTypeDEFAULT, NULL);

A simple case where board #1 is desired is:

    {
        MPIControlAddress address;
        address.number = 1;
        mpiControlCreate(MPIControlTypeDEFAULT, &address);
    }

Since the default MPIControlType = MPIControlTypeDEVICE, the address may be on the
stack with garbage for the device driver name. This isn’t a problem, however, because
the board number is the only field in address that will be used when the caller specifies
the DEFAULT MPIControlType.

Return Values
handle | to a Control object
MPIHandleVOID | if the object could not be created

See Also | MPIControl | MPIControlAddress | MPIControlType | mpiControlValidate mpiControlInit | mpiControlDelete


meiControlCycleWait

Declaration
long meiControlCycleWait(MPIControl control,
                         long       count)
Required Header stdmei.h
Description

ControlCycleWait waits for the XMP motion controller (control) to execute for count background cycles. The host will continuously verify that the XMP firmware is operational, and the host will give up its time slice as it waits (for the controller to execute the background cycles).
Return Values
MPIMessageOK after the motion controller successfully executes for count cycles
See Also


mpiControlDelete

Declaration
long mpiControlDelete(MPIControl control)
Required Header stdmpi.h
Description

ControlDelete deletes a control object and invalidates its handle. ControlDelete is the equivalent of a C++ destructor.

Return Values
MPIMessageOK if ControlDelete successfully deletes a Control object and invalidates its handle
See Also | mpiControlCreate | mpiControlValidate


meiControlExtMemAvail

Declaration
long meiControlExtMemAvail(MPIControl control,
                           long       *size)
Required Header stdmei.h
Description

ControlExtMemAvail gets the amount of external memory available on an XMP-Series controller. It puts the number of words (16 bit) in the location pointed to by size.

control | a handle to the Control object
*size | a pointer to the available memory words returned by the method
Return Values
MPIMessageOK if ControlExtMemAvail successfully gets and writes the available external memory words into *size
See Also | MPIControlConfig


mpiControlFlashConfigGet

Declaration
long mpiControlFlashConfigGet(MPIControl       control,
                              void             *flash,
                              MPIControlConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

ControlFlashConfigGet gets the flash configuration of a Control object (control) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Control’s flash configuration information in external is in addition to the Control’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIControlConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.

Return Values
MPIMessageOK if ControlFlashConfigGet successfully gets the Control’s flash configuration and writes it into the structure(s)
See Also | MEIFlash | mpiControlFlashConfigSet | | MEIControlConfig


mpiControlFlashConfigSet

Declaration
long mpiControlFlashConfigSet(MPIControl       control,
                              void             *flash,
                              MPIControlConfig *config,
                              void             *external)
Required Header stdmpi.h
Description

ControlFlashConfigSet sets (writes) the flash configuration of a Control object (control), using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Control’s flash configuration information in external is in addition to the Control’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIControlConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if ControlFlashConfigSet successfully sets (writes) the Control’s flash configuration using data from the structure(s)
See Also | MEIFlash | mpiControlFlashConfigGet | | MEIControlConfig


meiControlGateGet

Declaration
long meiControlGateGet(MPIControl control,
                       long       gate,
                       long       *closed)
Required Header stdmei.h
Description

ControlGateGet gets the closed state (TRUE or FALSE) from the specified control gate (0 to 31).
Return Values
MPIMessageOK if ControlGateGet successfully gets (reads) the state from the control gate and puts it into closed.
See Also | meiControlGateSet


meiControlGateSet

Declaration
long meiControlGateSet(MPIControl control,
                       long       gate,
                       long       closed)
Required Header stdmei.h
Description

ControlGateSet sets the closed state (TRUE or FALSE) for the specified control gate (0 to 31).
Return Values
MPIMessageOK if ControlGateSet successfully sets (writes) the closed state into the control gate.
See Also | meiControlGateGet


mpiControlInit

Declaration
long mpiControlInit(MPIControl   control)
Required Header stdmpi.h
Description

ControlInit initializes the motion control device control. ControlInit must be called at least once after a control object has been created and before any other mpiControl methods are called [with the exception of mpiControlDelete(...)].

Return Values
MPIMessageOK if ControlInit successfully initializes the motion control device control
See Also | mpiControlDelete


mpiControlInterruptEnable

Declaration
long mpiControlInterruptEnable(MPIControl control,
                               long       enable)
Required Header stdmpi.h
Description

If “enable” is TRUE, then ControlInterruptEnable enables interrupts from the motion controller.

If "enable" is FALSE, then ControlInterruptEnable disables interrupts from the motion controller.

Return Values
MPIMessageOK if ControlInterruptEnable successfully enables (or disables) interrupts from the motion controller
See Also | mpiControlInteruptWait | mpiControlInteruptWake


mpiControlInterruptWake

Declaration
long mpiControlInterruptWake(MPIControl control)
Required Header stdmpi.h
Description

ControlInterruptWake wakes all threads waiting for an interrupt from the motion controller control [as a result of a call to mpiControlInterruptWait(...)]. The waking thread(s) will return from the call with no interrupt indicated.
Return Values
MPIMessageOK if ControlInterruptWake successfully wakes all threads waiting for an interrupt from the motion controller
See Also | mpiControlInterruptWait | mpiControlInteruptEnable


mpiControlInterruptWait

Declaration
long mpiControlInterruptWait(MPIControl  control,
                             long        *interrupted,
                             MPIWait     timeout)
Required Header stdmpi.h
Description

ControlInterruptWait waits for an interrupt from the motion controller if interrupts are enabled.

After the ControlInterruptWait method returns, if the location pointed to by interrupted contains TRUE, then an interrupt has occurred.

After the ControlInterruptWait method returns, if the location pointed to by interrupted contains FALSE, then no interrupt has occurred, and the return of ControlInterruptWait was caused either by a call to mpiControlInterruptWake(...) or by a timeout that has occurred.

If timeout is MPIWaitFOREVER (-1), then ControlInterruptWait will wait forever for an interrupt
If timeout is MPIWaitPOLL (0), then ControlInterruptWait will return immediately
If timeout is a value (not 0 or -1), then ControlInterruptWait will wait for an interrupt for timeout milliseconds

Return Values
MPIMessageOK if ControlInterruptWait waits for an interrupt from the motion controller
See Also | mpiControlInterruptWake | mpiControlInteruptEnable


mpiControlIoGet

Declaration
long mpiControlIoGet(MPIControl       control,
                     MPIControlIo     *io);
Required Header stdmpi.h
Description

Some XMP controllers have some additional User I/O pinouts from the controller. ControlIoGet gets the I/O bits from controller I/O register and puts (writes) them in the structure pointed to by io.

Return Values
MPIMessageOK | if ControlUserIoGet successfully gets the I/O bits from controller and puts (writes) them in the structure.
MPIMessageARG_INVALID | if the io pointer points to NULL.

See Also | mpiControlIoSet | MPIControlIo


mpiControlIoSet

Declaration
long mpiControlIoSet(MPIControl       control,
                     MPIControlIo     *io);
Required Header stdmpi.h
Description

Some XMP controllers have some additional User I/O pinouts from the controller. ControlIoSet gets the I/O bits from controller I/O register and puts (writes) them in the structure pointed to by io.

Return Values
MPIMessageOK if ControlUserIoGet successfully gets the I/O bits from controller and puts (writes) them in the structure
See Also | mpiControlIoGet | MPIControlIo


mpiControlMemory

Declaration
long mpiControlMemory(MPIControl control,
                      void       **memory,
                      void       **external)
Required Header stdmpi.h
Description

ControlMemory sets (writes) an address (used to access a Control object’s memory) to the contents of memory.

If external is not NULL, the contents of external are set to an implementation-specific address that typically points to a different section or type of Control memory other than memory (e.g., to external or off-chip memory). These addresses (or addresses calculated from them) are passed as the src argument to mpiControlMemoryGet(...) and the dst argument to mpiControlMemorySet(...).
Return Values
MPIMessageOK if ControlMemory successfully writes the address(es) (used to access Control memory, and optionally to access another section of Control memory) to the contents of memory (and to external, if external is not Null)
See Also | mpiControlMemoryGet | mpiControlMemorySet | mpiControlMemoryAlloc | mpiControlMemoryCount | mpiControlMemoryFree


mpiControlMemoryAlloc

Declaration
long mpiControlMemoryAlloc(MPIControl           control,
                           MPIControlMemoryType type,
                           long                 count,
                           void                 **memory)
Required Header stdmpi.h
Description

ControlMemoryAlloc allocates count bytes of firmware memory [of type type on a Control object (control)] and writes the host address (of the allocated firmware memory) to the location pointed to by memory.

Return Values
MPIMessageOK if ControlMemoryAlloc successfully allocates firmware memory and writes the host address of that firmware memory to memory
See Also | mpiControlMemoryGet | mpiControlMemorySet | mpiControlMemory | mpiControlMemoryCount | mpiControlMemoryFree


mpiControlMemoryCount

Declaration
long mpiControlMemoryCount(MPIControl            control,
                           MPIControlMemoryType  type,
                           long                  *count)
Required Header control.h
Description

ControlMemoryCount writes the number of bytes of firmware memory [on a Control object (control, of type type) that are available to be allocated] to the location pointed to by count.
Return Values
MPIMessageOK if ControlMemoryCount successfully writes the number of bytes of firmware memory (that are available to be allocated) to count.
See Also


mpiControlMemoryFree

Declaration
long mpiControlMemoryFree(MPIControl           control,
                          MPIControlMemoryType type,
                          long                 count,
                          void                 *memory)
Required Header stdmpi.h
Description

ControlMemoryFree frees count bytes of firmware memory on a Control object (control, of type type) starting at host address memory.
Return Values
MPIMessageOK if ControlMemoryAlloc successfully frees count bytes of firmware memory on a Control object
See Also | mpiControlMemoryGet | mpiControlMemorySet | mpiControlMemoryAlloc | mpiControlMemoryCount | mpiControlMemory


mpiControlMemoryGet

Declaration
long mpiControlMemoryGet(MPIControl control,
                         void       *dst,
                         void       *src,
                         long       count)
Required Header stdmpi.h
Description

ControlMemoryGet gets count bytes of control memory (starting at address src) and puts (writes) them in application memory (starting at address dst).

Return Values
MPIMessageOK if ControlMemoryGet successfully gets count bytes of control memory and puts (writes) them in application memory
See Also | mpiControlMemorySet | mpiControlMemory | mpiControlMemoryAlloc | mpiControlMemoryCount | mpiControlMemoryFree


mpiControlMemorySet

Declaration
long mpiControlMemorySet(MPIControl control,
                         void       *dst,
                         void       *src,
                         long       count)
Required Header stdmpi.h
Description

ControlMemorySet sets (writes) count bytes of application memory (starting at address src) to control memory (starting at address dst).

Return Values
MPIMessageOK if ControlMemorySet successfully sets (writes) count bytes of application memory to control memory
See Also | mpiControlMemoryGet | mpiControlMemory | mpiControlMemoryAlloc | mpiControlMemoryCount | mpiControlMemoryFree


meiControlPlatform

Declaration
MEIPlatform  meiControlPlatform(MPIControl control)
Required Header stdmei.h
Description

ControlPlatform returns a handle to the Platform object with which the control is associated.

control | a handle to the Control object

Return Values
MPIPlatform | handle to a Platform object
MPIHandleVOID | if control is invalid

See Also | mpiControlCreate


mpiControlReset

Declaration

long mpiControlReset(MPIControl control)
Required Header stdmpi.h
Description

ControlReset resets the motion controller (control) board.

Return Values
MPIMessageOK if ControlReset successfully resets the motion controller board
See Also


meiControlSampleCounter

Declaration
long meiControlSampleCounter(MPIControl   control,
                             long         *sampleCounter)
Required Header stdmei.h
Description

ControlSampleCounter writes the number of servo cycles (samples) that have occured since the last sample counter reset/rollover, to the sampleCounter . When the user resets the controller, the sample counter will also be reset. Since the sample counter is a long, if the sample counter is 2147483647 it will roll over on the next servo cycle to -2147483648.

Return Values
MPIMessageOK if the sample counter could be read
See Also | meiControlSecondstoSamples | meiControlSamplestoSeconds | meiControlSampleWait


meiControlSamplesToSeconds

Declaration
long meiControlSamplesToSeconds(MPIControl control,
                                long       samples,
                                float      *seconds)
Required Header stdmei.h
Description

ControlSamplesToSeconds writes to seconds the number of seconds it takes to process samples number of samples (at the current sample rate). Use this function to convert samples to seconds.
Return Values
MPIMessageOK if ControlSampleToSeconds successfully converts the samples to seconds.
See Also | meiControlSecondstoSamples | meiControlSampleCounter


meiControlSampleWait

Declaration
long meiControlSampleWait(MPIControl control,
                          long       count)
Required Header stdmpi.h
Description

ControlSampleWait waits for count samples while the XMP motion controller (associated with control) executes. While the host waits, the host gives up its time slice and continuously verifies that the XMP firmware is operational.

Return Values
MPIMessageOK if ControlSampleWait successfully waits for count samples while the XMP motion controller executes
See Also | meiControlSamplestoSeconds | meiControlSecondstoSamples | meiControlSampleCounter |


meiControlSecondstoSamples

Declaration
long meiControlSecondsToSamples(MPIControl control,
                                float      seconds,
                                long       *samples)
Required Header stdmei.h
Description

ControlSecondsToSamples writes to samples the number of servo cycles that will take place in seconds number of seconds (at the current sample rate). Use this function to convert seconds to samples.

Return Values
MPIMessageOK if ControlSecondsToSamples successfully converts the seconds to samples.
See Also | meiControlSamplestoSeconds | meiControlSampleCounter | meiControlSampleWait


mpiControlType

Declaration
long mpiControlType(MPIControl     control,
                    MPIControlType *type)
Required Header stdmpi.h
Description

When a Control object (control) is created, a type is used. ControlType writes this type to the contents of type.
Return Values
MPIMessageOK if ControlType successfully gets the type (used when control was created) to the contents of type
See Also


mpiControlValidate

Declaration
long mpiControlValidate(MPIControl control)
Required Header stdmpi.h
Description

ControlValidate validates the control object and its handle.
Return Values
MPIMessageOK if Control is a handle to a valid object.
See Also | mpiControlCreate | mpiControlDelete


meiControlVersionGet

Declaration
long meiControlVersionGet(MPIControl        control,
                          MEIControlVersion *version)
Required Header stdmei.h
Description

ControlVersionGet writes the the version numbers of the XMP firmware, hardware, and the MPI library to the structure pointed to by version.

Return Values
MPIMessageOK if ControlVersionGet successfully writes the the version numbers of the XMP firmware, hardware, and the MPI library to the location
See Also | meiControlVersionSet


meiControlVersionSet

Declaration
long meiControlVersionSet(MPIControl        control,
                          MPIControlVersion *version)
Required Header stdmei.h
Description

ControlVersionSet sets the version numbers of the XMP firmware, hardware, and the MPI library using data from the structure pointed to by version.

Normally, the MPI library is compatible only with the XMP firmware for which the library is specifically built; i.e., only when

version -> mpi.firmware.version == version -> xmp.firmware.version

However, there are times when it is desirable to have the MPI library ignore incompatible firmware and continue to operate. As an example, the flash utility instructs the MPI library to ignore firmware incompatibility when new firmware is being loaded. Of course, this new firmware should also be compatible with the MPI library. In such cases, the version -> xmp.firmware structure will be copied into control.
Return Values
MPIMessageOK if ControlVersionSet successfully sets the version numbers of the XMP firmware, hardware, and the MPI library using data from the structure
See Also | meiControlVersionGet


Event Objects

Introduction

An Event object contains information about an asynchronous event. Typically, events are generated by the controller, but in some special cases it is possible to generate events from the host computer.

The Event object is retrieved through the EventMgr, via the Notify object. The Event object contains data about the type of event, its source, and other information. The user Event fields can be configured to collect data at the time when the event occurs in the controller.
Methods
Configuration and Information Methods
 | mpiEventStatusGet | Get Event status
 | mpiEventStatusSet | Set Event status
Data Types
MPIEventMessage
MEIEventNotifyData
MPIEventStatus
MEIEventStatusInfo
MPIEventType / MEIEventType
Constants
MPIEventStatusINFO_COUNT_MAX | defines the size of the MPIEventStatus.info[] array.


Special Note: Use of MPIEventTypeENCODER_FAULT

This event type is used to detect three types of encoder faults:

  • Broken wire errors
  • Illegal state errors
  • Absolute encoder initialization errors
    • Timeout errors
    • Protocol errors

Broken wire errors are detected for either incremental or absolute encoders whenever both differential inputs of any encoder receiver (A, B, or Index) are at the same voltage level (i. e., whenever one or both inputs is disconnected from the encoders differential transmitter). The EncoderTermination configuration of the encoder input must be TRUE for correct detection of broken wires.

Illegal state errors occur whenever transitions are seen on both A and B phases of an encoder input at the same time (e.g. noise spikes).

There are two types of absolute encoder initialization errors: Timeout errors and Protocol errors. Timeout errors occur when an absolute encoder does not transmit absolute encoder data within the timeout period starting at the transition of the interrogation line (SEN line). Protocol errors are detected when serial absolute data is sent during the timeout, but the data cannot be interpreted by the XMP. Both error types result in an ENCODER_FAULT event.

Return to MPIEventType


MPIEventMessage

MPIEventMessage

typedef enum {
    MPIEventMessageEVENT_INVALID,
} MPIEventMessage;

Description
 | MPIEventMessageEVENT_INVALID
 | Meaning | The MPIEvent handle passed to an MPIEvent method is invalid.
 | Possible Causes | Either the handle was never initialized or the mpiEventCreate method failed.
 | Recommendations | MPIEvent objects are used internally. Do not create your own. If you have not and you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
See Also


MEIEventNotifyData

MPIEventNotifyData

typedef struct MEIEventNotifyData {
    void	*address[MEIXmpSignalUserData];
} MEIEventNotifyData;

Description | The address of an EventNotifyData structure is passed as the third (void *external) argument to mpi'Object'EventNotify[GS]et(). The address array contains host-based XMP addresses, the contents of which are returned in MEIEventStatusInfo{}.data.

See Also | MEIEventStatusInfo


MPIEventStatus

MPIEventStatus

typedef struct MPIEventStatus {
    MPIEventType	type;
    void		*source;

    long		info[MPIEventStatusINFO_COUNT_MAX];
} MPIEventStatus;
Description

EventStatus holds information about a particular event that was generated by the XMP.

type | identifies the type of event that was generated.
*source | identifies what the source of the event was. source will either be a handle to an MPI object or a host pointer. Use mpiObjectModuleId() to identify what source points to.

See Also | mpiObjectModuleId | MPIEventType | MPIEventMgr | MPINotify | MEIEventStatusInfo | MPIEventStatusINFO_COUNT_MAX


MEIEventStatusInfo

MEIEventStatusInfo

typedef struct MEIEventStatusInfo {
    union {
        MPIHandle    handle;    /* generic */
        MPIAxis      axis;      /* MEIEventTypeAXIS_FIRST ... MEIEventTypeAXIS_LAST - 1 */
        long         number;    /* MPIEventTypeMOTION
                    MPIEventTypeMOTOR_FIRST ... MPIEventTypeMOTOR_LAST - 1
                MEIEventTypeMOTOR_FIRST ... MEIEventTypeMOTOR_LAST - 1 */
        long         value;     /* MPIEventTypeEXTERNAL */
        } type;

        MEIXmpSignalID signalID;

        /* Contents of addresses specified by MEIEventNotifyData{} */
        union {
                  long sampleCounter;
                  struct {
                      long sampleCounter;
                  } motion;
                  struct {
                       long sampleCounter;
                       long actualPosition;
                  } axis;
                  struct {
                       long sampleCounter;
                       long encoderPosition;
                  } motor;
                  long word[MEIXmpSignalUserData];
             } data;
} MEIEventStatusInfo;
Description

EventStatusInfo is an information structure that tells the XMP what the data in MPIEventStatus.info holds.

type | A union that specifies the object handle, motion number, or external ID value that generated the event
type.handle | A generic object handle. Used by MPIRecorder and MPIMotor events
type.axis | An axis object handle. Used by MPIAxis events
type.number | The motion number of the MPIMotion object that generated the event
type.value | An ID value used to identify what external source or MPISequence event was generated
signalID | Specifies what type of object actually generated the event
data | A union that contains extra data about the event that was generated
data.sampleCounter | The value of the sampleCounter when the event was generated
data.motion | A union that contains extra data about the motion event that was generated
data.motion.sampleCounter | The value of the sampleCounter when the motion event was generated
data.axis | A union that contains extra data about the axis event that was generated
data.axis.sampleCounter | The value of the sampleCounter when the axis.event was generated
data.axis.actualPosition | The value of the axis' actual position when the event was generated
data.motor | A union that contains extra data about the motor event that was generated
data.motor.sampleCounter | The value of the sampleCounter when the motor event was generated
data.motor.encoderPosition | The value of the motor's ecoder position when the event was generated
data.word[] | The extra data about the event that was generated formatted as an array of long values
Sample Code

        MPINotify      notify
        MPIEventStatus eventStatus;

        . . .

        /* Wait for event */
        returnValue =
            mpiNotifyEventWait(notify,
                                         &eventStatus,
                                          MPIWaitFOREVER);
        msgCHECK(returnValue);

        if (eventStatus.type == MPIEventTypeMOTION_DONE) {
            MEIEventStatusInfo *info;

            info = (MEIEventStatusInfo *)eventStatus.info;

            . . .
        }

See Also | MPIEventStatus | MPIAxis


MPIEventStatusINFO_COUNT_MAX

MPIEventStatusINFO_COUNT_MAX

#define MPIEventStatusINFO_COUNT_MAX	(16)
Description

EventStatusINFO_COUNT_MAX defines the size of the MPIEventStatus.info[] array.

See Also | MPIEventStatus | MPIEventMgr | MPINotify


MPIEventType and MEIEventType

MPIEventType / MEIEventType

MPIEventType
typedef enum {
    MPIEventTypeINVALID,

    MPIEventTypeNONE,		/*  0 */

    /* Motor events */
    MPIEventTypeAMP_FAULT,	/*  1 */
    MPIEventTypeHOME,		/*  2 */
    MPIEventTypeLIMIT_ERROR,	/*  3 */
    MPIEventTypeLIMIT_HW_NEG,	/*  4 */
    MPIEventTypeLIMIT_HW_POS,	/*  5 */
    MPIEventTypeLIMIT_SW_NEG,	/*  6 */
    MPIEventTypeLIMIT_SW_POS,	/*  7 */
    MPIEventTypeENCODER_FAULT,	/*  8 */

    /* Motion events */
    MPIEventTypeMOTION_DONE,		/*  9 */
    MPIEventTypeMOTION_AT_VELOCITY,	/* 10 */

    /* Recorder events */
    MPIEventTypeRECORDER_FULL,	/* 11 */
    MPIEventTypeRECORDER_DONE,	/* 12 */

    /* External events */
    MPIEventTypeEXTERNAL,	/* 13 */
} MPIEventType;
Description

EventType is used by the MPIEventMask macros to help generate event masks.

MPIEventTypeNONE | This event type indicates no event was generated.
MPIEventTypeAMP_FAULT | This event type indicates an Amp Fault event was generated from a Motor object.
MPIEventTypeHOME | This event type indicates a Home event was generated from a Motor object.
MPIEventTypeLIMIT_ERROR | This event type indicates a position Error Limit was generated from a Motor object.
MPIEventTypeLIMIT_HW_NEG | This event type indicates a Negative Hardware Limit event was generated from a Motor object.
MPIEventTypeLIMIT_HW_POS | This event type indicates a Positive Hardware Limit event was generated from a Motor object.
MPIEventTypeLIMIT_SW_NEG | This event type indicates a Negative Software Limit event was generated from a Motor object.
MPIEventTypeLIMIT_SW_POS | This event type indicates a Positive Software Limit event was generated from a Motor object.
MPIEventTypeENCODER_FAULT | This event type indicates an Encoder Fault event was generated from a Motor object.
MPIEventTypeMOTION_DONE | This event type indicates a Motion Done event was generated from a Motion Supervisor object.
MPIEventTypeMOTION_AT_VELOCITY | This event type indicates an At Velocity event was generated from a Motion Supervisor object.
MPIEventTypeRECORDER_FULL | This event type indicates a Recorder Full event was generated from a Recorder object.
MPIEventTypeRECORDER_DONE | This event type indicates a Recorder Done event was generated from a Recorder object.
MPIEventTypeEXTERNAL | This event type indicates an External event was generated from an external source.

MEIEventType
typedef enum {
    /* Motor events */
    MEIEventTypeLIMIT_USER0 = MPIEventTypeLAST,	/* 14 */
    MEIEventTypeLIMIT_USER1,	/* 15 */
    MEIEventTypeLIMIT_USER2,	/* 16 */
    MEIEventTypeLIMIT_USER3,	/* 17 */
    MEIEventTypeLIMIT_USER4,	/* 18 */
    MEIEventTypeLIMIT_USER5,	/* 19 */
    MEIEventTypeLIMIT_USER6,	/* 20 */
    MEIEventTypeLIMIT_USER7,	/* 21 */
    MEIEventTypeLIMIT_TORQUE,	/* 22 */

    /* Motion events */
    MEIEventTypeMOTION_OUT_OF_FRAMES,	/* 23 */
    MEIEventTypeMOTION_RESERVED0,		/* 24 */

    /* Axis events */
    MEIEventTypeIN_POSITION_COARSE,		/* 25 */
    MEIEventTypeIN_POSITION_FINE,		/* 26 */
    MEIEventTypeAT_TARGET,			/* 27 */
    MEIEventTypeFRAME,			/* 28 */
    MEIEventTypeAXIS_RESERVED0,		/* 29 */
    MEIEventTypeAXIS_RESERVED1,		/* 30 */
    MEIEventTypePOWER_FAILURE,		/* 31 */

} MEIEventType;
Description

EventType is used by the MPIEventMask macros to help generate event masks.

MPIEventTypeLIMIT_USER0 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER1 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER2 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER3 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER4 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER5 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER6 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_USER7 | This event type indicates a User Limit event was generated from a Motor object.
MPIEventTypeLIMIT_TORQUE | This event type indicates a Torque event was generated from a Motor object.
MPIEventTypeMOTION_OUT_OF_FRAMES | This event type indicates a Motion Done event was generated from a Motion Supervisor object.
MPIEventTypeMOTION_RESERVED0 | This event type indicates a Reserved Motion event was generated from a Motion Supervisor object. This event type is reserved for future use or custom motion events.
MPIEventTypeIN_POSITION_COARSE | This event type indicates an In Coarse Position event was generated from an Axis object.
MPIEventTypeIN_POSITION_FINE | This event type indicates an In Fine Position event was generated from an Axis object.
MPIEventTypeAT_TARGET | This event type indicates an At Target event was generated from an Axis object.
MPIEventTypeFRAME | This event type indicates an At Target event was generated from an Axis object.
MPIEventTypeAXIS_RESERVED0 | This event type indicates a Reserved Axis event was generated from an Axis object. This event type is reserved for future use or custom axis events.
MPIEventTypeAXIS_RESERVED1 | This event type indicates a Reserved Axis event was generated from an Axis object. This event type is reserved for future use or custom axis events.
MPIEventTypePOWER_FAILURE | This event type indicates a Power Failure event was generated from the controller.

See Also | MPIEventMask | MPIEventMgr | MPINotify | MPIEventStatus Special Note on the use of MPIEventTypeENCODER_FAULT


mpiEventStatusGet

Declaration
long mpiEventStatusGet(MPIEvent       event,
                       MPIEventStatus *status)
Required Header event.h
Description

EventStatusGet gets the status of an Event object (event) and writes it into the structure pointed to by status. Event status includes the event type, type-specific codes and the event source.

Return Values
MPIMessageOK if EventStatusGet successfully gets the status of an Event object and writes it into the structure
See Also | mpiEventStatusSet | meiEventStatusInfo


mpiEventStatusSet

Declaration
long mpiEventStatusSet(MPIEvent       event,
                       MPIEventStatus *status)
Required Header event.h
Description

EventStatusSet sets (writes) the status of event using data from the structure pointed to by status. Event status includes the event type, type-specific codes and the event source.

Return Values
MPIMessageOK if EventStatusSet successfully sets (writes) the status of event using data from the structure
See Also | mpiEventStatusGet | meiEventStatusInfo


EventMask Objects

Introduction

The EventMask determines which event types will be sent from the controller to the Notify object. By setting bits in the EventMask, specific events can be sent to the Notify object when they occur or by clearing specific bits, the events can be ignored. By default, no Events will occur until the EventMask is set.

The Event, EventMgr, and Notify objects are used with the EventMask to handle controller events.
Data Types
MPIEventMask | An array of unsigned longs
Macros
mpiEventMaskALL / meiEventMaskALL | Set all events within the event mask.
mpiEventMaskAND_ASSIGN | Assign dst all events masked by both src and dst.
mpiEventMaskASSIGN | Assign the value of event mask src to the event mask dst.
mpiEventMaskAXIS / meiEventMaskAXIS | Set all MPIAxis events within the event mask.
mpiEventMaskBIT | Set mask to only handle events of type type.
mpiEventMaskBITS_IN_ELEMENT | Define the number of bits in each data element of MPIEventMask.
mpiEventMaskBitGET | Reports if a mask is set to handle events of type type.
mpiEventMaskBitSET | Sets mask to handle events of type type.
mpiEventMaskBIT_POSITION_MASK | Returns an element's bit-mask for the specified event type.
mpiEventMaskCLEAR | Set mask to handle no events.
mpiEventMaskCOMPLEMENT | Change the value of every bit within the event mask.
mpiEventMaskEXTERNAL | Set external events within the event mask.
mpiEventMaskGET | Reports if a mask is set to handle events of type type.
mpiEventMaskIS_EQUAL | Tests the equality of two event masks.
mpiEventMaskMOTION / meiEventMaskMOTION | Set all MPIMotion events within the event mask.
mpiEventMaskMOTOR / meiEventMaskMOTOR | Set all MPIMotor events within the event mask.
mpiEventMaskOR_ASSIGN | Add all events masked by src to the event mask dst.
mpiEventMaskRECORDER | Sets all MPIRecorder events within the event mask.
mpiEventMaskSET | Set mask to handle events of type type.
mpiEventMaskSET_ALL | Set mask to handle all events whose type is enumerated less than type.
Constants
MPIEventMaskELEMENTS | Define the number of data elements in a MPIEventMask
MPIEventMaskELEMENT_TYPE | Define what the data type MPIEventMask is comprised of.


MPIEventMaskELEMENTS

MPIEventMaskELEMENTS

#define MPIEventMaskELEMENTS	(2)

Description
 | EventMaskELEMENTS defines the number of data elements in a MPIEventMask.

See Also | MPIEventMask


MPIEventMaskELEMENT_TYPE

MPIEventMaskELEMENT_TYPE

typedef unsigned long MPIEventMaskELEMENT_TYPE

Description
 | EventMaskELEMENT_TYPE defines what the data type MPIEventMask is comprised of.

See Also | MPIEventMask


MPIEventMask

MPIEventMask

#define MPIEventMaskELEMENTS	(2)
typedef unsigned long MPIEventMaskELEMENT_TYPE;
typedef MPIEventMaskELEMENT_TYPE MPIEventMask[MPIEventMaskELEMENTS];

Description
 | EventMask is an array of unsigned longs, with a length defined by MPIEventMaskELEMENTS. Each bit in the array represents a mask for a particular event. Be sure to always use the mpiEventMask…(…) macros to set or clear the event masks.

See Also | MPIEventType | mpiEventMaskBIT


mpiEventMaskAll and meiEventMaskALL

mpiEventMaskALL / meiEventMaskALL

mpiEventMaskALL
Declaration

#define mpiEventMaskALL(mask),mpiEventMaskSET_ALL((mask)
                              MPIEventTypeLAST)
Required Header stdmpi.h
Description

EventMaskALL sets all events within the event mask.

meiEventMaskALL
Declaration

#define	meiEventMaskALL(mask)
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER0, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER1, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER2, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER3, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER4, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER5, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER6, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER7, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeMOTION_OUT_OF_FRAMES, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeMOTION_RESERVED0, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeIN_POSITION_COARSE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeIN_POSITION_FINE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAT_TARGET, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeFRAME, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAXIS_RESERVED0, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAXIS_RESERVED1, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypePOWER_FAILURE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_TORQUE, 1)
Required Header stdmei.h
Description

EventMaskALL sets all MEI events within the event mask

See Also | MPIEventType


mpiEventMaskAND_ASSIGN

Declaration

#define mpiEventMaskAND_ASSIGN(dst,src)((dst)[0] = ((dst)[0] & (src)[0])), \
Required Header stdmpi.h
Description

EventMaskOR_ASSIGN assigns dst all events masked by both src and dst.

See Also | MPIEventMask


mpiEventMaskASSIGN

Declaration
#define mpiEventMaskASSIGN(dst,src)((dst)[0] = (src)[0]), \
Required Header stdmpi.h
Description

EventMaskASSIGN assigns the value of event mask src to the event mask dst.

See Also | MPIEventMask


mpiEventMaskAXIS and meiEventMaskAXIS

mpiEventMaskAXIS / meiEventMaskAXIS

mpiEventMaskAXIS
Declaration
#define mpiEventMaskAXIS(mask)(mask)
Required Header stdmpi.h
Description

EventMaskAXIS sets all MPIAxis events within the event mask.

meiEventMaskAXIS
Declaration

#define	meiEventMaskAXIS(mask)
    mpiEventMaskBitSET((mask), MEIEventTypeIN_POSITION_COARSE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeIN_POSITION_FINE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAT_TARGET, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeFRAME, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAXIS_RESERVED0, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeAXIS_RESERVED1, 1)
Required Header stdmei.h
Description

EventMaskAXIS sets all MEIAxis events within the event mask.

See Also | MPIEventMask


mpiEventMaskBIT

Declaration

#define mpiEventMaskBIT(mask,type)(((mask)[0] = 0); ((mask)[1] = 0); \
((mask)[mpiEventMaskWORD(type)]= mpiEventMaskBIT_POSITION_MASK(type)))
Required Header stdmpi.h
Description

EventMaskBIT sets mask to only handle events of type type.

See Also | MPIEventMask | mpiEventMaskBIT | mpiEventMaskBitGET | mpiEventMaskBitSET | mpiEventMaskBITS_IN_ELEMENT | mpiEventMaskBIT_POSITION_MASK


mpiEventMaskBitGET

Declaration

#define	mpiEventMaskBitGET(mask,bit)(((mask)[mpiEventMaskWORD(bit)] &
    mpiEventMaskBIT_POSITION_MASK(bit)) ? 1 : 0)
Required Header stdmpi.h
Description

EventMaskAXIS sets all MPIAxis events within the event mask.

Returns

 TRUE if mask is set to handle events of type type. Otherwise, it returns FALSE.
See Also | MPIEventMask | mpiEventMaskBIT | mpiEventMaskBitSET | mpiEventMaskBIT_POSITION_MASK | mpiEventMaskBITS_IN_ELEMENT


mpiEventMaskBITS_IN_ELEMENT

mpiEventMaskBITS_IN_ELEMENT

#define mpiEventMaskBITS_IN_ELEMENT ((unsigned long)
(sizeof(MPIEventMaskELEMENT_TYPE) * 8))
Description

EventMaskBITS_IN_ELEMENT defines the number of bits in each data element of MPIEventMask.

See Also | MPIEventMask | mpiEventMaskBIT | mpiEventMaskBitGET | mpiEventMaskBitSET | mpiEventMaskBIT_POSITION_MASK


mpiEventMaskBIT_POSITION_MASK

Declaration
#define mpiEventMaskBIT_POSITION_MASK (type)
               ((MPIEventMaskELEMENT_TYPE)(0x1 <<
                 mpiEventMaskBIT_POSITION(type)))
Required Header stdmpi.h
Description

type | the event type (MPIEventType / MEIEventType)

Returns

 an element's bit-mask for the specified event type.
See Also | MPIEventMask | mpiEventMaskBIT | mpiEventMaskBitGET | mpiEventMaskBitSET | mpiEventMaskBITS_IN_ELEMENT


mpiEventMaskBitSET

Declaration

#define	mpiEventMaskBitSET(mask,bit,value)	(((value) == 0) ? \
    ((mask)[mpiEventMaskWORD(bit)] &= ~mpiEventMaskBIT_POSITION_MASK(bit))
              : \
    ((mask)[mpiEventMaskWORD(bit)] |= mpiEventMaskBIT_POSITION_MASK(bit)))))
Required Header stdmpi.h
Description

EventMaskBitSET sets mask to handle events of type type.

See Also | MPIEventMask | mpiEventMaskBitGET | mpiEventMaskBIT | mpiEventMaskBIT_POSITION_MASK | mpiEventMaskBITS_IN_ELEMENT


mpiEventMaskCLEAR

Declaration

#define mpiEventMaskCLEAR(mask)((mask)[0] = 0), \ ((mask)[1] = 0)
Required Header stdmpi.h
Description EventMaskCLEAR sets mask to handle no events.
See Also | MPIEventMask


mpiEventMaskCOMPLEMENT

Declaration

#define mpiEventMaskCOMPLEMENT(mask)((mask)[0] = ~(mask)[0]),
                            \ ((mask)[1] = ~(mask)[1])
Required Header stdmpi.h
Description

EventMaskCOMPLEMENT() changes the value of every bit within the event mask. If the mask is origininally set to handle an event, then mask will be set to not handle the event after the call to mpiEventMaskCOMPLEMENT(). Likewise, If the mask is origininally set to not handle an event, then mask will be set to handle the event after the call to mpiEventMaskCOMPLEMENT().

See Also | MPIEventMask


mpiEventMaskEXTERNAL

Declaration
#define mpiEventMaskEXTERNAL(mask)mpiEventMaskBitSET((mask),
                             MPIEventTypeEXTERNAL, 1)
Required Header stdmpi.h
Description

EventMaskEXTERNAL sets external events within the event mask.

See Also | MPIEventMask


mpiEventMaskGET

Declaration

#define mpiEventMaskGET(mask,type)
mpiEventMaskBitGET(mask,type)
Required Header stdmpi.h
Description

Returns

 TRUE if mask is set to handle events of type type. Otherwise, it returns FALSE.
See Also | MPIEventMask | mpiEventMaskSET


mpiEventMaskIS_EQUAL

Declaration
#define	mpiEventMaskIS_EQUAL(mask1,mask2)
    (((mask1)[0] == (mask2)[0]) &&
    ((mask1)[1] == (mask2)[1])))
Required Header stdmpi.h
Description

EventMaskIS_EQUAL tests the equality of two event masks.

Returns

 TRUE if mask1 is the same as mask2. Otherwise it returns FALSE.
See Also | MPIEventMask


mpiEventMaskMOTION and meiEventMaskMOTION

mpiEventMaskMOTION / meiEventMaskMOTION

mpiEventMaskMOTION
Declaration

#define	mpiEventMaskMOTION(mask)
    mpiEventMaskBitSET((mask), MPIEventTypeMOTION_DONE, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeMOTION_AT_VELOCITY, 1)
Required Header stdmpi.h
Description

EventMaskMOTION sets all MPIMotion events within the event mask.

meiEventMaskMOTION
Declaration

#define	meiEventMaskMOTION(mask)	mpiEventMaskBitSET((mask),
    MEIEventTypeMOTION_OUT_OF_FRAMES, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeMOTION_RESERVED0, 1)
Required Header stdmei.h
Description

EventMaskMOTION sets all MEIMotion events within the event mask.

See Also | MPIEventMask


mpiEventMaskMOTOR and meiEventMaskMOTOR

mpiEventMaskMOTOR / meiEventMaskMOTOR

mpiEventMaskMOTOR
Declaration
#define	mpiEventMaskMOTOR(mask)
    mpiEventMaskBitSET((mask), MPIEventTypeAMP_FAULT,1), \
    mpiEventMaskBitSET((mask), MPIEventTypeHOME, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeLIMIT_ERROR, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeLIMIT_HW_NEG, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeLIMIT_HW_POS, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeLIMIT_SW_NEG, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeLIMIT_SW_POS, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeENCODER_FAULT, 1)
Required Header stdmpi.h
Description

EventMaskMOTOR sets all MPIMotor events within the event mask.

meiEventMaskMOTOR
Declaration
#define	meiEventMaskMOTOR(mask)
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER0, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER1, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER2, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER3, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER4, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER5, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER6, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_USER7, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypePOWER_FAILURE, 1), \
    mpiEventMaskBitSET((mask), MEIEventTypeLIMIT_TORQUE, 1)
Required Header stdmei.h
Description

EventMaskMOTOR sets all MEIMotor events within the event mask.

See Also | MPIEventMask


mpiEventMaskOR_ASSIGN

Declaration

#define	mpiEventMaskOR_ASSIGN(dst,src)	((dst)[0] = ((dst)[0] | (src)[0])), \
                    ((dst)[1] = ((dst)[1] | (src)[1]))
Required Header stdmpi.h
Description

EventMaskOR_ASSIGN adds all events masked by src to the event mask dst.

See Also | MPIEventMask


mpiEventMaskRECORDER

Declaration

#define	mpiEventMaskRECORDER(mask)	mpiEventMaskBitSET((mask),
    MPIEventTypeRECORDER_FULL, 1), \
    mpiEventMaskBitSET((mask), MPIEventTypeRECORDER_DONE, 1)
Required Header stdmpi.h
Description

EventMaskRECORDER sets all MPIRecorder events within the event mask.

See Also | MPIEventMask


mpiEventMaskSET

Declaration
#define mpiEventMaskSET(mask,type)
        mpiEventMaskBitSET(mask,type,1)
Required Header stdmpi.h
Description

mpiEventMaskSET sets mask to handle events of type type.

See Also | MPIEventMask | mpiEventMaskGET


mpiEventMaskSET_ALL

Declaration

#define	mpiEventMaskSET_ALL(mask,type)	((mpiEventMaskWORD(type) == 0) ? \
            ((mask)[0] |= mpiEventMaskBIT_POSITION_MASK(type) - 1) : \
            ((mask)[0] |= 0xFFFFFFFF)), \
            ((mpiEventMaskWORD(type) == 0) ? \
            ((mask)[1] |= 0x0) : \
            ((mask)[1] |= mpiEventMaskBIT_POSITION_MASK(type) - 1))
Required Header stdmpi.h
Description

EventMaskSET_ALL sets mask to handle all events whose type is enumerated less than type.

See Also | MPIEventMask


EventMgr Objects

Introduction

An EventMgr

  • Obtains asynchronous events from the Control object(s) that the EventMgr is associated with
  • Generates Event objects for enabled event sources
  • Awakens any threads that are waiting for events.
Methods
Create, Delete, Validate Methods
 | mpiEventMgrCreate | Create EventMgr object
 | mpiEventMgrDelete | Delete EventMgr object
 | mpiEventMgrValidate | Validate EventMgr object

Configuration and Information Methods
 | mpiEventMgrConfigGet | Get EventMgr config
 | mpiEventMgrConfigSet | Set EventMgr config
 | mpiEventMgrEvent | Request event notification for all Notify objects on EventMgr’s list
 | meiEventMgrServiceConfigGet | Get processes that EventMgr will service
 | meiEventMgrServiceConfigSet | Set processes that EventMgr will service

Action Methods
 | mpiEventMgrFlush | Flush pending EventMgr events
 | mpiEventMgrService | Get list of all pending asynchronous events

Relational Methods
 | List Methods- for Control Objects
 | mpiEventMgrControl | Return handle of indexth Control object in list
 | mpiEventMgrControlAppend | Append Control’s handle to list
 | mpiEventMgrControlCount | Count the number of Control objects associated with EventMgr (in list)
 | mpiEventMgrControlFirst | Return handle to first Control object in list
 | mpiEventMgrControlIndex | Return the index of a Control object in list
 | mpiEventMgrControlInsert | Insert Control handle into list
 | mpiEventMgrControlLast | Get handle to last Control object in list
 | mpiEventMgrControlListGet | Get list of Control objects associated with EventMgr
 | mpiEventMgrControlListSet | Create a list of Control objects associated with EventMgr
 | mpiEventMgrControlNext | Get handle to next Control object in list
 | mpiEventMgrControlPrevious | Get handle to previous Control object in list
 | mpiEventMgrControlRemove | Remove a Control object’s handle from list
 | List Methods- for Notify Objects
 | mpiEventMgrNotify | Return handle to a Notify object associated with EventMgr
 | mpiEventMgrNotifyAppend | Append Notify object to list
 | mpiEventMgrNotifyCount | Return number of Notify objects in list
 | mpiEventMgrNotifyFirst | Get first Notify object in list
 | mpiEventMgrNotifyIndex | Get index value for a Notify object in list
 | mpiEventMgrNotifyInsert | Place a Notify object after another Notify object in list
 | mpiEventMgrNotifyLast | Get handle to the Notify object that is last on the list
 | mpiEventMgrNotifyListGet | Get a list of Notify objects
 | mpiEventMgrNotifyListSet | Create a list of Notify objects
 | mpiEventMgrNotifyNext | Get the Notify object just after notify in list
 | mpiEventMgrNotifyPrevious | Get the Notify object just before notify in list
 | mpiEventMgrNotifyRemove | Remove a Notify object from list
Data Types
MPIEventMgrMessage
MEIEventMgrServiceConfig


MPIEventMgrMessage

MPIEventMgrMessage

typedef enum {

    MPIEventMgrMessageEVENTMGR_INVALID,
} MPIEventMgrMessage;

Description
 | MPIEventMgrMessageEVENTMGR_INVALID
 | Meaning | The MPIEventMgr handle passed to an MPIEventMgr method is invalid.
 | Possible Causes | Either the handle was never initialized or the mpiEventMgrCreate method failed.
 | Recommendations | Use mpiEventMgrValidate after mpiEventMgrCreate to see if the returned handle is valid.
Sample Code
MPIControl        control;
MPIEventMgr     eventMgr;
long                  returnValue;
…

eventMgr =
    mpiEventMgrCreate(control);
returnValue =
    mpiEventMgrValidate(eventMgr);

See Also | MPIEventMgr | mpiEventMgrCreate | mpiEventMgrValidate


MEIEventMgrServiceConfig

MEIEventMgrServiceConfig
typedef struct MEIEventMgrServiceConfig
            { long allProcesses; /* TRUE => collect events from all processes,
            else EventMgr process only */
} MEIEventMgrServiceConfig;

Description
 | allProcesses | is a boolean value. If allProcesses=TRUE, then the event manager will handle events originating from all processes. If allProcesses=FALSE, then the event manager will only handle events originating from the same process in which the event manager was created.
See Also


mpiEventMgrConfigGet

Declaration
long mpiEventMgrConfigGet(MPIEventMgr       eventMgr,
                          MPIEventMgrConfig *config,
                          void              *external)
Required Header stdmpi.h
Description

EventMgrConfigGet gets the configuration of an EventMgr object (eventMgr) and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIEventMgrConfig{} or is NULL.

Return Values
MPIMessageOK if EventMgrConfigGet successfully gets the EventMgr’s configuration and writes it into the structure(s)
See Also | mpiEventMgrConfigSet


mpiEventMgrConfigSet

Declaration
long mpiEventMgrConfigSet(MPIEventMgr       eventMgr,
                          MPIEventMgrConfig *config,
                          void              *external)
Required Header stdmpi.h
Description

EventMgrConfigSet sets (writes) the eventMgr configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIEventMgrConfig{} or is NULL.

Return Values
MPIMessageOK if EventMgrConfigSet successfully sets (writes) the EventMgr’s configuration using data from the structure(s)
See Also | mpiEventMgrConfigGet


mpiEventMgrControl

Declaration
MPIControl mpiEventMgrControl(MPIEventMgr eventMgr,
                              long        index)
Required Header stdmpi.h
Description

Returns the element at the position on the list indicated by "index".

eventMgr | a handle to the EventMgr object.
index | a position in the list.

Return Values
handle | to the indexth motion controller (Control) associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if index is less than 0 if index is greater than or equal to mpiEventMgrCount(eventMgr)
MPIMessageARG_INVALID | index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | eventMgr is an invalid handle.
See Also


mpiEventMgrControlAppend

Declaration
long mpiEventMgrControlAppend(MPIEventMgr eventMgr,
                              MPIControl  control)
Required Header stdmpi.h
Description

EventMgrControlAppend appends control to the list of motion controllers associated with an EventMgr (eventMgr). Add "control" to the end of the list.

eventMgr | a handle to the EventMgr object.
control | a handle to a Control object.

Return Values
MPIMessageOK | if EventMgrControlAppend successfully appends control to the list of motion controllers associated with an EventMgr
MPIMessageHANDLE_INVALID | Either eventMgr or control is an invalid handle.
MPIMessageOBJECT_ON_LIST | control is already on the list.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiEventMgrControlCount

Declaration
long mpiEventMgrControlCount(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

Returns the number of elements on the list.

eventMgr | a handle to the EventMgr object.

Return Values
number | of motion controllers associated with an EventMgr (eventMgr)
-1 | if eventMgr is an invalid handle
0 | if eventMgr has no associated motion controllers
See Also


mpiEventMgrControlFirst

Declaration
MPIControl mpiEventMgrControlFirst(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrControlFirst returns the first element in the list. This function can be used in conjuntion with mpiEventMgrControlNext() in order to iterate through the list. MPIHandleVOID is returned if the list is empty.

eventMgr | a handle to the EventMgr object.

Return Values
handle | to the first motion controller (Control) associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if eventMgr has no associated motion controllers
MPIMessageHANDLE_INVALID | if eventMgr is an invalid handle.

See Also | mpiEventMgrControlLast


mpiEventMgrControlInsert

Declaration
long mpiEventMgrControlInsert(MPIEventMgr eventMgr,
                              MPIControl  control,
                              MPIControl  insert)
Required Header stdmpi.h
Description

EventMgrControlInsert inserts a Control object (insert) after the Control object (control) in the list of motion controllers associated with eventMgr.
Return Values
MPIMessageOK if EventMgrControlInsert successfully inserts the Control object (insert) after another Control object (control) in the list of motion controllers
See Also


mpiEventMgrControlIndex

Declaration
long mpiEventMgrControlIndex(MPIEventMgr eventMgr,
                             MPIControl  control)
Required Header stdmpi.h
Description

EventMgrControlIndex returns the position of "control" on the list.

eventMgr | a handle to the EventMgr object.
control | a handle to a Control object.

Return Values
index | of control in the list of motion controllers associated with an EventMgr (eventMgr)
-1 | if eventMgr is invalid if control was not found in the list of motion controllers
See Also


mpiEventMgrControlLast

Declaration
MPIControl mpiEventMgrControlLast(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrControlLast returns the last element in the list.
This function can be used in conjuntion with mpiEventMgrControlPrevious() in order to iterate through the list backwards.

eventMgr | a handle to the EventMgr object.

Return Values
handle | to the last motion controller (Control) associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if eventMgr has no associated motion controllers
MPIMessageHANDLE_INVALID | if eventMgr is an invalid handle.

See Also | mpiEventMgrControlFirst


mpiEventMgrControlListGet

Declaration
long mpiEventMgrControlListGet(MPIEventMgr eventMgr,
                               long        *controlCount,
                               MPIControl  *controlList)
Required Header stdmpi.h
Description

EventMgrControlListGet returns the list of Control objects associated with an EventMgr object (eventMgr).

EventMgrControlListGet also writes the number of Control handles (in the list) to the location pointed to by controlCount, and writes an array (of controlCount Control handles) to the location pointed to by controlList.
Return Values
MPIMessageOK if EventMgrControlListGet successfully returns the list of Control objects associated with an EventMgr object
See Also | mpiEventMgrControlListSet


mpiEventMgrControlListSet

Declaration
long mpiEventMgrControlListSet(MPIEventMgr eventMgr,
                               long        controlCount,
                               MPIControl  *controlList)
Required Header stdmpi.h
Description

EventMgrControlListSet creates a list of controlCount Control objects using the Control handles specified by controlList. Any existing motion controller list is completely replaced.

The controlList parameter is the address of an array of controlCount Control handles, or is NULL (if controlCount is equal to zero).

A motion controller list can also be created incrementally (i.e., one Control at a time) by using the append and/or insert methods described in this section. The initial Control of a control list may be specified using the control parameter of mpiEventMgrCreate(...). The list methods in this section can be used to examine and manipulate a motion controller list regardless of how the list was created.
Return Values
MPIMessageOK if EventMgrControlListSet successfully creates a list of Control objects using the Control handles
See Also | mpiEventMgrControlListGet


mpiEventMgrControlNext

Declaration
MPIControl mpiEventMgrControlNext(MPIEventMgr  eventMgr,
                                  MPIControl   control)
Required Header stdmpi.h
Description

EventMgrControlNext returns the next element following "control" on the list. MPIHandleVOID is returned if "control" is the last element on the list, or if "control" is not in the list at all. This function can be used in conjuntion with mpiEventMgrControlFirst() in order to iterate through the list.

eventMgr | a handle to the EventMgr object.
control | a handle to a Control object.

Return Values
handle | to the motion controller following control in the list of motion controllers associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if control is the last motion controller
MPIMessageHANDLE_INVALID | Either eventMgr or control is an invalid handle.

See Also | mpiEventMgrControlPrevious


mpiEventMgrControlPrevious

Declaration
MPIControl  mpiEventMgrControlPrevious(MPIEventMgr eventMgr,
                                       MPIControl  control)
Required Header stdmpi.h
Description

EventMgrControlPrevious returns the previous element prior to "control" on the list. MPIHandleVOID is returned if "control" is the first element on the list, or if "control" is not in the list at all. This function can be used in conjuntion with mpiEventMgrControlLast() in order to iterate through the list backwards.

eventMgr | a handle to the EventMgr object.
control | a handle to a Control object.

Return Values
handle | to the motion controller preceding control in the list of motion controllers associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if control is the first motion controller
MPIMessageHANDLE_INVALID | Either eventMgr or control is an invalid handle.

See Also | mpiEventMgrControlNext


mpiEventMgrControlRemove

Declaration
long mpiEventMgrControlRemove(MPIEventMgr eventMgr,
                              MPIControl  control)
Required Header stdmpi.h
Description

EventMgrControlRemove removes a Control object (control) from the list of Control objects associated with eventMgr.
Return Values
MPIMessageOK if EventMgrControlRemove successfully removes a Control object from the list of Control objects associated with an EventMgr (eventMgr)
See Also | mpiEventMgrControl


mpiEventMgrCreate

Declaration
const MPIEventMgr mpiEventMgrCreate(MPIControl control)
Required Header stdmpi.h
Description

EventMgrCreate creates an EventMgr object, with control as the initial element in the list of Control objects from which the EventMgr obtains asynchronous events (control may be MPIHandleVOID).

EventMgrCreate is the equivalent of a C++ constructor.

Return Values
handle | to an EventMgr object
MPIHandleVOID | if the object could not be created

See Also | mpiEventMgrDelete | mpiEventMgrValidate


mpiEventMgrDelete

Declaration
long mpiEventMgrDelete(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrDelete deletes an EventMgr object and invalidates its handle (eventMgr). EventMgrDelete is the equivalent of a C++ destructor.

Deleting an EventMgr object does not delete any of the Control objects that supply the EventMgr with asynchronous events. However, deleting an EventMgr object will delete any unreceived events for that EventMgr.

Return Values
MPIMessageOK if EventMgrDelete successfully deletes an EventMgr object and invalidates its handle
See Also | mpiEventMgrCreate | mpiEventMgrValidate


mpiEventMgrEvent

Declaration
long mpiEventMgrEvent(MPIEventMgr    eventMgr,
                      MPIEventStatus *status)
Required Header stdmpi.h
Description

EventMgrEvent requests that the EventMgr (eventMgr) call mpiNotifyEvent(notify, status) for all Notify objects on that Event Manager’s list. Each Notify object represents a thread that has requested event notification. The Notify object will determine whether it accepts the event notification or not.

EventMgrEvent enables your application to use the Event Manager to distribute user-created events in the same way that events generated by the motion controller are distributed.
Return Values
MPIMessageOK if EventMgrEvent successfully requests that the EventMgr call mpiNotify Event(notify, status) for all Notify objects on that Event Manager’s list
See Also


mpiEventMgrFlush

Declaration
long mpiEventMgrFlush(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrFlush flushes any pending events from an EventMgr (eventMgr).
Return Values
MPIMessageOK if EventMgrFlush successfully flushes any pending EventMgr events
See Also


mpiEventMgrNotify

Declaration
MPINotify mpiEventMgrNotify(MPIEventMgr eventMgr,
                            long        index)
Required Header stdmpi.h
Description

EventMgrNotify returns the element at the position on the list indicated by "index".

eventMgr | a handle to the EventMgr object.
index | a position in the list.

Return Values
handle | to the indexth Notify object associated with an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if index is less than 0 if index is greater than or equal to mpiEventMgrCount(eventMgr)
MPIMessageARG_INVALID | index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | eventMgr is an invalid handle.
See Also


mpiEventMgrNotifyAppend

Declaration
long mpiEventMgrNotifyAppend(MPIEventMgr eventMgr,
                             MPINotify   notify)
Required Header stdmpi.h
Description

EventMgrNotifyAppend appends a Notify object (notify) to the list of Notify objects maintained by an EventMgr object (eventMgr).

eventMgr | a handle to the EventMgr object.
notify | a handle to a Notify object.

Return Values
MPIMessageOK | if EventMgrNotifyAppend successfully appends a Notify object to the list of Notify objects maintained by an EventMgr object
MPIMessageHANDLE_INVALID | Either eventMgr or notify is an invalid handle.
MPIMessageOBJECT_ON_LIST | if notify is already on the list.
MPIMessageNO_MEMORY | if not enough memory was available.
See Also


mpiEventMgrNotifyCount

Declaration
long mpiEventMgrNotifyCount(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrNotifyCount returns the number of elements on the list.

eventMgr | a handle to the EventMgr object.

Return Values
number | of Notify objects in the list (of Notify objects) maintained by an EventMgr (eventMgr)
-1 | if eventMgr is invalid
0 | if the list (of Notify objects) is empty
See Also


mpiEventMgrNotifyFirst

Declaration
MPINotify mpiEventMgrNotifyFirst(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrNotifyFirst returns the first element in the list. This function can be used in conjuntion with mpiEventMgrNotifyNext() in order to iterate through the list.

eventMgr | a handle to the EventMgr object.

Return Values
handle | to the first Notify object in the list (of Notify objects) maintained by an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if the list (of Notify objects) is empty
MPIMessageHANDLE_INVALID | if eventMgr is an invalid handle.

See Also | mpiEventMgrNotifyLast


mpiEventMgrNotifyInsert

Declaration
long mpiEventMgrNotifyInsert(MPIEventMgr eventMgr,
                             MPINotify   notify,
                             MPINotify   insert)
Required Header stdmpi.h
Description

EventMgrNotifyInsert places a Notify object (insert) after another Notify object (notify) in the list (of Notify objects) maintained by an EventMgr object (eventMgr).

Return Values
MPIMessageOK if EventMgrNotifyInsert successfully places a Notify object after another Notify object in the list of Notify objects
See Also


mpiEventMgrNotifyIndex

Declaration
long mpiEventMgrNotifyIndex(MPIEventMgr eventMgr,
                            MPINotify   notify)
Required Header stdmpi.h
Description

EventMgrNotifyIndex returns the position of "notify" on the list.

eventMgr | a handle to the EventMgr object.
notify | a handle to the EventMgr object.

Return Values
index | of notify in the list (of Notify objects) maintained by an EventMgr (eventMgr)
-1 | if eventMgr is invalid if notify was not found in the list
See Also


mpiEventMgrNotifyLast

Declaration
MPINotify mpiEventMgrNotifyLast(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description

EventMgrNotifyLast returns the last element in the list. This function can be used in conjuntion with mpiEventMgrNotifyPrevious() in order to iterate through the list backwards.

eventMgr | a handle to the EventMgr object.

Return Values
handle | to the last Notify object in the list maintained by an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if the list (of Notify objects) is empty
MPIMessageHANDLE_INVALID | if eventMgr is an invalid handle.

See Also | mpiEventMgrNotifyFirst


mpiEventMgrNotifyListGet

Declaration
long mpiEventMgrNotifyListGet(MPIEventMgr eventMgr,
                              long        *notifyCount,
                              MPINotify   *notifyList)
Required Header stdmpi.h
Description

EventMgrNotifyListGet returns the list of Notify objects for an EventMgr object (eventMgr). EventMgrNotifyListGet also sets (writes) the number (of Notify objects in the list) to the location pointed to by notifyCount, and sets (writes) an array (of notifyCount Notify handles) to the contents of the location pointed to by notifyList.
Return Values
MPIMessageOK if EventMgrNotifyListGet successfully returns the list of Notify objects for an EventMgr object
See Also | mpiEventMgrNotifyListSet


mpiEventMgrNotifyListSet

Declaration
long mpiEventMgrNotifyListSet(MPIEventMgr  eventMgr,
                              long         notifyCount,
                              MPINotify    *notifyList)
Required Header stdmpi.h
Description

EventMgrNotifyListSet creates a list of Notify objects, where the number of Notify objects is specified by notifyCount, using the Notify handles specified by notifyList. The notifyList argument is the address of an array of notifyCount Notify handles, or is NULL if notifyCount is zero. Any existing notify object list is completely replaced.

You can also create a Notify object list incrementally (i.e., one Notify object is created at a time), by using the EventMgrAppend and/or EventMgrInsert methods. After creating a list of Notify objects, use the EventMgrList methods to examine and manipulate the list, regardless of how the list was created.

Return Values
MPIMessageOK if EventMgrNotifyListSet successfully creates a list of Notify objects using the Notify handles specified by notifyList
See Also | mpiEventMgrNotifyListGet


mpiEventMgrNotifyNext

Declaration
MPINotify mpiEventMgrNotifyNext(MPIEventMgr eventMgr,
                                MPINotify   notify)
Required Header stdmpi.h
Description

EventMgrNotifyNext returns the next element following "notify" on the list. This function can be used in conjuntion with mpiEventMgrNotifyFirst() in order to iterate through the list.

eventMgr | a handle to the EventMgr object.
notify | a handle to a Notify object.

Return Values
handle | to the Notify object after another Notify object (notify) in the list (of Notify objects) maintained by an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if notify is the last notify object in the list
MPIMessageHANDLE_INVALID | Either eventMgr or notify is an invalid handle.

See Also | mpiEventMgrNotifyPrevious


mpiEventMgrNotifyPrevious

Declaration
MPINotify mpiEventMgrNotifyPrevious(MPIEventMgr eventMgr,
                                    MPINotify   notify)
Required Header stdmpi.h
Description

EventMgrNotifyPrevious returns the previous element prior to "notify" on the list. This function can be used in conjuntion with mpiEventMgrNotifyLast() in order to iterate through the list backwards.

eventMgr | a handle to the EventMgr object.
notify | a handle to a Notify object.

Return Values
handle | to the Notify object just before another Notify object (notify) in the list (of Notify objects) maintained by an EventMgr (eventMgr)
MPIHandleVOID | if eventMgr is invalid if notify is the first Notify object in the list
MPIMessageHANDLE_INVALID | either eventMgr or notify is an invalid handle

See Also | mpiEventMgrNotifyNext


mpiEventMgrNotifyRemove

Declaration
long mpiEventMgrNotifyRemove(MPIEventMgr eventMgr,
                             MPINotify   notify)
Required Header stdmpi.h
Description

EventMgrNotifyRemove removes a Notify object (notify) from the list of Notify objects maintained by an EventMgr object (eventMgr).

Return Values
MPIMessageOK if EventMgrNotifyRemove successfully removes a Notify object from the list of Notify objects maintained by an EventMgr object
See Also


mpiEventMgrService

Declaration
long mpiEventMgrService(MPIEventMgr eventMgr,
                        MPIControl  control)
Required Header stdmpi.h
Description

EventMgrService obtains all pending asynchronous events from the motion controller (control).

Events generated by sources for which no prior call to mpiEventMgrEnable(...) has been made are discarded. Events generated by enabled sources are returned in First-In/First-Out (FIFO) order each time a thread calls mpiEventMgrWait(...).

Typically, after a motion controller generates a hardware interrupt, the Interrupt Service Routine (ISR) is invoked, and the ISR in turn invokes mpiEventMgrService(...) directly or indirectly.

If "control" is | Then
MPIHandleVOID | events will be obtained from all motion controllers on the EventMgr’s (eventMgr) control list
valid | control must also be present on the EventMgr’s (eventMgr) control list
Return Values
MPIMessageOK if EventMgrService successfully obtains all pending asynchronous events from the motion controller
See Also | meiEventMgrServiceConfigGet | meiEventMgrServiceConfigSet


meiEventMgrServiceConfigGet

Declaration

           long meiEventMgrServiceConfigGet(MPIEventMgr              eventMgr,
                                            MEIEventMgrServiceConfig *config)
Required Header stdmei.h
Description

EventMgrServiceConfigGet gets the configuration of an EventMgr object (eventMgr) and writes it into the structure pointed to by config.
Return Values
MPIMessageOK if EventMgrServiceConfigGet successfully gets the EventMgr’s configuration and writes it into the structure(s).
See Also


meiEventMgrServiceConfigSet

Declaration

            long meiEventMgrServiceConfigSet(MPIEventMgr              eventMgr,
                                             MEIEventMgrServiceConfig *config)
Required Header stdmei.h
Description

EventMgrServiceConfigSet sets (writes) the flash configuration for an EventMgr object (eventMgr) using data from the structure pointed to by config.

Return Values
MPIMessageOK if EventMgrServiceConfigSet successfully sets (writes) the EventMgr’s flash configuration using data from the structure(s)
See Also | meiEventMgrServiceConfigGet | mpiEventMgrService


mpiEventMgrValidate

Declaration
long mpiEventMgrValidate(MPIEventMgr eventMgr)
Required Header stdmpi.h
Description EventMgrValidate validates an EventMgr object and its handle (eventMgr).
Return Values
MPIMessageOK if EventMgr is a handle to a valid object.
See Also | mpiEventMgrCreate | mpiEventMgrDelete


Filter Objects

Introduction

A Filter object manages a single filter on a controller. It represents the control algorithm used to control a motor in a closed-loop system. The Filter contains an algorithm, a set of coefficients, inputs, and an output. Its primary responsibility is to take the difference between the command and actual positions and then calculate the output based on the control algorithm and coefficients.

For simple systems, there is a one-to-one relationship between the Axis, Filter, and Motor objects.
Methods
Create, Delete, Validate Methods
 | mpiFilterCreate | Create Filter object
 | mpiFilterDelete | Delete Filter object
 | mpiFilterValidate | Validate Filter object

Configuration and Information Methods
 | mpiFilterConfigGet | Get Filter configuration
 | mpiFilterConfigSet | Set Filter configuration
 | mpiFilterFlashConfigGet | Get flash configuration for Filter
 | mpiFilterFlashConfigSet | Set flash configuration for Filter
 | mpiFilterGainGet | Get gain coefficients
 | mpiFilterGainSet | Set current gain index
 | mpiFilterGainIndexGet | Get current gain index
 | mpiFilterGainIndexSet | Set current gain index
 | mpiFilterStatus | Get Filter’s status

Memory Methods
 | mpiFilterMemory | Get address to Filter memory
 | mpiFilterMemoryGet | Copy data from Filter memory to application memory
 | mpiFilterMemorySet | Copy data from application memory to Filter memory

Relational Methods
 | mpiFilterAxisMapGet | Get object map of axes associated with Filter
 | mpiFilterAxisMapSet | Set axes associated with Filter
 | mpiFilterControl | Return handle of Control that is assoiciated with Filter
 | mpiFilterMotorMapGet | Get object map of Motors associated with Filter
 | mpiFilterMotorMapSet | Set Motors to be associated with Filter
 | mpiFilterNumber | Get index of Filter (for Control list)
Action Methods
 | mpiFilterIntergratorReset | Reset the integrators of filter.

Data Types
MPIFilterCoeff
MPIFilterConfig / MEIFilterConfig
MPIFilterGain
MEIFilterGainIndex
MEIFilterGainPID
MEIFilterGainPIDCoeff
MEIFilterGainPIV
MEIFilterGainPIVCoeff
MEIFilterGainSercos
MEIFilterGainSercosCoeff
MPIFilterMessage
Constants
MPIFilterCoeffCOUNT_MAX
MPIFilterGainCOUNT_MAX


High / Low Output Limits (MEIFilterGainPID and PIV)

Special Note: High / Low Output Limits (MEIFilterGainPID and PIV)

In the 19990820 release, the MEIFilterGainPID and MEIFilterGainPIV structures were expanded to support High and Low output limits for PID and PIV algorithms. The "High" output limit prevents the filter output from exceeding the "High" value. The "Low" output limit prevents the filter output from falling below the "Low" value. This feature will allow an application to have upper and lower limits which are not centered on zero volts. If the "High" and "Low" values have the same sign, then the output will be limited to either the positive or negative range bounded by "High" and "Low".

The standard Output Limit is still valid. The controller will simultaneously use the standard Output Limit and the High / Low Output Limits to bound the output. The limits, (standard or high or low) that are closest to zero will be used as the boundary for the output.

Return to MEIFilterGainPID or MEIFilterGainPIV


MPIFilterConfig / MEIFilterConfig

MPIFilterConfig

typedef struct MPIFilterConfig {
    long		gainIndex;
    MPIFilterGain	gain[MPIFilterGainCOUNT_MAX];
    long		sercosGainIdnMap[MPIFilterCoeffCOUNT_MAX];

    MPIObjectMap	axisMap;
    MPIObjectMap	motorMap;
} MPIFilterConfig;

Description
 | gainIndex | gain table index. Gain tables number 0 to MPIFilterGainCOUNT_MAX -1 (MPIFilterGainCOUNT_MAX = 4).
 | gain | see MPIFilterGain
 | sercosGainIdnMap | Map of Sercos servo loop gains. MPIFilterCoeffCOUNT_MAX coefficients in the map (MPIFilterCoeffCOUNT_MAX = 20).
 | axisMap | see MPIObjectMap
 | motorMap | see MPIObjectMap

MEIFilterConfig
typedef struct MEIFilterConfig {
    MEIXmpAlgorithm	Algorithm;

    MEIXmpAxisInput	Axis[MEIXmpFilterAxisInputs];

    long		*VelPositionPtr;
    long		*AuxInput[MEIXmpFilterAuxInputs];

    MEIXmpSwitchType	 GainSwitchType;
    float	   	 GainDelay;
    long		 GainWindow;
    MEIXmpSwitchType 	 PPISwitchType;
    MEIXmpPPIMode 	 PPIMode;
    float		 PPIDelay;
    long		 PPIWindow;
    MEIXmpIntResetConfig ResetIntegratorConfig;
    float		 ResetIntegratorDelay;

    MEIXmpPostFilter	 PostFilter;
} MEIFilterConfig;

Description
 | Algorithm | This value defines the algorithm that the filter is executing every servo cycle.
 | Axis[MEIXmpFilterAxisInputs] | This array defines the axis (pointer to the axis) and coefficient for the position input into the filter. The input to the filter is the position error of the axis, which is multiplied by the coefficient defined by the Axis array.
 | VelPositionPtr | Velocity position pointer to an encoder input for algorithms that require a velocity encoder position input (such as the PIV algorithm).
 | AuxInput[MEIXmpFilterAuxInputs] | This array is a place holder for additional filter inputs from analog sources. This is currently not supported and is reserved for future use.
 | GainSwitchType | Value to define the gain table switch type. Not implemented in standard firmware.
 | GainDelay | Custom Delay not implemented in standard firmware.
 | GainWindow | Custom Delay not implemented in standard firmware.
 | PPISwitchType | Value to define the gain switch type for PPI mode. Not implemented in standard firmware.
 | PPIMode | Value to define the PPI switch mode. Not implemented in standard firmware.
 | PPIDelay | Custom Delay not implemented in standard firmware.
 | PPIWindow | Custom Window not implemented in standard firmware.
 | ResetIntegratorConfig | Value to define the integrator's reset configuration. Not supported in standard firmware.
 | ResetIntegratorDelay | Value to define the integrator's reset delay. Not supported in standard firmware.
 | PostFilter | This array defines the configuration for the filter's post filter (the type, the length and values for the post filter coefficients).
See Also


MPIFilterCoeff

MPIFilterCoeff

typedef union {
    float	f;
    long	l;
} MPIFilterCoeff;

Description
 | f | float coefficient
 | l | long coefficient

See Also | MPIFilterCoeffCOUNT_MAX


MPIFilterCoeffCOUNT_MAX

MPIFilterCoeffCOUNT_MAX

#define MPIFilterCoeffCOUNT_MAX (20)

Description
 | FilterCoeffCOUNT_MAX is a constant that defines the maximum number of filter coefficients contained in a gain table.

See Also | MPIFilterCoeff


MPIFilterGain

MPIFilterGain

typedef struct MPIFilterGain {
    MPIFilterCoeff	coeff[MPIFilterCoeffCOUNT_MAX];
} MPIFilterGain;

Description
 | coeff | see MPIFilterCoeff

See Also | MPIFilterGainCOUNT_MAX


MPIFilterGainCOUNT_MAX

MPIFilterGainCOUNT_MAX

#define MPIFilterGainCOUNT_MAX (20)

Description
 | FilterGainCOUNT_MAX is a constant that defines the maximum number of filter gain tables. The first gain table is used by the standard filter types (all filter types except for the user filter type as defined by the structure MEIXmpAlgorithm). Additional gain tables can be used for manual or automatic gain switching. For firmware that implements automatic gain switching, please contact Motion Engineering. Manual gain switching can be accomplished by specifying the gainIndex of the mpiFilterConfig structure using the mpiFilterConfigSet method. Valid gainIndex values range from 0 to MPIFilterGainCOUNT_MAX.

See Also | MPIFilterGain


MEIFilterGainIndex

MEIFilterGainIndex

typedef enum {	/* NOTE: These *must* match MEIXmpGain{}!!! */
    MEIFilterGainIndexINVALID,

    MEIFilterGainIndexSTOPPING2,  /* MEIXmpGainSTOPPED2 */
    MEIFilterGainIndexSTOPPING1,  /* MEIXmpGainSTOPPED1 */
    MEIFilterGainIndexSETTLING,	  /* MEIXmpGainSETTLING */
    MEIFilterGainIndexMOVING,	  /* MEIXmpGainMOVING */
    MEIFilterGainIndexLAST,	  /* MEIXmpGainLAST */
    MEIFilterGainIndexALL,
    MEIFilterGainIndexDEFAULT	= MEIFilterGainIndexSTOPPING2,
} MEIFilterGainIndex;

Description
 | FilterGainIndex is a constant enum structure defining gain indexes used to select one of the four filter gain tables.
See Also


MEIFilterGainPID

MEIFilterGainPID

typedef	struct MEIFilterGainPID {
    struct {
    float	proportional;	/* Kp */
    float	integral;	/* Ki */
    float	derivative;	/* Kd */
    } gain;
    struct {
        float	position;	/* Kpff */
        float	velocity;	/* Kvff */
        float	acceleration;	/* Kaff */
        float	friction;	/* Kfff */
    } feedForward;
    struct {
        float	moving;		/* MovingIMax */
        float	rest;		/* RestIMax */
    } integrationMax;
    long	dRate;		/* DRate */
    struct {
        float	limit;		/* OutputLimit */
        float	limitHigh;	/* OutputLimitHigh */
        float	limitLow;	/* OutputLimitLow */
        float	offset;		/* OutputOffset */
    } output;
    struct {
        float	positionFFT;	/* Ka0 */
        float	filterFFT;	/* Ka1 */
        float	velocityFFT;	/* Ka2 */
    } noise;
} MEIFilterGainPID;

Description
 | FilterGainPID is a structure that defines the filter coefficients for the PID filter algorithm.

See Also | High/Low Output Limits section for special instructions regarding MEIFilterGainPID. MEIFilterGainPIDCoeff


MEIFilterGainPIDCoeff

MEIFilterGainPIDCoeff

typedef		enum {
    MEIFilterGainPIDCoeffINVALID = -1,

    MEIFilterGainPIDCoeffGAIN_PROPORTIONAL,	/* Kp */
    MEIFilterGainPIDCoeffGAIN_INTEGRAL,		/* Ki */
    MEIFilterGainPIDCoeffGAIN_DERIVATIVE,	/* Kd */
    MEIFilterGainPIDCoeffFEEDFORWARD_POSITION,	/* Kpff */
    MEIFilterGainPIDCoeffFEEDFORWARD_VELOCITY,	/* Kvff */
    MEIFilterGainPIDCoeffFEEDFORWARD_ACCELERATION,/* Kaff */
    MEIFilterGainPIDCoeffFEEDFORWARD_FRICTION,	/* Kfff */
    MEIFilterGainPIDCoeffINTEGRATIONMAX_MOVING,	/* MovingIMax */
    MEIFilterGainPIDCoeffINTEGRATIONMAX_REST,	/* RestIMax */
    MEIFilterGainPIDCoeffDRATE,			/* DRate */
    MEIFilterGainPIDCoeffOUTPUT_LIMIT,		/* OutputLimit */
    MEIFilterGainPIDCoeffOUTPUT_LIMITHIGH,	/* OutputLimitHigh */
    MEIFilterGainPIDCoeffOUTPUT_LIMITLOW,	/* OutputLimitLow */
    MEIFilterGainPIDCoeffOUTPUT_OFFSET,		/* OutputOffset */
    MEIFilterGainPIDCoeffNOISE_POSITIONFFT,	/* Ka0 */
    MEIFilterGainPIDCoeffNOISE_FILTERFFT,	/* Ka1 */
    MEIFilterGainPIDCoeffNOISE_VELOCITYFFT,	/* Ka2 */

} MEIFilterGainPIDCoeff;

Description
 | FilterGainPIDCoeff is a structure of enums that defines the filter coefficients for the PID filter algorithm.

See Also | MEIFilterGainPID


MEIFilterGainPIV

MEIFilterGainPIV

typedef		struct MEIFilterGainPIV {
    struct {
        float	proportional;	/* Kpp */
        float	integral;	/* Kip */
    } gainPosition;
    struct {
        float	proportional;	/* Kpv */
    } gainVelocity1;
    struct {
        float	position;	/* Kpff */
        float	velocity;	/* Kvff */
        float	acceleration;	/* Kaff */
        float	friction;	/* Kfff */
    } feedForward;
    struct {
        float	moving;		/* MovingIMax */
        float	rest;		/* RestIMax */
    } integrationMax;
    struct {
        float	feedback;	/* Kdv */
    } gainVelocity2;
    struct {
        float	limit;		/* OutputLimit */
        float	limitHigh;	/* OutputLimitHigh */
        float	limitLow;	/* OutputLimitLow */
        float	offset;		/* OutputOffset */
    } output;
    struct {
        float	integral;	/* Kiv */
        float	integrationMax;	/* VintMax */
    } gainVelocity3;
    struct {
        float	positionFFT;	/* Ka0 */
        float	filterFFT;	/* Ka1 */
    } noise;
} MEIFilterGainPIV;

Description
 | FilterGainPIV is a structure that defines the filter coefficients for the PIV filter algorithm.

See Also | High/Low Output Limits section for special instructions regarding MEIFilterGainPIV. MEIFilterGainPIVCoeff


MEIFilterGainPIVCoeff

MEIFilterGainPIVCoeff

typedef		enum {
    MEIFilterGainPIVCoeffINVALID = -1,

    MEIFilterGainPIVCoeffGAINPOSITION_PROPORTIONAL,	/* Kpp */
    MEIFilterGainPIVCoeffGAINPOSITION_INTEGRAL,		/* Kip */

    MEIFilterGainPIVCoeffGAINVELOCITY_PROPORTIONAL,	/* Kpv */

    MEIFilterGainPIVCoeffFEEDFORWARD_POSITION,		/* Kpff */
    MEIFilterGainPIVCoeffFEEDFORWARD_VELOCITY,		/* Kvff */
    MEIFilterGainPIVCoeffFEEDFORWARD_ACCELERATION,	/* Kaff */
    MEIFilterGainPIVCoeffFEEDFORWARD_FRICTION,		/* Kfff */

    MEIFilterGainPIVCoeffINTEGRATIONMAX_MOVING,		/* MovingIMax */
    MEIFilterGainPIVCoeffINTEGRATIONMAX_REST,		/* RestIMax */

    MEIFilterGainPIVCoeffGAINVELOCITY_FEEDBACK,		/* Kdv */

    MEIFilterGainPIVCoeffOUTPUT_LIMIT,		/* OutputLimit */
    MEIFilterGainPIVCoeffOUTPUT_LIMITHIGH,	/* OutputLimitHigh */
    MEIFilterGainPIVCoeffOUTPUT_LIMITLOW,	/* OutputLimitLow */
    MEIFilterGainPIVCoeffOUTPUT_OFFSET,		/* OutputOffset */

    MEIFilterGainPIVCoeffGAINVELOCITY_INTEGRAL,		/* Kiv */
    MEIFilterGainPIVCoeffGAINVELOCITY_INTEGRATIONMAX,	/* Vintmax */

    MEIFilterGainPIVCoeffNOISE_POSITIONFFT,		/* Ka0 */
    MEIFilterGainPIVCoeffNOISE_FILTERFFT,		/* Ka1 */

} MEIFilterGainPIVCoeff;

Description
 | FilterGainPIVCoeff is a structure of enums that defines the filter coefficients for the PIV filter algorithm.

See Also | High/Low Output Limits section for special instructions regarding MEIFilterGainPIV. MEIFilterGainPIV


MEIFilterGainSercos

MEIFilterGainSercos

typedef	struct MEIFilterGainSercos {
    long	Coeff[MEIXmpSercosCoeffMAX];
    struct {
        long	velocity;
        long	acceleration;
        long	friction;
        float	scaler;
    } feedForward;
} MEIFilterGainSercos;

Description
 | FilterGainSercos is a structure that defines the filter coefficients for the SERCOS filter algorithm.

See Also | MEIFilterGainSercosCoeff


MEIFilterGainSercosCoeff

MEIFilterGainSercosCoeff

typedef	enum {
    MEIFilterGainSercosCoeffINVALID = -1,
    MEIFilterGainSercosCoeff0,
    MEIFilterGainSercosCoeff1,
    MEIFilterGainSercosCoeff2,
    MEIFilterGainSercosCoeff3,
    MEIFilterGainSercosCoeff4,
    MEIFilterGainSercosCoeff5,
    MEIFilterGainSercosCoeff6,
    MEIFilterGainSercosCoeff7,
    MEIFilterGainSercosCoeff8,
    MEIFilterGainSercosCoeff9,
    MEIFilterGainSercosCoeff10,
    MEIFilterGainSercosCoeff11,
    MEIFilterGainSercosCoeff12,
    MEIFilterGainSercosCoeff13,
    MEIFilterGainSercosCoeff14,
    MEIFilterGainSercosCoeff15,
    MEIFilterGainSercosCoeffFEED_FORWARD_VELOCITY,
    MEIFilterGainSercosCoeffFEED_FORWARD_ACCELERATION,
    MEIFilterGainSercosCoeffFEED_FORWARD_FRICTION,
    MEIFilterGainSercosCoeffFEED_FORWARD_SCALER,
    MEIFilterGainSercosCoeffLAST,
    MEIFilterGainSercosCoeffFIRST = MEIFilterGainSercosCoeffINVALID + 1
} MEIFilterGainSercosCoeff;

Description
 | FilterGainSercosCoeff is a structure of enums that defines the filter coefficients for the PID filter algorithm.

See Also | MEIFilterGainSercos


MPIFilterMessage

MPIFilterMessage

typedef enum {

    MPIFilterMessageFILTER_INVALID,
    MPIFilterMessageINVALID_ALGORITHM,

} MPIFilterMessage;

Description
 | MPIFilterMessageFILTER_INVALID | This message indicates that an invalid filter number has been specified. This message is returned by the mpiFilterCreate method when the filter number is < 0 or > MEIXmpMAX_Filters
 | MPIFilterMessageINVALID_ALGORITHM | This message indicates that an invalid filter algorithm has been specified.

See Also | mpiFilterCreate


mpiFilterAxisMapGet

Declaration
long mpiFilterAxisMapGet(MPIFilter    filter,
                         MPIObjectMap *map)
Required Header stdmpi.h
Description

FilterAxisMapGet gets the object map of the Axes that are associated with a Filter (filter), and writes it into the structure pointed to by map.
Return Values
MPIMessageOK if FilterAxisMapGet successfully writes the object map of Axes to the structure
See Also | mpiFilterAxisMapSet


mpiFilterAxisMapSet

Declaration
long mpiFilterAxisMapSet(MPIFilter    filter,
                         MPIObjectMap map)
Required Header stdmpi.h
Description

FilterAxisMapSet sets the Axes associated with a Filter (filter), using data from the object map specified by map.

Return Values
MPIMessageOK if FilterAxisMapSet successfully sets the Axes using the object map
See Also | mpiFilterAxisMapGet


mpiFilterConfigGet

Declaration
long mpiFilterConfigGet(MPIFilter       filter,
                        MPIFilterConfig *config,
                        void            *external)
Required Header stdmpi.h
Description

FilterConfigGet gets a Filter’s (filter) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Filter’s configuration information in external is in addition to the Filter’s configuration information in config, i.e, the Filter’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIFilterConfig{} or is NULL.
Return Values
MPIMessageOK if FilterConfigGet successfully writes the Filter’s configuration to the structure(s)
See Also | mpiFilterConfigSet | MEIFilterConfig


mpiFilterConfigSet

Declaration
long mpiFilterConfigSet(MPIFilter       filter,
                        MPIFilterConfig *config,
                        void            *external)
Required Header stdmpi.h
Description

FilterConfigSet sets a Filter’s (filter) configuration using data from the structure pointed to by config, and from the implementation-specific structure pointed to by external (if external is not NULL).

The Filter’s configuration information in external is in addition to the Filter’s configuration information in config, i.e, the Filter’s configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIFilterConfig{} or is NULL.
Return Values
MPIMessageOK if FilterConfigSet successfully sets the Filter’s configuration using data from the structure(s)
See Also | mpiFilterConfigGet | MEIFilterConfig


mpiFilterControl

Declaration
const MPIControl mpiFilterControl(MPIFilter filter)
Required Header stdmpi.h
Description

FilterControl returns a handle to the motion controller (Control object) associated with the specified Filter object (filter).

Return Values
handle | to a Control object that a Filter object is associated with
MPIHandleVOID | if the Filter object is invalid
See Also


mpiFilterCreate

Declaration
const MPIFilter mpiFilterCreate(MPIControl  control,
                                long        number)
Required Header stdmpi.h
Description

FilterCreate creates a Filter object associated with a filter (number), that is located on a motion controller (control).
FilterCreate is the equivalent of a C++ constructor.

Return Values
handle | to an Filter object
MPIHandleVOID | if the Filter object could not be created

See Also | mpiFilterDelete | mpiFilterValidate


mpiFilterDelete

Declaration
long mpiFilterDelete(MPIFilter filter)
Required Header stdmpi.h
Description

FilterDelete deletes a Filter object and invalidates its handle (filter). FilterDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if FilterDelete successfully deletes a Filter object and invalidates its handle
See Also | mpiFilterCreate | mpiFilterValidate


mpiFilterFlashConfigGet

Declaration
long mpiFilterFlashConfigGet(MPIFilter       filter,
                             void            *flash,
                             MPIFilterConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

FilterFlashConfigGet gets a Filter’s (filter) flash configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Filter’s flash configuration information in external is in addition to the Filter’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIFilterConfig{} or is NULL.

Return Values
MPIMessageOK if FilterFlashConfigGet successfully writes the Filter’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiFilterFlashConfigSet |MEIFilterConfig


mpiFilterFlashConfigSet

Declaration
long mpiFilterFlashConfigSet(MPIFilter       filter,
                             void            *flash,
                             MPIFilterConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

FilterFlashConfigSet sets a Filter’s (filter) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Filter’s flash configuration information in external is in addition to the Filter’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIFilterConfig{} or is NULL.
Return Values
MPIMessageOK if FilterFlashConfigSet successfully sets the Filter’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiFilterFlashConfigGet | MEIFilterConfig


mpiFilterGainGet

Declaration
long mpiFilterGainGet(MPIFilter     filter,
                      long          gainIndex,
                      MPIFilterGain *gain)
Required Header stdmpi.h
Description

FilterGainGet gets the gain coefficients of a Filter (filter, for the gain index specified by gainIndex) and writes them into the structure pointed to by gain.
Return Values
MPIMessageOK if FilterGainGet successfully writes the gain coefficients to the structure
See Also | mpiFilterGainSet


mpiFilterGainIndexGet

Declaration
long mpiFilterGainIndexGet(MPIFilter filter,
                           long      *gainIndex)
Required Header stdmpi.h
Description

FilterGainIndexGet gets the current gain index of a Filter (filter) and writes it to the location pointed to by gainIndex.

Return Values
MPIMessageOK if FilterGainIndexGet successfully writes the gain index to the location
See Also | mpiFilterGainIndexSet


mpiFilterGainIndexSet

Declaration
long mpiFilterGainIndexSet(MPIFilter filter,
                           long      gainIndex)
Required Header stdmpi.h
Description

FilterGainIndexSet sets the current gain index of a Filter (filter) to gainIndex.
Return Values
MPIMessageOK if FilterGainIndexSet successfully sets the current gain index to gainIndex
See Also | mpiFilterGainIndexGet


mpiFilterGainSet

Declaration
long mpiFilterGainSet(MPIFilter     filter,
                      long          gainIndex,
                      MPIFilterGain *gain)
Required Header stdmpi.h
Description

FilterGainSet sets the gain coefficients of a Filter (filter, for the gain index specified by gainIndex) using data from the structure pointed to by gain.

Return Values
MPIMessageOK if FilterGainSet successfully sets the gain coefficients of a Filter using data from the structure
See Also | mpiFilterGainGet


mpiFilterIntegratorReset

Declaration
long mpiFilterIntegratorReset(MPIFilter filter)
Required Header stdmpi.h
Description

FilterIntegratorReset resets the integrators of filter.

Return Values
MPIMessageOK | if mpiFilterIntegratorReset successfully clears the integrators of filter.
MPIFilterMessageINVALID_ALGORITHM | if the filter's current algorithm does not use integrators.

Sample Code

/* Enable the amplifier for every motor attached to a motion supervisor */
void motionAmpEnable(MPIMotion	motion)
{
    MPIControl		control;
    MPIAxis			axis;
    MPIMotor		motor;
    MPIFilter		filter;
    MPIObjectMap	map;
    MPIObjectMap	motionMotorMap;
    long			motorIndex;
    long			filterIndex;
    long			returnValue;
    double			position;
    long			enableState;

    /* Get the controller handle */
    control = mpiMotionControl(motion);

    for (axis =  mpiMotionAxisFirst(motion);
         axis != MPIHandleVOID;
         axis =  mpiMotionAxisNext(motion, axis)) {

        /* Get the object map for the motors */
        returnValue = mpiAxisMotorMapGet(axis, &map);
        msgCHECK(returnValue);

        /* Add map to motionMotorMap */
        motionMotorMap |= map;
    }

    /* For every motor ... */
    for (motorIndex = 0; motorIndex < MEIXmpMAX_Motors; motorIndex++) {

        if (mpiObjectMapBitGET(motionMotorMap, motorIndex)) {

            /* Create motor handle */
            motor = mpiMotorCreate(control, motorIndex);
            msgCHECK(mpiMotorValidate(motor));

            /* Get the state of the amplifier */
            returnValue = mpiMotorAmpEnableGet(motor, &enableState);
            msgCHECK(returnValue);

            /* If the amplifier is disabled ... */
            if (enableState == FALSE) {

                /* For every axis */
                for (axis =  mpiMotionAxisFirst(motion);
                     axis != MPIHandleVOID;
                     axis =  mpiMotionAxisNext(motion, axis)) {

                    /* Get the object map for the motors */
                    returnValue = mpiAxisMotorMapGet(axis, &map);
                    msgCHECK(returnValue);

                    /* If axis is attached to motor ... */
                    if (mpiObjectMapBitGET(map, motorIndex)) {

                        /* Get the actual position of the axis */
                        returnValue = mpiAxisActualPositionGet(axis, &position);
                        msgCHECK(returnValue);

                        /* Set command position equal to actual position */
                        returnValue = mpiAxisCommandPositionSet(axis, position);
                        msgCHECK(returnValue);
                    }
                }

                /* Get the object map for the filters */
                returnValue = mpiMotorFilterMapGet(motor, &map);
                msgCHECK(returnValue);

                /* For every filter ... */
                for (filterIndex = 0;
                     filterIndex < MEIXmpMAX_Filters;
                     filterIndex++) {

                    if (mpiObjectMapBitGET(map, filterIndex)) {

                        /* Create filter handle */
                        filter = mpiFilterCreate(control, filterIndex);
                        msgCHECK(mpiFilterValidate(filter));

                        /* Reset integrator */
                        returnValue = mpiFilterIntegratorReset(filter);
                        msgCHECK(returnValue);

                        /* Delete filter handle */
                        returnValue = mpiFilterDelete(filter);
                        msgCHECK(returnValue);
                    }
                }

                /* Enable the amplifier */
                returnValue = mpiMotorAmpEnableSet(motor, TRUE);
                msgCHECK(returnValue);
            }

            /* Delete motor handle */
            returnValue = mpiMotorDelete(motor);
            msgCHECK(returnValue);
        }
    }
}

See Also | MPIFilter | MEIFilterConfig | MEIFilterGainPID | MEIFilterGainPIV mpiAxisActualPositionGet | mpiAxisCommandPositionSet

Troubleshooting / Helpful Hints

If an axis is not in an error state and the filter associated with that axis' motor has a non-zero integration term, then it is very likely that the integrator has built up a substantial integral term. Enabling the motor's amplifier when this has happened could cause the motor to jump with enormous force. Use mpiFilterIntegratorReset to reset the integrator before enabling the motor's amplifier to prevent this kind of jump.

Another condition that can cause the motor to jump upon enabling its amplifier is that the command position of the axis is not equal to the actual position of the axis. To prevent this situation, one should use mpiAxisActualPositionGet and mpiAxisCommandPositionSet. Please refer to this functions for a more in depth discussion.


mpiFilterMemory

Declaration
long mpiFilterMemory(MPIFilter  filter,
                     void       **memory)
Required Header stdmpi.h
Description

FilterMemory writes an address, which is used to access a Filter’s (filter) memory to the contents of memory. This address, or an address calculated from it, can be passed as the src parameter to MPIFilterMemoryGet(...) and as the dst parameter to MPIFilterMemorySet(...).

Return Values
MPIMessageOK if FilterMemory successfully writes the Filter’s memory address to the contents of memory
See Also | mpiFilterMemoryGet | mpiFilterMemorySet


mpiFilterMemoryGet

Declaration
long mpiFilterMemoryGet(MPIFilter filter,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description FilterMemoryGet copies count bytes of a Filter’s (filter) memory (starting at address src) and writes them into application memory (starting at address dst).
Return Values
MPIMessageOK if FilterMemoryGet successfully copies data from Filter memory to application memory
See Also | mpiFilterMemorySet | mpiFilterMemory


mpiFilterMemorySet

Declaration
long mpiFilterMemorySet(MPIFilter filter,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description FilterMemorySet copies count bytes of application memory (starting at address src) and writes them into a Filter’s (filter) memory (starting at address dst).
Return Values
MPIMessageOK if FilterMemoryGet successfully copies data from application memory to Filter memory
See Also | mpiFilterMemoryGet | mpiFilterMemory


mpiFilterMotorMapGet

Declaration
long mpiFilterMotorMapGet(MPIFilter    filter,
                          MPIObjectMap *map)
Required Header stdmpi.h
Description FilterMotorMapGet gets the object map of the Motors associated with the Filter (filter), and writes it into the structure pointed to by map.
Return Values
MPIMessageOK if FilterMotorMapGet successfully writes the object map of the Motors to the structure
See Also | mpiFilterMotorMapSet


mpiFilterMotorMapSet

Declaration
long mpiFilterMotorMapSet(MPIFilter    filter,
                          MPIObjectMap map)
Required Header stdmpi.h
Description FilterMotorMapSet sets the Motors associated with the Filter (filter) using data from the object map specified by map.
Return Values
MPIMessageOK if FilterMotorMapGet successfully sets the Motors using data from the object map
See Also | mpiFilterMotorMapGet


mpiFilterNumber

Declaration
long mpiFilterNumber(MPIFilter  filter,
                     long       *number)
Required Header stdmpi.h
Description For a motion controller that filter is associated with, FilterNumber writes the index of filter to the contents of number.
Return Values
MPIMessageOK if FilterNumber successfully writes the index of a Filter to the contents of number
See Also


mpiFilterStatus

Declaration
long mpiFilterStatus(MPIFilter  filter,
                     MPIStatus  *status,
                     void       *external)
Required Header stdmpi.h
Description

FilterStatus writes a Filter’s (filter) status into the structure pointed to by status, and also into the implementation-specific structure pointed to by external (if external is not NULL).

The Filter’s status information in external is in addition to the Filter’s status information in status, i.e, the status configuration information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIFilterStatus{} or is NULL.
Return Values
MPIMessageOK if FilterStatus successfully writes the status of a Filter to the structure(s)
See Also


mpiFilterValidate

Declaration
long mpiFilterValidate(MPIFilter filter)
Required Header stdmpi.h
Description

FilterValidate validates the Filter object and its handle (filter).
Return Values
MPIMessageOK if Filter is a handle to a valid object.
See Also | mpiFilterCreate | mpiFilterDelete


Flash Objects

Introduction

A Flash object manages nonvolatile flash memory on the XMP motion controller. Because all of flash memory must be written as one contiguous piece (which takes a lot of time), and a host-resident flash memory cache is used to provide faster writing performance, and to also reduce the number of write cycles performed.

After your application creates a Flash object (using meiFlashCreate(...)), the Flash object then creates a host-resident flash memory cache, initializing it using a copy of actual flash memory [by calling meiFlashMemoryToFile(fileName=Null)]. Using the data structures defined in xmp.h and pointers to those structures (returned by the mpiControlMemory(...) method), your application can then use the meiFlashData[Get/Set](...) methods to access this memory cache. Note that the meiFlashDataSet(...) method updates the flash cache, and doesn’t update the actual flash memory. To write the flash memory cache to actual flash memory, your application must call meiFlashMemoryFromFile(fileName=Null).

Use the FlashDataGet/Set(...) methods to move data between your application and the flash cache. Use the FlashMemoryTo/FromFile(...) methods to move data between the flash cache (or file) and the actual flash memory. Typically, your application would:

  1. Create a Flash object [using meiFlashCreate(...)].
  2. Pass the MEIFlash handle to the FlashConfig[Get/Set](...) methods of the objects to be configured (which in turn call the meiFlashData[Get/Set](...) methods).
  3. Write the flash cache to actual flash memory [using meiFlashMemoryFromFile(...)].
  4. Delete the Flash object.
Methods
Create, Delete, Validate Methods
 | meiFlashCreate | Create Flash object
 | meiFlashDelete | Delete Flash object
 | meiFlashValidate | Validate Flash object

Configuration and Information Methods
 | meiFlashConfigGet | Copy flash config from cache to application memory
 | meiFlashConfigSet | Copy flash config from application memory to cache
 | meiFlashDataGet | Get count bytes of flash data memory and write them in application memory
 | meiFlashDataSet | Set count bytes of flash data memory using application memory

Memory Methods
 | meiFlashMemoryErase | Erase actual flash memory on XMP
 | meiFlashMemoryFromFile | Write actual flash memory using cache or file
 | meiFlashMemoryFromFileType | Write actual flash memory using the binary image contained in filename
 | meiFlashMemoryGet | Copy count bytes of flash memory to application memory
 | meiFlashMemoryModified | Determine if flash cache has been modified
 | meiFlashMemorySet | Copy count bytes of application memory to flash memory
 | meiFlashMemoryToFile | Save actual flash memory to cache or to file
 | meiFlashMemoryVerify | Compare actual flash memory to cache or to file

Relational Methods
 | meiFlashControl | Return handle of Control that is associated with Flash
Data Types
MEIFlashFiles
MEIFlashMessage


MEIFlashFiles

MEIFlashFiles

typedef struct MEIFlashFiles {
    char binFile[MEIFlashFileMaxChars];
    char FPGAFile[MEIXmpFlashMaxFPGAFiles][MEIFlashFileMaxChars];
} MEIFlashFiles;
Description

FlashFiles is a configuration structure that specifies what files should be copied to the flash memory of the controller.

binFile | A string buffer that holds the filename of the .bin file to be flashed.
FPGAFile | An array of string buffers that holds the filenames of the FPGA files to be flashed.

See Also | MEIFlash


MEIFlashMessage

MEIFlashMessage

typedef enum {

    MEIFlashMessageFLASH_INVALID,
    MEIFlashMessageFLASH_READ_ERROR,
    MEIFlashMessageFLASH_WRITE_ERROR,
    MEIFlashMessagePATH,
} MEIFlashMessage;
Description

FlashMessage lists the error messages returned by the MEIFlash module.

MEIFlashMessageFLASH_INVALID | The flash object passed to meiFlash…() methods was invalid.
MEIFlashMessageFLASH_READ_ERROR | The flash object could not successfully read data.
MEIFlashMessageFLASH_WRITE_ERROR | The flash object could not successfully write data.
MEIFlashMessagePATH | The flash file path is too long.

See Also | MEIFlash


meiFlashConfigGet

Declaration
long meiFlashConfigGet(MEIFlash       flash,
                       MEIFlashConfig *config)
Required Header stdmei.h
Description

FlashConfigGet gets the flash configuration and writes it into the structure pointed to by config. The flash configuration includes data about the actual flash memory device (its type and size).

Return Values
MPIMessageOK if FlashConfigGet successfully gets the flash configuration and writes it into the structure
See Also | meiFlashConfigSet


meiFlashConfigSet

Declaration
long meiFlashConfigSet(MEIFlash       flash,
                       MEIFlashConfig *config)
Required Header stdmei.h
Description

FlashConfigSet sets (reads) the control configuration from the structure pointed to by config.

Return Values
MPIMessageOK if FlashConfigSet successfully reads the control configuration from the structure
See Also | meiFlashConfigGet


meiFlashControl

Declaration
const MPIControl meiFlashControl(MEIFlash flash)
Required Header stdmei.h
Description

FlashControl returns a handle to the motion controller (Control object) that a Flash object (flash) is associated with.

Return Values
handle | to a Control object that a Flash object is associated with
MPIHandleVOID | if the Flash object is invalid
See Also


meiFlashCreate

Declaration
const MEIFlash meiFlashCreate(MPIControl control)
Required Header stdmpi.h
Description

FlashCreate creates a Flash object and a host-resident copy of flash memory on motion controller control (called the flash cache). FlashCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Flash object
MPIHandleVOID | if the object could not be created

See Also | meiFlashDelete | meiFlashValidate


meiFlashDelete

Declaration
long meiFlashDelete(MEIFlash flash)
Required Header stdmei.h
Description

FlashDelete deletes a Flash object and invalidates its handle (flash). FlashDelete is the equivalent of a C++ destructor.

Return Values
MPIMessageOK if FlashDelete successfully deletes a Flash object and invalidates its handle
See Also | meiFlashCreate | meiFlashValidate


meiFlashDataGet

Declaration
long meiFlashDataGet(MEIFlash flash,
                     void     *dst,
                     void     *src,
                     long     count)
Required Header stdmei.h
Description

FlashDataGet gets count bytes of flash data memory starting at address src and puts (writes) them in application memory starting at address dst. The src pointer must point into the MEIXmpData{...} structure defined in xmp.h and be based on the firmware address (MEIXmpData *) returned by mpiControlMemory(...).

Your application cannot access Flash memory directly; instead your application will access the host-resident flash memory cache maintained by flash.

meiFlashDataGet(...) reads from the flash cache and is called only by applications and utilities, while meiFlashMemoryGet(...) is a low-level method that reads directly from actual flash memory and is called primarily by other flash methods.

Return Values
MPIMessageOK if FlashDataGet successfully gets count bytes of flash data memory writes them to application memory
See Also | mpiControlMemory | meiFlashMemoryGet | meiFlashDataSet


meiFlashDataSet

Declaration
long meiFlashDataSet(MEIFlash flash,
                     void     *dst,
                     void     *src,
                     long     count)
Required Header stdmei.h
Description

FlashDataSet sets (writes) count bytes of flash data memory (starting at address dst) using application memory (starting at address src). The dst pointer must point into the MEIXmpData{...} structure defined in xmp.h and be based on the firmware address (MEIXmpData *) returned by mpiControlMemory(...).

Your application cannot access Flash memory directly; instead your application will access the host-resident flash memory cache maintained by flash.

mpiControlMemory(...) returns an external pointer that points to the MEIXmpBufferData{...} structure. You cannot use this external pointer with the FlashDataSet method to access flash data memory.

Return Values
MPIMessageOK if FlashDataSet successfully writes to the flash cache
See Also | mpiControlMemory | meiFlashDataGet


meiFlashMemoryErase

Declaration
long meiFlashMemoryErase(MEIFlash flash,
                         long     erase,
                         long     verify)
Required Header stdmei.h
Description

FlashMemoryErase erases actual flash memory, and also verifies that actual flash memory is erased.

flash | a handle to a Flash object
erase | a value, either zero or non-zero
verify | a value, either zero or non-zero
Return Values
MPIMessageOK if FlashMemoryErase successfully erases the flash memory.
See Also | meiFlashCreate


meiFlashMemoryFromFile

Declaration
long meiFlashMemoryFromFile(MEIFlash      flash,
                            MEIFlashFiles *filesIn,                             MEIFlashFiles *filesOut)
Required Header stdmei.h
Description

FlashMemoryFromFile writes actual flash memory using the binary image contained in fileName, or using the flash memory cache.

Also, calling the meiFlashMemoryFromFile(...) method resets the flash cache modified indication to FALSE.
Return Values
MPIMessageOK if FlashMemoryFromFile successfully writes to actual flash memory using the file or using flash cache
See Also | meiFlashMemoryFromFileType


meiFlashMemoryFromFileType

Declaration
long meiFlashMemoryFromFileType(MEIFlash         flash,
                                const char       *fileName,
                                MEIFlashFileType fileType)
Required Header stdmei.h
Description

FlashMemoryFromFileType writes actual flash memory using the binary image contained in fileName, or using the flash memory cache.

flash | a handle to a Flash object
*filename | a string
fileType | an enumeration corresponding to the flash file types
Return Values
MPIMessageOK if FlashMemoryFromFileType successfully copies the data from the file to the flash.
See Also | meiFlashCreate | meiFlashMemoryFromFile


meiFlashMemoryGet

Declaration
long meiFlashMemoryGet(MEIFlash flash,
                       void     *dst,
                       void     *src,
                       long     count)
Required Header stdmei.h
Description

FlashMemoryGet copies count bytes of actual flash memory (flash, starting at address src) to application memory (starting at address dst).

You should calculate the src pointer by considering flash memory as a stream of bytes, because FlashMemoryGet will adjust the pointer for the actual type of flash memory.

meiFlashMemoryGet(...) is a low-level method that reads directly from actual flash memory and is called primarily by other flash methods, while meiFlashDataGet(...) reads from the flash cache and is called only by applications and utilities.

XMP Only

flash memory is of type unsigned long *.

Return Values
MPIMessageOK if FlashMemoryGet successfully copies flash memory to application memory
See Also | meiFlashMemorySet


meiFlashMemoryModified

Declaration
long meiFlashMemoryModified(MEIFlash flash,
                            long     *modified)
Required Header stdmei.h
Description

FlashMemoryModified determines if the flash memory cache has been modified. Note that unless meiFlashDataSet(...) has been called previously, the meiFlashMemoryModified(...) method will always return False, regardless of whether the cache has been modified or not modified.

If the "flash cache" | Then
has been modified | FlashMemoryModified writes True to the location pointed to by modified
has not been modified | FlashMemoryModified writes False to the location pointed to by modified
Return Values
MPIMessageOK if FlashMemoryModified successfully determines if the flash cache has been modified
See Also | meiFlashDataSet


meiFlashMemorySet

Declaration
long meiFlashMemorySet(MEIFlash flash,
                       void     *dst,
                       void     *src,
                       long     count)
Required Header stdmei.h
Description

FlashMemorySet copies application memory (starting at address src) to count bytes of flash memory (flash, starting at address dst).

You should calculate the dst pointer by considering flash memory as a stream of bytes, because FlashMemoryGet will adjust the pointer for the actual type of flash memory.
XMP Only

flash memory is of type unsigned long *.
Return Values
MPIMessageOK if FlashMemorySet successfully copies application memory to flash memory
See Also | meiFlashMemoryGet


meiFlashMemoryToFile

Declaration
long meiFlashMemoryToFile(MEIFlash          flash,
                          const char        *fileName,
                          MEIFlashFileType  fileType)
Required Header stdmei.h
Description

FlashMemoryToFile saves actual flash memory to a binary image contained in fileName, or to the flash memory cache.

Return Values
MPIMessageOK if FlashMemoryToFile successfully saves actual flash memory to file or to cache
See Also


meiFlashMemoryVerify

Declaration
long meiFlashMemoryVerify(MEIFlash    flash,
                          const char  *fileName)
Required Header stdmei.h
Description

FlashMemoryVerify compares actual flash memory to the binary image contained in fileName, or to the flash memory cache (if fileName is Null). Every word of flash memory (including code and data) is compared with the firmware bin file (or cache if the fileName is Null). The firmware version number is contained in flash data memory, so even if the only difference is the firmware version number, flash verification will fail. Flash verification will fail if any word is different.

Return Values
MPIMessageOK | if actual flash memory is identical to the binary image in fileName or in cache
MPIMessageNo_Memory | if memory allocation error occurred
MPIMessageFILE_OPEN_ERROR | if the file (fileName) was not found
MPIMessageFILE_READ_ERROR | if an error occurred while reading the file (fileName)
MPIMessageFILE_CLOSE_ERROR | if an error occurred whileclosing the file (fileName)
MPIFlashMessageFLASH_READ_ERROR | if differences were detected during flash validation
See Also


meiFlashValidate

Declaration
long meiFlashValidate(MEIFlash flash)
Required Header stdmei.h
Description

FlashValidate validates the Flash object and its handle (flash).

Return Values
MPIMessageOK if Flash is a handle to a valid object.
See Also | meiFlashCreate | meiFlashDelete


Global Objects

Introduction

Data types that are used by more than one module are defined in the mpidef.h header file.The definitions listed in this section are available to all modules, and are defined in mpidef.h.

The object.h header file contains the data type definition for a generic object handle (MPIHandle) and an invalid object handle (MPIHandleVOID). The object.h header file also contains declarations of generic mpiObject functions, the definitions for which are in the object.c source file. These functions take a generic object handle (of type MPIHandle) as their first argument. Any MPI object handle may be treated as an MPIHandle and passed as the first argument to these functions.
Data Types
MPIAction
MPIIoSource
MPIIoType
MPIIoTrigger
MPIModuleId / MEIModuleId
MPIState
MPIStatus
MPIStatusFlag
MPIStatusMask
MPITrajectory
MPIWait
Macros
 | mpiStatusMaskBIT


MPIAction

MPIAction

typedef enum {
    MPIActionINVALID,

    MPIActionNONE,
    MPIActionSTOP,
    MPIActionE_STOP,
    MPIActionE_STOP_ABORT,
    MPIActionABORT,

    MPIActionDONE,
    MPIActionSTART,
    MPIActionRESUME,
    MPIActionRESET,
} MPIAction;

Description
 | MPIActionNONE | Performs no action. Use with MPIMotorEventConfig to prevent a motor event from performing an action.
 | MPIActionSTOP | Makes a motion supervisor perform a stop. This action can be commanded with mpiMotionAction(…) or by a motor event on the controller. Please see MPIMotionDecelTime for more information about stop actions.
 | MPIActionE_STOP | Makes a motion supervisor perform an e-stop. This action can be commanded with mpiMotionAction(…) or by a motor event on the controller. Please see MPIMotionDecelTime for more information about e-stop actions.
 | MPIActionE_STOP_ABORT | Makes a motion supervisor perform an e-stop and then an abort. This action can be commanded with mpiMotionAction(…) or by a motor event on the controller. Please see MPIMotionDecelTime for more information about e-stop actions.
 | MPIActionABORT | Makes a motion supervisor perform an abort. This action can be commanded with mpiMotionAction(…) or by a motor event on the controller.
 | MPIActionDONE | is currently not supported and is reserved for future use.
 | MPIActionSTART | Intended to force a motion supervisor to start when it is waiting for some event (a delay or hold) before starting. This action is currently not supported.
 | MPIActionRESUME | Makes a motion supervisor to resume motion after a stop action has occurred. A motion supervisor can only resume a motion after a stop event, not an e-stop event. This action can be commanded with mpiMotionAction(…).
 | MPIActionRESET | Makes a motion supervisor return to an idle state after an error has occurred or after a stop, e-stop, abort, or e-stop/abort action has occurred. While abort actions and certain errors cause all associated motors to turn off their amp-enable lines, this action does not change the state of any amp-enable lines. One will have to call the method mpiMotorAmpEnableSet(…) to re-enable the amplifiers. This action can be commanded with mpiMotionAction(…).
Remarks
MPIAction enumerations are used to perform some sort of action on an MPI object. Currently, only MPIMotion and MPIMotor use the MPIAction enumerations. One can command an MPIMotion object to perform some action with the mpiMotionAction(…) method, while one can get and set the types of actions that will be performed when certain motor events occur with the MPIMotorEventConfig structure with the mpiMotorEventConfigGet(…) and mpiMotorEventConfigSet(…) methods.

An MPIAction can be generated from the host or the firmware. Below is a table where MPIActions originate (start):

MPIAction | Originating from Host | Originating from XMP Firmware
Start Resume Reset Stop | mpiMotionAction(…) (currently unsupported) mpiMotionAction(…) mpiMotionAction(…) mpiMotionAction(…) | NEVER NEVER NEVER Event
E_Stop ABORT | mpiMotionAction(…) mpiMotionAction(…) | Event Event
DONE | NEVER | NEVER

See Also | mpiMotionAction | MPIMotionDecelTime | MPIMotorEventConfig mpiMotorEventConfigGet | mpiMotorEventConfigSet | MPIEvent


MPIIoSource

MPIIoSource

typedef union {
    MPIHandle	motor;	/* MOTOR */
    long	index;	/* USER */
} MPIIoSource;

Description
 | motor | Handle to a motor object that is the source for the IO.
 | index | Value of the index for a user input. User IO's are no longer supported by the xmp (user IO's are handled through the motor object).
See Also


MPIIoTrigger

MPIIoTrigger

typedef struct MPIIoTrigger {
    MPIIoType        type;
    MPIIoSource      source;
    unsigned long    mask;
    unsigned long    pattern;
} MPIIoTrigger;

Description
 | type | see MPIIoType.
 | source | see MPIIoSource.
 | mask | Value that specifies the mask to be applied to the IO.
 | pattern | Value that specifies the pattern to be compared to the masked IO.
See Also


MPIIoType

MPIIoType

typedef enum {
    MPIIoTypeINVALID,

    MPIIoTypeMOTOR,
    MPIIoTypeUSER,

} MPIIoType;

Description
 | MPIIoTypeMotor | Value specifies the IO type as motor (the IO source is a motor object).
 | MPIIoTypeUSER | Value specifies the IO type as user (User IO types are currently not supported. User IO is available through the motor objects).
See Also


MPIModuleId and MEIModuleId

MPIModuleId / MEIModuleId

MPIModuleId

typedef enum {
    MPIModuleIdINVALID,

    MPIModuleIdMESSAGE,
    MPIModuleIdADC,
    MPIModuleIdAXIS,
    MPIModuleIdCAPTURE,
    MPIModuleIdCOMMAND,
    MPIModuleIdCOMPARE,
    MPIModuleIdCONTROL,

    MPIModuleIdEVENT,
    MPIModuleIdEVENTMGR,
    MPIModuleIdFILTER,
    MPIModuleIdIDN,
    MPIModuleIdIDNLIST,
    MPIModuleIdMOTION,
    MPIModuleIdMOTOR,
    MPIModuleIdNODE,
    MPIModuleIdNOTIFY,
    MPIModuleIdPATH,
    MPIModuleIdRECORDER,
    MPIModuleIdSEQUENCE,
    MPIModuleIdSERCOS,
    MPIModuleIdSYNQNET,  /* This is a duplicate of MEIModuleIdSYNQNET
                         only for use in calling functions in xmp.c */
    MPIModuleIdBLOCK,    /* This is a duplicate of MEIModuleIdBLOCK only
                         for use in calling functions in xmp.c */

    MPIModuleIdEXTERNAL,

    MPIModuleIdMAX = 0xFF
} MPIModuleId;
Description

ModuleId is used to identify what module a particular MPIHandle belongs to. If the handle is an external memory pointer instead of an MPI object handle, MPIModuleIdEXTERNAL will be returned by MPI methods.

MEIModuleId

typedef enum {
    MEIModuleIdPLATFORM = MPIModuleIdEXTERNAL,

    MEIModuleIdCAN,

    MEIModuleIdCLIENT,
    MEIModuleIdELEMENT,
    MEIModuleIdFLASH,
    MEIModuleIdLIST,
    MEIModuleIdMAP,
    MEIModuleIdPACKET,
    MEIModuleIdSERVER,
    MEIModuleIdSYNQNET,
    MEIModuleIdBLOCK,
    MEIModuleIdSNDRIVE,

}MEIModuleId;
Description

ModuleId is used to identify what module a particular MPIHandle belongs to. If the handle is an external memory pointer instead of an MPI object handle, MPIModuleIdEXTERNAL will be returned by MPI methods.

See Also | mpiObjectModuleId | mpiObjectValidate


MPIState

MPIState

typedef enum {
    MPIStateINVALID,

    MPIStateINIT,
    MPIStateIDLE,
    MPIStateMOVING,
    MPIStateSTOPPING,
    MPIStateSTOPPING_ERROR,
    MPIStateERROR,
} MPIState;
Description

State enumerations define basic states the motion is in. MPIState resides in the MPIStatus structure. Currently MPIState is only used with motion module.

MPIStateINIT | The of the motion is performing an initialization.
MPIStateIDLE | The state of motion is idle and waiting to resume motion.
MPIStateMOVING | The state of the motion is moving.
MPIStateSTOPPING | The state of the motion is stopping. This occurs from a Stop event, but not an E_Stop, E_Stop Abort, or Abort events.
MPIStateSTOPPING_ERROR | The state of the motion is performing an emergency stop and/or abort on all axes.
MPIStateERROR | The state of the motion is in error. The error state is generated from an E_Stop or Abort event.

See Also | MPIStatus


MPIStatus

MPIStatus

typedef struct MPIStatus {
    MPIState        state;
    MPIAction       action;
    MPIEventMask    eventMask;

    long    settled;
    long    atTarget;

    MPIStatusMask    statusMask;
} MPIStatus;

Description
 | state | Value that indicates the state of an xmp controller's motion supervisor.
 | action | Value that indicates the action to perform for a motion supervisor.
 | eventMask | Array that defines the event mask bits. The array is defined as typedef MPIEventMaskELEMENT_TYPE MPIEventMask[MPIEventMaskELEMENTS].
 | settled | Value that indicates if an axis associated with a motion supervisor has settled (is in fine position).
 | atTarget | Value that indicates if an axis associated with a motion supervisor has completed its command trajectory (i.e. the command position has reached the targeted end point of the move).

See Also | Note on status information if using a SERCOS controller. MPIState | MPIStatusFlag | MPIStatusMask


MPIStatusFlag

MPIStatusFlag

typedef enum {
    MPIStatusFlagINVALID,

    MPIStatusFlagCOMM_ERROR,

} MPIStatusFlag;
Description
See Also | Special Note on status information when using a SERCOS controller.


MPIStatusMask

MPIStatusMask

typedef enum {
    MPIStatusMaskNONE	= 0x0,

    MPIStatusMaskCOMM_ERROR	= mpiStatusMaskBIT(MPIStatusFlagCOMM_ERROR),
                     /* 0x00000001 */

    MPIStatusMaskMOTOR	= MPIStatusMaskCOMM_ERROR,
                      /* 0x00000001 */

    MPIStatusMaskALL	= mpiStatusMaskBIT(MPIStatusFlagLAST) - 1
                      /* 0x00000001 */
} MPIStatusMask;

Description
 | MPIStatusMaskCOMM_ERROR | Value for the status mask that indicates a commutation error has occurred.
 | MPIStatusMaskMOTOR | Value specifies the motor's status mask.
 | MPIStatusMaskALL | Value specifies the status mask that encompasses all the possible status flags.

See Also | Note on status information if using a SERCOS controller. MPIStatus | MPIStatusFlag


MPITrajectory

MPITrajectory

typedef struct MPITrajectory {
    double    velocity;
    double    acceleration;
    double    deceleration;
    double    jerkPercent;
    double    accelerationJerk;
    double    decelerationJerk;
} MPITrajectory;
Description

The Trajectory structure is within the MPIMotionVelocity structure which in turn is within the MPIMotionParams structure. The data contained in MPITrajectory are the parameters used in certain motion profiles.

See Also | MPIMotionParams | MPIMotionSCurve | MPIMotionTrapezoidal | MPIMotionType MPIMotionVelocity | mpiMotionTrajectory


MPIWait

MPIWait

typedef enum {
    MPIWaitFOREVER = -1,
    MPIWaitPOLL = 0,
    MPIWaitMSEC
} MPIWait;
Description

Wait enumerations define basic wait times for certain MPI methods.

MPIWaitFOREVER | Makes MPI methods wait forever for an event to occur before returning.
MPIWaitPOLL | Makes MPI methods see if a certain event has occurred. If an event has not occurred, then the MPI method will generally return immediately returning the value MPIMessageTIMEOUT.
MPIWaitMSEC | Defines a period of one millisecond. If used alone, this will make MPI methods wait for one millisecond for an event occurs before returning. One can pass an an agument a multiple of MPIWaitMSEC to make MPI methods wait longer periods of time. For example, the following statement will make mpiPlatformKey wait 5 milliseconds for a user keystroke: mpiPlatformKey( 5 * MPIWaitMSEC ); If an event does not occur within the specified time, MPI methods will generally return the value MPIMessageTIMEOUT.

WARNING
 | The MPI depends on the ability of the operating system it is running on to be able to activate threads or put threads to sleep for a specified period of time in order for these times to be accurate. Microsoft Windows platforms are not real-time operating systems and are known to be unable to activate threads any quicker than 10 milliseconds. If you encounter a timing problem, it is likely an operating system timing issue.

See Also | mpiControlInterruptWait | mpiNotifyEventWait | mpiObjectTimeoutGet mpiObjectTimeoutSet | meiPlatformKey


mpiStatusMaskBIT

Declaration
#define	  mpiStatusMaskBIT(flag)	(0x1 << (flag))
Required Header stdmpi.h
Description

StatusMaskBIT converts the status flag into the status mask.

See Also | MPIStatusFlag | MPIStatusMask


Idn Objects

Introduction |
 | An Idn object represents an individual SERCOS IDN. An Idn object is a container for data that is sent to and received from a Node. Methods are provided to get and set the data associated with an Idn object, but these methods do not actually transmit an Idn object to or from a Node.
Methods
Create, Delete, Validate Methods
 | mpiIdnCreate | Create Idn object
 | mpiIdnDelete | Delete Idn object
 | mpiIdnValidate | Validate Idn object

Configuration and Information Methods
 | mpiIdnCopy | Copy all element fields of one IDN object to another.
 | mpiIdnFieldGet | Get the value of an IDN (or all fields) from the drive.
 | mpiIdnFieldSet | Set the value of an IDN field. The inverse of mpiIdnFieldGet.
 | mpiIdnNumberName | Fill the buffer with the text form of the IDN number.
 | mpiIdnNumberText | Get the ASCII representation of an Idn objects IDNumber (S-X-XXXX or P-X-XXXX)
Data Types
MPIIdnData
MPIIdnDataType
MPIIdnElement
MPIIdnField
MPIIdnMessage
MPIIdnNumber
MPIIdnProcedure
MPIIdnValue
MPIIdnVarLength
Macros
mpiIdnDataGET | Get data type (Element 3) and operation data (Element 7)
mpiIdnDataSET |
mpiIdnElementGET |
mpiIdnFieldATTR |
mpiIdnFieldAttrDATA_TYPE |
mpiIdnFieldAttrGET |
mpiIdnFieldAttrMASK |
mpiIdnFieldAttrSET |
mpiIdnFieldAttrSHIFT |
mpiIdnNUMBER |
mpiIdnNumberDATA_BLOCK |
mpiIdnNumberGET |
mpiIdnNumberPARAMETER_SET |
mpiIdnNumberPRODUCT |
mpiIdnNumberSET |
mpiIdnNumberSTANDARD |
mpiIdnNumberTYPE |
Constants
MPIIdnDATA_SIZE_MAX
MPIIdnNAME_SIZE_MAX
MPIIdnNUMBER_SIZE_MAX
MPIIdnUNIT_SIZE_MAX


MPIIdnData

MPIIdnData

typedef union {
    unsigned long	binary;
    MPIIdnNumber	idn;
    MPIIdnProcedure	procedure;
    char		*text;
    MPIIdnValue		value;
    MPIIdnVarLength	varLength;
} MPIIdnData;

Description
 | binary | 0 or 1
 | idn | an IDN number
 | procedure | procedure IDN's data is a word that is a bit mask.
 | *text | a char pointer that points to a text string.
 | value | a long or unsigned long.
 | valLength | IDN data whose length is not defined, and it's data can be of any number of types.

See Also | MPIIdnDATA_SIZE_MAX | MPIIdnDataType


MPIIdnDATA_SIZE_MAX

MPIIdnDATA_SIZE_MAX

#define	  MPIIdnDATA_SIZE_MAX	(65532)

Description
 | IdnDATA_SIZE_MAX defines the maximum data size an Idn object supports.

See Also | mpiIdnDataGET | MPIIdnData


MPIIdnDataType

MPIIdnDataType

typedef enum {
    MPIIdnDataTypeINVALID,
    /*
     * These data types correspond to the
     * SERCOS attribute TYPE field.
     * They should not be changed,
     * though new types may be appended
     */

    MPIIdnDataTypeBINARY,	/* 0x0 */
    MPIIdnDataTypeUNSIGNED,	/* 0x1 */
    MPIIdnDataTypeLONG,		/* 0x2 */
    MPIIdnDataTypeUNSIGNED_HEX,	/* 0x4 */
    MPIIdnDataTypeTEXT,		/* 0x5 */
    MPIIdnDataTypeIDN,		/* 0x6 */

} MPIIdnDataType;

Description
 | IdnDataType corresponds to the SERCOS attribute TYPE field. It specifies the type of data that the IDN contains.

See Also | MPIIdnDATA_SIZE_MAX | MPIIdnData


MPIIdnElement

MPIIdnElement

typedef struct MPIIdnElement {
    MPIIdnNumber	number;		/* 0	MPIIdnFieldNUMBER	*/
    const char		*name;		/* 1	MPIIdnFieldNAME		*/
    unsigned long	attributes;	/* 2	MPIIdnFieldATTRIBUTES	*/
    const char		*unit;		/* 3	MPIIdnFieldUNIT		*/
    MPIIdnValue		minimum;	/* 4	MPIIdnFieldMINIMUM	*/
    MPIIdnValue		maximum;	/* 5	MPIIdnFieldMAXIMUM	*/
    MPIIdnData		data;		/* 6	MPIIdnFieldDATA		*/
} MPIIdnElement;

Description
 | number | The IDN number field.
 | *name | A pointer to the IDN name field.
 | attributes | The IDN attributes field.
 | *unit | A pointer to the IDN unit field.
 | minimum | The IDN minimum field which is the smallest value the IDN data can be (not valid with certain data types).
 | maximum | The IDN maximum field which is the largest value the IDN data can be (not valid with certain data types).
 | data | The IDN data.

See Also | mpiIdnElementGET


MPIIdnField

MPIIdnField

typedef enum {
    MPIIdnFieldINVALID,

    MPIIdnFieldNUMBER,
    MPIIdnFieldNAME,
    MPIIdnFieldATTRIBUTES,
    MPIIdnFieldUNIT,
    MPIIdnFieldMINIMUM,
    MPIIdnFieldMAXIMUM,
    MPIIdnFieldDATA,

    MPIIdnFieldALL,
} MPIIdnField;
Description

The IdnField enumeration is a list of all the different fields that comprises an IDN.

See Also | mpiIdnFieldGet | mpiIdnFieldSet


MPIIdnMessage

MPIIdnMessage

typedef enum {

    MPIIdnMessageIDN_INVALID,
    MPIIdnMessageATTRIBUTES_INVALID,
} MPIIdnMessage;
Description

The IdnMessage is an enumeration that contains possible return values for IDN method calls.
See Also


MPIIdnNAME_SIZE_MAX

MPIIdnNAME_SIZE_MAX

#define	MPIIdnNAME_SIZE_MAX	(60)
Description

IdnNAME_SIZE_MAX defines the maximum number of characters that can be used to represent the name of an IDN.
See Also


MPIIdnNumber

MPIIdnNumber

typedef enum {
    MPIIdnNumberSTANDARD,
    MPIIdnNumberPRODUCT,

    MPIIdnNumberINVALID,

} MPIIdnNumber;

Description
 | IdnNumber is an IDN number, and also is used to specify whether the IDN is a standard or proprietary IDN.

See Also | MPIIdnNUMBER_SIZE_MAX


MPIIdnNUMBER_SIZE_MAX

MPIIdnNUMBER_SIZE_MAX

#define	MPIIdnNUMBER_SIZE_MAX	(8)

Description
 | IdnNUMBER_SIZE_MAX defines the maximum number of characters that can be used in an IDN number string.

See Also | MPIIdnNumber


MPIIdnProcedure

MPIIdnProcedure

typedef enum {
    MPIIdnProcedureSET,
    MPIIdnProcedureENABLED,

    MPIIdnProcedureCANCEL,
    MPIIdnProcedureEXECUTE,

    MPIIdnProcedureRUNNING,
    MPIIdnProcedureERROR,
    MPIIdnProcedureDATA_VALID,
} MPIIdnProcedure;

Description
 | The data portion of a Procedure IDN is a bit map that represents the state of the procedure, this enumeration is a bit mask and can be used to decipher the status of the procedure.
See Also


MPIIdnUNIT_SIZE_MAX

MPIIdnUNIT_SIZE_MAX

#define	 MPIIdnUNIT_SIZE_MAX	(12)

Description
 | IdnUNIT_SIZE_MAX defines the maximum number of characters that can be used to represent the units used by an IDN.
See Also


MPIIdnValue

MPIIdnValue

typedef union {
    long		l;
    unsigned long	u;
} MPIIdnValue;

Description
 | IdnValue represents either an unsigned long or long.
See Also


MEIIdnVarLength

MEIIdnVarLength

typedef struct MPIIdnVarLength{
    long		count;

    MPIIdnDataType	type;

    union {
        MPIIdnNumber	*idn;
        char		*text;
        MPIIdnValue	*value;
    } as;
} MPIIdnVarLength;

Description
 | count | The size of the data buffer pointed to by as.
 | type | The type of data in the buffer.
 | as | A union of different pointer types, where the data is located.
See Also


mpiIdnCopy

Declaration
long mpiIdnCopy(MPIIdn idn,
                MPIIdn dst)
Required Header stdmpi.h
Description

IdnCopy copies all element fields of one IDN object to another.

Return Values
MPIMessageOK if IdnCopy successfully copies all element fields to on IDN object to another
See Also


mpiIdnCreate

Declaration
const MPIIdn mpiIdnCreate(MPIIdnNumber number)
Required Header stdmpi.h
Description

IdnCreate creates an Idn object, where number argument is the initial SERCOS IDNumber to be assigned to this object.
IdnCreate is the equivalent of a C++ constructor.

Return Values
handle | to an Idn object
MPIHandleVOID | if the object could not be created

See Also | mpiIdnDelete | mpiIdnValidate


mpiIdnDelete

Declaration
long mpiIdnDelete(MPIIdn idn)
Required Header stdmpi.h
Description

IdnDelete deletes an Idn object and invalidates its handle (idn).
IdnDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if IdnDelete successfully deletes the Idn object and invalidates its handle
See Also | mpiIdnCreate | mpiIdnValidate


mpiIdnDataGET

Declaration

#define mpiIdnDataGET(idn,idnData) \
        mpiIdnFieldGet((idn), MPIIdnFieldDATA, (idnData))
Required Header stdmpi.h
Description

IdnDataGET reads the MPIIdnFieldDATA from the specified idn and writes it to the location pointed to by idnData.

See Also | mpiIdnDataSET


mpiIdnDataSET

Declaration

#define	mpiIdnDataSET(idn,idnData) \
    mpiIdnFieldSet((idn), MPIIdnFieldDATA, (idnData))
Required Header stdmpi.h
Description

IdnDataSET writes the MPIIdnFieldDATA to the specified idn, from the location pointed to by idnData.

See Also | mpiIdnDataGET


mpiIdnElementGET

Declaration

#define	mpiIdnElementGET(idn,idnElement) \
    mpiIdnFieldGet((idn), MPIIdnFieldALL, (idnElement))
Required Header stdmpi.h
Description

IdnElementGET reads the MPIIdnFieldALL from the specified idn and writes it to the location pointed to by idnElement.

See Also | MPIIdnElement


mpiIdnFieldATTR

Declaration

#define mpiIdnFieldATTR(mask,shift)
       (((mask) << 16) | (shift))
Required Header stdmpi.h
Description

IdnFieldATTR shifts the mask up by 16 bits and bitwise ORs in the shift value.

See Also | mpiIdnFieldAttrGET | mpiIdnFieldAttrSET


mpiIdnFieldAttrDATA_TYPE

Declaration

#define mpiIdnFieldAttrDATA_TYPE(attr)
       ((MPIIdnDataType)mpiIdnFieldAttrGET  MPIIdnField	AttrTYPE, (attr)))
Required Header stdmpi.h
Description

IdnFieldAttrDATA_TYPE reads the MPIIdnDataType from the specified attr.
See Also


mpiIdnFieldAttrGET

Declaration

#define mpiIdnFieldAttrGET(attr,word)
        (((word) >> iIdnFieldAttrSHIFT(attr)) &
        mpiIdnFieldAttrMASK(attr))
Required Header stdmpi.h
Description

IdnFieldAttrGET reads the value of the specified attr (MPIIdnFieldAttr) from the word.

See Also | mpiIdnFieldATTR


mpiIdnFieldAttrMASK

Declaration

#define     mpiIdnFieldAttrMASK(attr)
            ((( attr) >> 16) & 0xFFFF)
Required Header stdmpi.h
Description

IdnFieldAttrMASK masks the value of the specified attr (MPIIdnFieldAttr). Used internally by mpiIdnFieldAttrGET/SET(…).

See Also | mpiIdnFieldAttrGET | mpiIdnFieldAttrSET


mpiIdnFieldAttrSET

Declaration

#define mpiIdnFieldAttrSET(attr,bits)
        (((bits) & mpiIdnFieldAttrMASK(attr)) <<
        mpiIdnFieldAttrSHIFT(attr))
Required Header stdmpi.h
Description

IdnFieldAttrSET sets the value of the specified attr (MPIIdnFieldAttr) to bits.

See Also | mpiIdnFieldAttrGET | mpiIdnFieldATTR


mpiIdnFieldAttrSHIFT

Declaration

#define mpiIdnFieldAttrSHIFT(attr)
        ((attr) & 0xFFFF)
Required Header stdmpi.h
Description

IdnFieldAttrSHIFT shifts the value of the specified attr (MPIIdnFieldAttr). Used internally by mpiIdnFieldAttrGET/SET(…).

See Also | mpiIdnFieldAttrGET | mpiIdnFieldAttrSET


mpiIdnFieldGet

Declaration
long mpiIdnFieldGet(MPIIdn      idn,
                    MPIIdnField field,
                    void        *value)
Required Header stdmpi.h
Description

IdnFieldGet gets the value of an IDN (or all fields) from the drive. The pointer “value” must point to enough memory to hold the value of the requested field. See MPIIdnElement for the type of each field.
Return Values
MPIMessageOK if successful
See Also | MPIIdnElement | mpiIdnFieldSet | MPIIdnField


mpiIdnFieldSet

Declaration
long mpiIdnFieldSet(MPIIdn      idn,
                    MPIIdnField field,
                    void        *value)
Required Header stdmpi.h
Description

IdnFieldSet sets the value of an IDN field. The inverse of mpiIdnFieldGet.

Return Values
MPIMessageOK if successful
See Also | mpiIdnFieldGet | MPIIdnField


mpiIdnNUMBER

Declaration

#define	mpiIdnNUMBER(type,param,data) \
((((type) & 0x1) << 15) | (((param) & 0x7) << 12) | ((data) & 0xFFF))
Required Header stdmpi.h
Description

IdnNUMBER converts the idn type, param, and data into a number. Used internally by mpiIdnNumberPRODUCT/STANDARD(…).

See Also | mpiIdnNumberPRODUCT | mpiIdnNumberSTANDARD


mpiIdnNumberDATA_BLOCK

Declaration

#define     mpiIdnNumberDATA_BLOCK(number)
            ((number) & 0xFFF)
Required Header stdmpi.h
Description

IdnNumberDATA_BLOCK determines the idn data block from a SERCOS identification number.
See Also


mpiIdnNumberGET

Declaration

#define     mpiIdnNumberGET(idn,idnNumber) \
            mpiIdnFieldGet((idn), MPIIdnFieldNUMBER, (idnNumber))
Required Header stdmpi.h
Description

IdnNumberGET gets the SERCOS identification number from the idn and writes it into the location pointed to by idnNumber.

See Also | mpiIdnNumberSET


mpiIdnNumberName

Declaration
char * mpiIdnNumberName(MPIIdnNumber number,
                        char *buffer)
Required Header stdmpi.h
Description

Given a pointer to a char buffer of length MPIIdnNUMBER_SIZE_MAX + 1, IdnNumberName fills the buffer with the text form of the IDN number.
Return Values
MPIMessageOK if successful
See Also


mpiIdnNumberPARAMETER_SET

Declaration

#define    mpiIdnNumberPARAMETER_SET(number)
          (((number) >> 12) & 0x7)
Required Header stdmpi.h
Description

IdnNumberPARAMETER_SET determines the idn parameters from a SERCOS identification number.
See Also


mpiIdnNumberPRODUCT

Declaration

#define	 mpiIdnNumberPRODUCT(data)
    mpiIdnNUMBER(MPIIdnNumberPRODUCT, 0, (data))
Required Header stdmpi.h
Description

IdnNumberPRODUCT converts an idn from a product specific value to the SERCOS identification number format.
See Also


mpiIdnNumberSET

Declaration

#define     mpiIdnNumberSET(idn,idnNumber) \
            mpiIdnFieldSet((idn), MPIIdnFieldNUMBER, (idnNumber))
Required Header stdmpi.h
Description

IdnNumberSET sets the SERCOS identification number in the idn, to the value from idnNumber.

See Also | mpiIdnNumberGET


mpiIdnNumberSTANDARD

Declaration
#define	 mpiIdnNumberSTANDARD(data)
         mpiIdnNUMBER(MPIIdnNumberSTANDARD, 0, (data))
Required Header stdmpi.h
Description

IdnNumberSTANDARD converts an idn from a standard value to the SERCOS identification number format.
See Also


mpiIdnNumberText

Declaration
long mpiIdnNumberText(MPIIdn     idn,
                      const char **text)
Required Header stdmpi.h
Description

IdnNumberText sets “text” to point to the internal memory storing the text form of the IDN number.

Return Values
MPIMessageOK if successful
See Also


mpiIdnNumberTYPE

Declaration

#define mpiIdnNumberTYPE(number)
        (((number) >> 15) & 0x1)
Required Header stdmpi.h
Description

IdnNumberTYPE determines the idn type (STANDARD or PRODUCT) from a SERCOS identification number.

See Also | MPIIdnNumber


mpiIdnValidate

Declaration
long mpiIdnValidate(MPIIdn idn)
Required Header stdmpi.h
Description

IdnValidate validates the Idn object and its handle (idn).
Return Values
MPIMessageOK if Idn is a handle to a valid object.
See Also | mpiIdnCreate | mpiIdnDelete


IdnList Objects

Introduction |
 | An IdnList object manages a list of SERCOS Idn objects.
Methods
Create, Delete, Validate Methods
 | mpiIdnListCreate | Create IdnList object
 | mpiIdnListDelete | Delete IdnList object
 | mpiIdnListValidate | Validate IdnList object

Configuration and Information Methods
 | mpiIdnListCopy | Copy the contents of idnList to dst.
 | mpiIdnListIdnNumber | Read and write the identification numbers of an IdnList object.

Relational Methods
 | List Methods- for Idn Objects
 | mpiIdnListAppend | Append an Idn to an IdnList
 | mpiIdnListCount | Count the number of Idns in an IdnList
 | mpiIdnListFirst | Get handle to first Idn in an IdnList
 | mpiIdnListIdn | Return the position of the element on the list indicated by "index."
 | mpiIdnListIndex | Get index value to an Idn in an IdnList
 | mpiIdnListInsert | Insert an Idn into an IdnList
 | mpiIdnListLast | Get handle to last Idn in an IdnList
 | mpiIdnListGet | Get array of handles to Idns in an IdnList
 | mpiIdnListSet | Create a list (IdnList) containing idnCount Idn objects
 | mpiIdnListNext | Get handle to the Idn object just after a specified Idn object in an IdnList
 | mpiIdnListIdnNumberFind |
 | mpiIdnListPrevious | Get handle to the Idn object preceding a specified Idn object in an IdnList
 | mpiIdnListRemove | Remove an Idn object from an IdnList


mpiIdnListAppend

Declaration
long mpiIdnListAppend(MPIIdnList idnList,
                      MPIIdn     idn)
Required Header stdmpi.h
Description

IdnListAppend appends an Idn (idn) to an IdnList (idnList).

idnList | a handle to the IdnList object.
idn | a handle to an Idn object.

Return Values
MPIMessageOK | if IdnListAppend successfully appends the Idn to the IdnList
MPIMessageHANDLE_INVALID | Either idnList or idn is an invalid handle.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiIdnListCount

Declaration
long mpiIdnListCount(MPIIdnList idnList)
Required Header stdmpi.h
Description

IdnListCount returns the number of elements on the list.

idnList | a handle to the IdnList object.

Return Values
count | the number of elements in idnList
(-1) | if the idnList object is invalid
See Also


mpiIdnListCopy

Declaration
long mpiIdnListCopy(MPIIdnList idnList,
                    MPIIdnList dst)
Required Header stdmpi.h
Description

IdnListCopy copies the contents of idnList to dst.

Return Values
MPIMessageOK if IdnListCopy successful
See Also


mpiIdnListCreate

Declaration
const MPIIdnList mpiIdnListCreate(MPIIdn idn)
Required Header stdmpi.h
Description

IdnListCreate creates an IdnList object, where the idn argument specifies the initial element in the list of Idn objects. Note that idn may be MPIHandleVOID. IdnListCreate is the equivalent of a C++ constructor.

Return Values
handle | to an IdnList object
MPIHandleVOID | if the object could not be created

See Also | mpiIdnListDelete | mpiIdnListValidate


mpiIdnListDelete

Declaration
long mpiIdnListDelete(MPIIdnList idnList)
Required Header stdmpi.h
Description

IdnListDelete deletes an IdnList object and invalidates its handle (idnList). Note that deleting an IdnList object will also delete all of the Idn objects that it contains. IdnListDelete is the equivalent of a C++ destructor.

Return Values
MPIMessageOK if IdnListDelete successfully deletes the IdnList object and invalidates its handle
See Also | mpiIdnListCreate | mpiIdnListValidate


mpiIdnListFirst

Declaration
MPIIdn mpiIdnListFirst(MPIIdnList idnList)
Required Header stdmpi.h
Description

IdnListFirst return the first element in the list. This function can be used in conjuntion with mpiIdnListIdnNext() in order to iterate through the list.

idnList | a handle to the IdnList object.

Return Values
handle | to the first Idn object of an IdnList (idnList)
MPIHandleVOID | if idnList is invalid if idnList is empty
MPIMessageHANDLE_INVALID | idnList is an invalid handle.

See Also | mpiIdnListLast


mpiIdnListGet

Declaration
long mpiIdnListGet(MPIIdnList idnList,
                   long       *idnCount,
                   MPIIdn     *idnArray)
Required Header stdmpi.h
Description

IdnListGet gets an array (that contains the handles of the Idn objects held by idnList), and writes that array (of idnCount handles) to the location pointed to by idnArray, and also writes the number of Idn objects (held by idnList) to the location pointed to by idnCount.

Return Values
MPIMessageOK if IdnListGet successfully writes the array of Idn hanldes and the number of Idn objects to the idnArray and idnCount locations (respectively)
See Also


mpiIdnListIdn

Declaration
MPIIdn mpiIdnListIdn(MPIIdnList idnList,
                     long       index,)
Required Header stdmpi.h
Description

IdnListIdn returns the position of the element on the list indicated by "index."

idnList | a handle to the IdnList object.
index | a position in the list.

Return Values
MPIMessageARG_INVALID | if index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | if index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | if idnList is an invalid handle.
See Also


mpiIdnListIdnNumber

Declaration
long mpiIdnListIdnNumber(MPIIdnList   idnList,
                         MPIIdnNumber *number)
Required Header stdmpi.h
Description

IdnListIdnNumber reads the identification numbers of an IdnList object (idnList) and writes it to an array of MPIIdnNumbers pointed to by number.

idnList | a handle to the IdnList object.
*number | a pointer to an array of MPIIdnNumbers returned by the method.
Return Values
MPIMessageOK if IdnListIdnNumber successfully gets the list of identification numbers.
See Also | mpiIdnNumberGET


mpiIdnListIdnNumberFind

Declaration
long mpiIdnListIdnNumberFind(MPIIdnList   idnList,
                             MPIIdnNumber idnNumber
                             MPIIdn       *idn)
Required Header stdmpi.h
Description

IdnListIdnNumberFind searches the idnList and writes to idn the handle to the MPIIdn object whose idn number is idnNumber.
Return Values
MPIMessageOK if IdnListIdnNumberFind is successful
See Also


mpiIdnListInsert

Declaration
long mpiIdnListInsert(MPIIdnList idnList,
                      MPIIdn     idn,
                      MPIIdn     insert)
Required Header stdmpi.h
Description

IdnListInsert inserts an Idn object (insert) in an IdnList (idnList), just after this Idn object (idn).

Return Values
MPIMessageOK if IdnListInsert successfully inserts the Idn into the IdnList, in the slot after the specified Idn (idn)
See Also


mpiIdnListIndex

Declaration
long mpiIdnListIndex(MPIIdnList idnList,
                      MPIIdn    idn)
Required Header stdmpi.h
Description IdnListIndex returns the position of "idn" on the list.
idnList | a handle to the IdnList object.
idn | a handle to an Idn object.

Return Values
index | of an Idn (idn) in an IdnList (idnList)
MPIHandleVOID | if idnList is invalid if idnList is empty
See Also


mpiIdnListLast

Declaration
MPIIdn mpiIdnListLast(MPIIdnList idnList)
Required Header stdmpi.h
Description

The last element in the list is returned. This function can be used in conjuntion with mpiIdnListIdnPrevious() in order to iterate through the list backwards.

idnList | a handle to the IdnList object.

Return Values
handle | to the last Idn object of an IdnList (idnList)
MPIHandleVOID | if idnList is invalid if idnList is empty
MPIMessageHANDLE_INVALID | if idnList is an invalid handle.

See Also | mpiIdnListFirst


mpiIdnListNext

Declaration
MPIIdn mpiIdnListNext(MPIIdnList idnList,
                      MPIIdn     idn)
Required Header stdmpi.h
Description

IdnListNext returns the next element following "idn" on the list. This function can be used in conjuntion with mpiIdnListIdnFirst() in order to iterate through the list.

idnList | a handle to the IdnList object.
idn | a handle to an Idn object.

Return Values
handle | to the Idn object following another Idn object (idn) in an IdnList (idnList)
MPIHandleVOID | if idnList is invalid if idnList is the last Idn object in the IdnList (idnList)
MPIMessageHANDLE_INVALID | Either idnList or idn is an invalid handle.

See Also | mpiIdnListPrevious


mpiIdnListPrevious

Declaration
MPIIdn mpiIdnListPrevious(MPIIdnList idnList,
                          MPIIdn     idn)
Required Header stdmpi.h
Description

IdnListPrevious returns the previous element prior to "idn" on the list. This function can be used in conjuntion with mpiIdnListLast() in order to iterate through the list backwards.

idnList | a handle to the IdnList object.
idn | a handle to an Idn object.

Return Values
handle | to the Idn object preceding another Idn object (idn) in an IdnList (idnList)
MPIHandleVOID | if idnList is invalid if idnList is the first Idn object in the IdnList (idnList)
MPIMessageHANDLE_INVALID | Either idnList or idn is an invalid handle.

See Also | mpiIdnListLast | mpiIdnListNext


mpiIdnListRemove

Declaration
long mpiIdnListRemove(MPIIdnList idnList,
                      MPIIdn     idn)
Required Header stdmpi.h
Description

IdnListRemove removes an Idn (idn) from an IdnList (idnList).
Return Values
MPIMessageOK if IdnListRemove successfully removes the Idn object from the IdnList
See Also


mpiIdnListSet

Declaration
long mpiIdnListSet(MPIIdnList idnList,
                   long       idnCount,
                   MPIIdn     *idnArray)
Required Header stdmpi.h
Description

IdnListSet creates a list (idnList) of idnCount Idn objects, using the Idn handles specified by idnArray.Any existing list is completely replaced.

The idnArray argument is the address of an array of idnCount Idn handles, or is NULL (if idnCount is equal to zero).

You can also create an IdnList incrementally (one Idn at a time), by using the mpiIdnListAppend(...) and/or mpiIdnListInsert(...) methods. To specify the initial Idn object of an IdnList, use the idn argument of mpiIdnListCreate(...). You can use any mpiIdnList method to examine and manipulate an IdnList, regardless of how the IdnList was created.
Return Values
MPIMessageOK if IdnListSet successfully creates the IdnList using the handles in idnArray
See Also | mpiIdnListInsert | mpiIdnListAppend | mpiIdnListCreate | mpiIdnListGet


mpiIdnListValidate

Declaration
long mpiIdnListValidate(MPIIdnList idnList)
Required Header stdmpi.h
Description

IdnListValidate validates the IdnList object and its handle (idnList).
Return Values
MPIMessageOK if IdnList is a handle to a valid object.
See Also | mpiIdnListCreate | mpiIdnListDelete


Message Objects

Introduction |
 | The Message module manages text strings associated with the error code return values. Each error return value has a unique value which can be decoded using the Message methods and macros.
Methods
Configuration and Information Methods
 | mpiMessage |
 | mpiMessageFunction | Associate message text with a function
Macros
mpiMessageID
mpiMessageMODULE
mpiMessageNUMBER


mpiMessageFunction

Declaration
long mpiMessageFunction(MPIModuleId        moduleId,
                        MPIMessageFunction function)
Required Header stdmpi.h
Description

MessageFunction registers function as the function to be called by mpiMessage(...) (in order to obtain the text for a message associated with module moduleId).

MessageFunction is typically called internally by object create methods. Applications generally do not need to call MessageFunction directly.

Return Values
MPIMessageOK if MessageFunction successfully registers function as the function to be called by mpiMessage(...)
See Also | mpiMessage


mpiMessageID

Declaration

#define mpiMessageID(module number) \
((long)((((module) & MPIModuleIdMAX) << 8) | \ ((number) & 0xFF)))
Required Header stdmpi.h
Description

MessageID converts the message module value and number to a unique message identification value.

See Also | mpiMessage


mpiMessageMODULE

Declaration

#define mpiMessageMODULE(messageId) \
(((messageId) & (MPIModuleIdMAX << 8)) >> 8)
Required Header stdmpi.h
Description

MessageMODULE converts the message identification value to the message module value.

See Also | mpiMessage


mpiMessage

Declaration
const char *mpiMessage(long  messageId,
                       char  *messageText)
Required Header stdmpi.h
Description

mpiMessage returns the text message associated with messageId and copies the text to messageText if messageText is not NULL.

If "messageText" is | Then
NULL | Message returns a pointer to message text resident in the library
not NULL | Message returns the pointer messageText, which must point to a buffer large enough to hold the message text (that will be copied into it)

Return Values
NULL | if messageId is invalid
Pointer to an empty string (" ") | if the messge utility is not enabled or the message function pointer associated with messageId is NULL.
Pointer to a non-zero-length string | if the mpiMessage successsfully retrieves the message associated with messageId.

See Also | mpiMessageFunction


mpiMessageNUMBER

Declaration

#define mpiMessageNUMBER(messageId) ((messageId) & 0xFF)
Required Header stdmpi.h
Description

MessageNUMBER converts the message identification value to the message number.

See Also | mpiMessage


Motion Objects

Introduction

A Motion object manages a single axis or group of axes. Its primary function is to provide an interface to command movement on a coordinate system. It also provides status information about all the axes under its control, so motion can be either stopped or resumed in a controlled manner, especially in the event of error recovery. The Motion object is really a host-based object, with a corresponding Motion Supervisor object in the controller. The Motion Supervisor handles the real-time issues associated with axis data and status synchronization.

Some careful consideration should be given to Motion object (Motion Supervisor) to axis mapping. While it's possible to have multiple Motion objects share the same axes, only one Motion Supervisor can command motion to an axis at a time. Motion object to axis maps can be changed dynamically at any time, but Motion Supervisor to axis maps should NOT be changed when the axes are moving.

To learn more about usind MPI Motion Attributes and MEI Motion Attributes, click here.

| Error Messages |
Methods
Create, Delete, Validate Methods
 | mpiMotionCreate | Create Motion object
 | mpiMotionDelete | Delete Motion object
 | mpiMotionValidate | Validate Motion object

Configuration and Information Methods
 | mpiMotionConfigGet | Get Motion configuration
 | mpiMotionConfigSet | Set Motion configuration
 | mpiMotionFlashConfigGet | Get Motion flash config
 | mpiMotionFlashConfigSet | Set Motion flash config
 | mpiMotionParamsGet | Get Motion parameters
 | mpiMotionParamsSet | Set Motion parameters
 | meiMotionParamsValidate | Validate Motion parameters
 | mpiMotionPositionGet | Get position parameters of all axes associated with Motion
 | mpiMotionPositionSet | Set position parameters of all axes associated with Motion
 | mpiMotionStatus | Get Motion status
 | mpiMotionTrajectory | Get trajectories for all Axis associated with Motion
Event Methods
 | mpiMotionEventNotifyGet | Get event mask
 | mpiMotionEventNotifySet | Set event mask
 | mpiMotionEventReset | Reset events specified in event mask
Action Methods
 | mpiMotionAction | Perform an action on a Motion
 | mpiMotionModify | Modify parameters of Motion while it is executing
 | mpiMotionStart | Start Motion (idle state > moving state)
Memory Methods
 | mpiMotionMemory | Set address to be used to access Motion memory
 | mpiMotionMemoryGet | Get bytes of Motion memory and place it into application memory
 | mpiMotionMemorySet | Put (set) bytes of application memory into Motion memory
Relational Methods
 | mpiMotionControl | Return handle of Control object associated with Motion
 | mpiMotionNumber | Get index of Motion
 | mpiMotionAxis | Return handle of axis by index number
 | mpiMotionAxisAppend | Append axis to list
 | mpiMotionAxisCount | Return number of axes in list
 | mpiMotionAxisFirst | Return handle to first axis in list
 | mpiMotionAxisIndex | Return index value of an axis in list
 | mpiMotionAxisInsert | Insert axis into list associated with Motion
 | mpiMotionAxisLast | Return handle to last axis in list
 | mpiMotionAxisListGet | Get list of axes associated with Motion
 | mpiMotionAxisListSet | Create a list of axes associated with Motion
 | mpiMotionAxisNext | Get handle to next axis in list
 | mpiMotionAxisPrevious | Get handle to previous axis in list
 | mpiMotionAxisRemove | Remove handle to axis in list

Data Types
MPIMotionAttr / MEIMotionAttr
MEIMotionAttrHold
MEIMotionAttrHoldSource
MEIMotionAttrHoldType
MPIMotionAttrMask / MEIMotionAttrMask
MEIMotionAttrOutput
MEIMotionAttrOutputType
MPIMotionAttributes / MEIMotionAttributes
MPIMotionBESSEL
MPIMotionBSPLINE
MPIMotionConfig / MEIMotionConfig
MPIMotionDecelTime
MEIMotionFrame
MEIMotionFrameBufferStatus
MPIMotionMessage / MEIMotionMessage
MPIMotionParams / MEIMotionParams
MPIMotionPoint
MPIMotionPT
MPIMotionPVT
MPIMotionSCurve
MPIMotionSPLINE
MEIMotionTrace
MPIMotionTrapezoidal
MPIMotionType / MEIMotionType
MPIMotionVelocity

Macros
mpiMotionATTR
mpiMotionAttrMaskBIT
mpiMotionTYPE


 Diagram of mpiMotionStart

The diagram below explains how mpiMotionStart(...) executes.

Return to mpiMotionStart


 Motion Error Codes and Messages
Code | Message | Tips / Fixes
0x0d01 (3329) | Motion: motion invalid | The Motion parameters are incorrect. Recheck them.
0x0d02 (3330) | Motion: axis not found | The Axis number is invalid.
0x0d03 (3331) | Motion: axis count invalid | You may be commanding moves on Axes that don’t exist, or on zero Axes.
0x0d04 (3332) | Motion: type invalid | You may have called a motion type that doesn’t exist.
0x0d05 (3333) | Motion: attribute invalid | The value for a motion attribute is wrong.
0x0d06 (3334) | Motion: not ready | The motion controller is still executing the power-up sequence.
0x0d07 (3335) | Motion: MPIStateIDLE | No Motion was in progress when mpiMotionModify(...) was called. In order for mpiMotionModify(...) to work, there must be a motion in progress.
0x0d08 (3336) | Motion: MPIStateMOVING | You may have called mpiMotionStart(...) when a Motion was in progress.
0x0d09 (3337) | Motion: MPIStateSTOPPING | Indicates that a Stop event is in progress.
0x0d0a (3338) | Motion: MPIStateSTOPPING_ERROR | Indicates that an E-Stop event is in progress.
0x0d0b (3339) | Motion: MPIStateERROR | Indicates that an E-Stop or Abort event has occurred. Use mpiMotionAction(MPIActionRESET) to recover.
0x0d0c (3340) | Motion: auto-start | mpiMotionModify(...) was called with the MPIMotionAttrMaskAUTO_START attribute when the motion state was MPIStateIDLE. In this case, the motion profile is automatically started.
0x0d0d (3341) | Motion: profile error | The XMP couldn’t generate the next set of points. Check the motion parameters and attributes.

Return to Motion Objects page


Motion Attributes

Introduction | MPI Motion Attributes | MEI Motion Attributes

Introduction

This section details the use of various Motion Attributes, which are listed individually below. To use Motion Attributes, OR the attribute mask with the MPIMotionType value.

MPI Motion Attributes

MPIMotionAttrAPPEND

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskAPPEND attribute. This makes it possible to buffer several point-to-point motion profiles in the controller. Each successful call to mpiMotionStart(...) with the APPEND attribute will generate an MPIEventTypeMOTION_DONE from the controller when the motion is complete.

The MPIMotionAttrMaskID attribute is supported with MPIMotionAttrMaskAPPEND when calling mpiMotionStart(...). The XMP-Series controller firmware has been modified to buffer the ID values inside the axis' frames. Therefore, applications using the motion and axis event user data must be changed. Since the ID is stored in the controller's axis frames, the mpiMotionEventNotifySet(...) and mpiAxisEventNotifySet(...) must explicitly configure an appropriate axis memory location for the firmware to retrieve the ID. The sample programs motionID1.c and motionID2.c demonstrate this feature.

The MEIMotionAttrHOLD attribute is supported with MPIMotionAttrMaskAPPEND when calling mpiMotionStart(...).

Move Types: PT, PVT, Bessel, Bspline, Bspline2, S-Curve, Trapezoidal, Velocity, Frame
MPIMotionAttrAUTO_START

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskAUTO_START attribute. When AUTO_START is enabled, calls to mpiMotionModify(…) will automatically start a new motion if the previous motion is done. If AUTO_START is not enabled, and mpiMotionModify(...) is commanded after the initial motion has completed, the method will return an MPIMotionStateIDLE error.

Move Types: S-Curve, Trapezoidal, Velocity
MPIMotionAttrDELAY

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskDELAY attribute. This motion attribute will delay the move for a given number of seconds. MPIMotionParams.attributes.delay is a pointer to an array of doubles that assign delay times for each Axis.

Move Types: S-Curve, Trapezoidal, Velocity
MPIMotionAttrELEMENT_ID

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskELEMENT_ID attribute. Similar to the MPIMotionAttrMaskID, the ELEMENT_ID allows the application to set an identification value for each element of a path motion. The ID values are long values configured in the MPIMotionParams.attributes.elementId array. Each element in the array will be the ID value for that sequential portion of the motion.

In order to retrieve the ElementID, a pointer to the element ID is placed into the MEIEventNotifyData structure. This will cause the XMP to send the ElementID up to the MEIEventStatusInfo structure when an event occurs that causes an interrupt.

Move Types: PT, PVT, Bessel, Bspline, Bspline2, S-Curve, Trapezoidal, Velocity
MPIMotionAttrID

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskID attribute. The ID attributes allows the application to assign an identification number to each motion. This number can be returned in the MPIEventStatus structure so the application will know which move has ended. This is particularly useful when multiple moves are buffered and the application needs to know which move is executing or has returned an event.

The MPIMotionParams.attributes.id value is a long that identifies the Motion. This ID value is passed to each Axis associated with the MS. In order to retrieve the MoveID, a pointer to the move ID is placed in the MEIEventNotifyData structure. This will cause the XMP to send the MoveID up to the MEIEventStatusInfo structure when an event occurs that causes an interrupt.

Move Types: PT, PVT, Spline, Bessel, Bspline, Bspline2, S-Curve, Trapezoidal, Velocity, Frame
MPIMotionAttrRELATIVE

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskRELATIVE attribute. When this mask is ANDed into the attribute mask, all position values will be used as relative motion distances instead of final absolute positions. For example, without the RELATIVE motion attribute, a move beginning at position 1000 with a position parameter value of 2000 will move to position 2000. If the RELATIVE attribute is turned on, the final move position will be 3000, a relative distance of 2000 counts from the starting value of 1000.

Move Types: PT, PVT, Spline, Bessel, Bspline, Bspline2, S-Curve, Trapezoidal, Velocity
MPIMotionAttrSYNC_END

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskSYNC_END attribute. SYNC_END is used for motions that include more than one axis. The SYNC_END attribute will generate trajectories for all axes appended to an MS that will end simultaneously. For all but the longest motion profile, wait frames will be added to the beginning of the moves. This will ensure that all axes end simultaneously.

Move Types: S-Curve, Trapezoidal
MPIMotionAttrSYNC_START

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskSYNC_START attribute. SYNC_START is used for Motions that include more than one Axis. All Axes will begin simultaneously. For those axes that finish first, a delay frame will be added to the end of the move.

Move Types: S-Curve, Trapezoidal

MEI Motion Attributes

MEIMotionAttrEVENT

The MPI has been extended to support mpiMotionStart(...) with the MEIMotionAttrMaskEVENT attribute.
MEIMotionAttrFINAL_VEL

The MPI has been extended to support mpiMotionStart(...) with the MEIMotionAttrMaskFINAL_VEL attribute.
MEIMotionAttrNO_REVERSAL

The MPI has been extended to support mpiMotionStart(...) with the MEIMotionAttrMaskNO_REVERSAL attribute.
MEIMotionAttrHOLD

The MPI has been extended to support mpiMotionStart(...) with the MEIMotionAttrMaskHOLD attribute. The HOLD attribute prevents execution of a Motion. The HOLD attribute is applied at the beginning of the motion (one HOLD frame) before the execution of the point list. This prevents execution of the Motion until the HOLD frame is disabled.

The HOLD attribute is used to synchronize the start of motion with a host function call, XMP internal variable, or Motor Input state change. More than one Motion Supervisor may be synchronized. The type field of the MEIMotionAttrHold{} structure determines whether the synchronization comes from a host call (meiControlGateSet(), see below), internal variable (Axis Status, Position, etc.) or a Motor Input signal (transceiver, home input, user input, etc.).

Gated Moves: If the value of type is MEIMotionAttrHoldTypeGATE, the motion will be held until a call to mpiControlGateSet() is made with the closed parameter set to FALSE. When a MEIMotionAttrHoldTypeGATE is used, the source.gate field of MEIMotionAttrHold{} must be set to the gate number (0-31). The same gate number must be used for the gate parameter of meiControlGateSet().

Input Hold Moves: If the value of type is MEIMotionAttrHoldTypeINPUT, the motion will be held until then value of the internal Xmp variable specified (pointed to) by source.input bitwise anded with source.mask matches source.pattern.

Motor Input Hold Moves: If the value of type is MEIMotionAttrHoldTypeMOTOR, the motion will be held until the value of the internal dedicated input word (Motor[n].IO. DedicatedIN.IO) for the motor specified by source.motorNumber bitwise anded with source.mask matches source.pattern.

The timeout field of MEIMotionAttrHold{} will cause the motion to start after the specified timeout period (in seconds), even if the other hold criteria have not been satisfied. A value of zero for timeout causes the timeout feature to be disabled and forces the motion to wait for the hold criteria (gate open, or pattern match).

The MPI expects an array of hold attributes specifying separate attributes form each axis of a motion supervisor. All axes holding with the same hold attributes (same gate, same input, mask, and pattern) will start motion in the same sample even if the moves are specified using different motion supervisors.
MEIMotionAttrOUTPUT

The MPI has been extended to support mpiMotionStart(...) with the MPIMotionAttrMaskAPPEND attribute. This motion attribute allows a Motion to change the state of a register in the controller memory. This configures a frame to toggle an output bit as a move begins.

Return to Motion Objects page


 Returns for mpiMotionStart and mpiMotionModify

Both mpiMotionStart and mpiMotionModify use motion attributes, which are summarized in the table below.

Return Values - for both mpiMotionStart and MotionModify
MPIMotionMessageERROR | if MotionStart is called when the Motion Supervisor is in the error state.
MPIMotionMessageAXIS_COUNT | if the motion object has no axes.
MPIMotionMessagePROFILE_ERROR | if the Motion profile specified by the parameters cannot be calculated correctly.
MPIMotionMessageATTRIBUTE_INVALID | if the specified motion attribute mask is not valid with the motion type.
MPIMessagePARAM_INVALID | if the specified motion parameters are not valid with the Motion type.
MPIMessageARG_INVALID | if any of the MotionStart arguments are not valid.
MPIMessageUNSUPPORTED | if the motion type is not supported by the controller.

Return to mpiMotionStart or mpiMotionModify


MPIMotionAttr and MEIMotionAttr

MPIMotionAttr / MEIMotionAttr

MPIMotionAttr
typedef enum {
    MPIMotionAttrINVALID,

    MPIMotionAttrAPPEND,
    MPIMotionAttrAUTO_START,
    MPIMotionAttrDELAY,
    MPIMotionAttrID,
    MPIMotionAttrELEMENT_ID,
    MPIMotionAttrRELATIVE,
    MPIMotionAttrSYNC_END,
    MPIMotionAttrSYNC_START,
    MPIMotionAttrCOUNT,
} MPIMotionAttr;
Description

The motion attributes are used to generate the motion attribute masks to enable features with mpiMotionStart(…) and mpiMotionModify(…). Please see MPIMotionAttrMask data type for more information.

MEIMotionAttr

typedef enum {

    MEIMotionAttrEVENT,
    MEIMotionAttrFINAL_VEL,
    MEIMotionAttrNO_REVERSAL,
    MEIMotionAttrHOLD,
    MEIMotionAttrOUTPUT,

    MEIMotionAttrCOUNT,
} MEIMotionAttr;
Description

The motion attributes are used to generate the motion attribute masks to enable features with mpiMotionStart(…) and mpiMotionModify(…). Please see MPIMotionAttrMask for more information.

See Also | MPIMotionAttrMask | mpiMotionStart | mpiMotionModify


MEIMotionAttrHold

MEIMotionAttrHold

typedef	struct MEIMotionAttrHold {
    MEIMotionAttrHoldType	type;
    MEIMotionAttrHoldSource	source;
    float			timeout;
} MEIMotionAttrHold;

Description
 | type | This value specifies the motion hold type. Please see MEIMotionAttrHoldType for more information.
 | source | This value specifies the motion hold conditions. Please see MEIMotionAttrHoldSource for more information.
 | timeout | This value specifies the motion hold expiration time (seconds). When the time exceeds the timeout value or the hold conditions are met, the motion profile will execute.

See Also | MEIMotionAttrHoldType | MEIMotionAttrHoldSource


MEIMotionAttrHoldSource

MEIMotionAttrHoldSource

typedef union {
    long	gate;
    struct {
        long	*input;
        long	mask;
        long	pattern;
    } input;
    struct {
        long	number;
        long	mask;
        long	pattern;
        } motor;
} MEIMotionAttrHoldSource;

Description
 | gate | This value specifies the control gate number when MEIMotionAttrHoldTypeGATE is used. Valid values are between 0 and 31. See meiControlGateGet/Set(…) for more information.
 | input (input) | This value specifies the input address when MEIMotionAttrHoldTypeINPUT is used.
 | mask (input) | This value specifies the AND mask when MEIMotionAttrHoldTypeINPUT is used.
 | pattern (input) | This value specifies the comparison pattern when MEIMotionAttrHoldTypeINPUT is used. The value at input.input is bit-wise ANDed with the input.mask and compared to the input.pattern.
 | number (motor) | This value specifies the motor number when MEIMotionAttrHoldTypeMOTOR is used.
 | mask (motor) | This value specifies the AND mask when MEIMotionAttrHoldTypeMOTOR is used.
 | pattern (motor) | This value specifies the comparison pattern when MEIMotionAttrHoldTypeMOTOR is used. The motor input word is bit-wise ANDed with the motor.mask and compared to the motor.pattern.

See Also | MEIMotionAttrHoldType | meiControlGateGet | meiControlGateSet


MEIMotionAttrHoldType

MEIMotionAttrHoldType

typedef enum {
    MEIMotionAttrHoldTypeINVALID,
    MEIMotionAttrHoldTypeNONE,
    MEIMotionAttrHoldTypeGATE,
    MEIMotionAttrHoldTypeINPUT,
    MEIMotionAttrHoldTypeMOTOR,
} MEIMotionAttrHoldType;

Description
 | MEIMotionAttrHoldTypeNONE | This type disables the hold trigger condition.
 | MEIMotionAttrHoldTypeGATE | This type configures a control gate for the hold trigger condition. See meiControlGateGet/Set(…) for more information.
 | MEIMotionAttrHoldTypeINPUT | This type configures a memory address for the hold trigger condition.
 | MEIMotionAttrHoldTypeMOTOR | This type configures a motor's input bit(s) for the hold trigger condition.
Remarks
 | These types specify the motion profile trigger condition. The hold trigger value is specified with the MEIMotionAttrHoldSource data type.

See Also | MEIMotionAttrHoldSource | MEIMotionAttrHold


MPIMotionAttrMask and MEIMotionAttrMask

MPIMotionAttrMask / MEIMotionAttrMask

MPIMotionAttrMask

typedef	enum {
    MPIMotionAttrMaskAPPEND,
    MPIMotionAttrMaskAUTO_START,
    MPIMotionAttrMaskDELAY,
    MPIMotionAttrMaskID,
    MPIMotionAttrMaskELEMENT_ID,
    MPIMotionAttrMaskRELATIVE,
    MPIMotionAttrMaskSYNC_END,
    MPIMotionAttrMaskSYNC_START,
    MPIMotionAttrMaskALL,
} MPIMotionAttrMask;

Description
 | MPIMotionAttrMaskAPPEND | This mask enables the motion profile to be added to the end of a previous motion profile, in the controller's memory buffer. The APPENDed profile will begin execution after the previous profile has completed and the settling criteria has been met. The APPEND mask can be used with mpiMotionStart(…) or mpiMotionModify(…).
 | MPIMotionAttrMaskAUTO_START | This mask converts a mpiMotionModify(…) call to a mpiMotionStart(…) if the modify occurs after the previous motion profile has completed. If the previous profile had completed, then mpiMotionModify(…) will return an error code, MPIMotionMessageAUTO_START.
 | MPIMotionAttrMaskDELAY | This mask enables a time delay (seconds) before the motion profile begins. Please see MPIMotionAttributes for more information. This mask can be used with mpiMotionStart(…).
 | MPIMotionAttrMaskID | This mask enables an identification tag to be stored in the motion profile. Please see MPIMotionAttributes for more information. This mask can be used with mpiMotionStart(…) and mpiMotionModify(…).
 | MPIMotionAttrMaskELEMENT_ID | - This mask enables an identification tag to be stored in the path motion profiles. Please see MPIMotionAttributes for more information.
 | MPIMotionAttrMaskRELATIVE | This mask changes the profile target position from absolute to relative coordinates.
 | MPIMotionAttrMaskSYNC_END | This mask synchronizes the motion profiles for multiple axes so they will all end at the same time. Delays are inserted before the shorter profiles. When enabled, each axis will use its own MPITrajectory values.
 | MPIMotionAttrMaskSYNC_START | This mask synchronizes the motion profiles for multiple axes so they will all start at the same time. Delays are inserted after the shorter profiles. When enabled, each axis will use its own MPITrajectory values.
Remarks
 | The motion attribute masks are used to enable features with mpiMotionStart(…) and mpiMotionModify(…). The masks are ORed with the MPIMotionType to enable each feature.

MEIMotionAttrMask

typedef enum {
    MEIMotionAttrMaskEVENT,
    MEIMotionAttrMaskFINAL_VEL,
    MEIMotionAttrMaskNO_REVERSAL,
    MEIMotionAttrMaskHOLD,
    MEIMotionAttrMaskOUTPUT,
    MEIMotionAttrMaskALL,
} MEIMotionAttrMask;

Description
 | MEIMotionAttrMaskEVENT | This mask allows the user to specify an MPIEventMask during a motion.
 | MEIMotionAttrMaskFINAL_VEL | This mask allows the user to specify a non-zero target velocity for point to point motion types.
 | MEIMotionAttrMaskNO_REVERSAL | This mask prevents a motion profile from changing direction.
 | MEIMotionAttrMaskHOLD | This mask prevents a motion profile from executing until the specified trigger conditions are met.
 | MEIMotionAttrMaskOUTPUT | This mask allows the user to set or clear bits during a motion.

See Also | mpiMotionStart | mpiMotionModify | MPIMotionType | MPITrajectory | MPIEventMask


MEIMotionAttrOutput

MEIMotionAttrOutput

typedef	struct MEIMotionAttrOutput {
    MEIMotionAttrOutputType	type;
    union {
        long	*output;
        long	motor;
    } as;
    long	mask;
    long	pattern;
    long	pointIndex;	/* MEIMotionAttrMaskOUTPUT for path motion - point
                        index for turning on output - used with point lists */
} MEIMotionAttrOutput;

Description
 | type | This value specifies the output type to determine the output bits to be set or cleared.
 | *output | This value specifies the memory address when MEIMotionAttrOutputTypeOUTPUT is used.
 | motor | This value specifies the motor number when MEIMotionAttrOutputTypeMOTOR is used.
 | mask | This value specifies the AND mask when MEIMotionAttrHoldTypeOUTPUT is used.
 | pattern | This value specifies the comparison pattern when MEIMotionAttrHoldTypeOUTPUT is used. The motor output word or output address is bit-wise ANDed with the mask and compared to the pattern.
 | pointIndex | This value specifies an index to a point, when multiple point motion is used.

See Also | MEIMotionAttrOutputType


MEIMotionAttrOutputType

MEIMotionAttrOutputType

typedef enum {
    MEIMotionAttrOutputTypeINVALID,
    MEIMotionAttrOutputTypeNONE,
    MEIMotionAttrOutputTypeMOTOR,
    MEIMotionAttrOutputTypeOUTPUT,
} MEIMotionAttrOutputType;

Description
 | MEIMotionAttrOutputTypeNONE | This type disables the setting/clearing of output bit(s) during motion.
 | MEIMotionAttrOutputTypeMOTOR | This type configures a motor's output bit(s) to be set or cleared during motion.
 | MEIMotionAttrOutputTypeOUTPUT | This type configures bit(s) at a memory address to be set or cleared during motion.

See Also | MEIMotionAttrOutput


MPIMotionAttributes and MEIMotionAttributes

MPIMotionAttributes / MEIMotionAttributes

MPIMotionAttributes

typedef struct MPIMotionAttributes {
    double	*delay;		/* MPIMotionAttrMaskDELAY */
    long	id;		/* MPIMotionAttrMaskID */
    long	*elementId;	/* MPIMotionAttrMaskELEMENT_ID */
} MPIMotionAttributes;

Description
 | delay | This array defines the delay time (seconds) before a motion profile begins execution.
 | id | This value defines the identity for a point to point motion.
 | elementId | This array defines the identity for each element of a path motion.

MEIMotionAttributes

typedef struct MEIMotionAttributes {
    MPIEventMask	eventMask;	/* MEIMotionAttrMaskEVENT */
    double		*finalVelocity;	/* MEIMotionAttrMaskFINAL_VEL */
    MEIMotionAttrHold	*hold;		/* MEIMotionAttrMaskHOLD */
    long		*outputCount;	/* MEIMotionAttrMaskOUTPUT for path motion
                                       - number of outputs - per axis */
    MEIMotionAttrOutput	*output;	/* MEIMotionAttrMaskOUTPUT for path and non
                                       path motion - outputs - per axis */
} MEIMotionAttributes;

Description
 | eventMask | This structure specifies the mask to enable event generation. See MPIEventMask for more information.
 | *finalVelocity | This array specifies the target velocity for each axis when MEIMotionAttrMaskFINAL_VEL is used.
 | *hold | This array specifies the hold configurations for each axis when MEIMotionAttrMaskHOLD is used.
 | *outputCount | This array specifies the number of points per axis, to set/clear an output when MEIMotionAttrMaskOUTPUT is used.
 | *output | This structure specifies the output configuration for each axis when MEIMotionAttrMaskOUTPUT is used.

See Also | MPIEventMask | MEIMotionAttrMask


MPIMotionBESSEL

MPIMotionBESSEL

typedef	struct MPIMotionBESSEL {
    long	pointCount;
    double	*position;
    double	*time;

    MPIMotionPoint  point;
} MPIMotionBESSEL;

Description
 | positionCount | This value specifies the number of points.
 | *position | This array stores the positions for the motion profile. There is one position value per point, per axis. The length of the array must be equal to pointCount multiplied by the number of axes. The positions are interleaved in the array by the axis index.
 | *time | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | point | This structure contains the point configuration. Please see MPIMotionPoint data type for more information.

See Also | MPIMotionPoint


MPIMotionBSPLINE

MPIMotionBSPLINE

typedef	struct MPIMotionBSPLINE {
    long		pointCount;
    double		*position;
    double		*time;

    MPIMotionPoint	point;
} MPIMotionBSPLINE;

Description
 | pointCount | This value specifies the number of points.
 | *position | This array stores the positions for the motion profile. There is one position value per point, per axis. The length of the array must be equal to pointCount multiplied by the number of axes. The positions are interleaved in the array by the axis index.
 | *time | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | point | This structure contains the point configuration. Please see MPIMotionPoint data type for more information.

See Also | MPIMotionPoint


MPIMotionConfig and MEIMotionConfig

MPIMotionConfig / MEIMotionConfig

MPIMotionConfig

typedef struct MPIMotionConfig {
    MPIMotionDecelTime	decelTime;
    float		normalFeedrate;
    float		pauseFeedrate;
}MPIMotionConfig;

Description
 | decelTime | This structure defines the deceleration time for Stop and E-Stop actions. Please see MPIMotionDecelTime data type documentation for more information.
 | normalFeedrate | This value defines the normal feed speed rate. The default value is 1.0 (100%).
 | pauseFeedrate | This value defines the feed speed rate for the Stop action. The default value is 0.0.

MEIMotionConfig

typedef struct	MEIMotionConfig {
    long	axisCount;
    long	axisNumber[MEIXmpMAX_COORD_AXES];
    double	blendLimit;
} MEIMotionConfig;

Description
 | axisCount | The current number of axes mapped to the Motion Supervisor on the controller.
 | axisNumber | This array specifies the axis numbers of the current Axis to Motion Supervisor mapping on the controller.
 | blendLimit | This value specifies the acceleration blending limit criteria. If the change direction is greater than 90 degrees (0 degrees = no change, 180 degrees = about face) the acceleration resulting from the blending can exceed the acceleration limit specified in the motion parameters (180 degrees = acceleration*2.0). The blendLimit allows the user to limit the sharpness of turns to be blended. If cosine (turn angle defined above) is greater than the blendLimit, the motion will be blended. A blend limit value of 0 exclude turns sharper than 90 degrees. 1.0 causes all moves to be blended. -1.0 allows no blending

See Also | MPIMotionDecelTime | mpiMotionModify


MPIMotionDecelTime

MPIMotionDecelTime

typedef struct MPIMotionDecelTime {
    float	stop;	/* seconds */
    float	eStop;	/* seconds */
} MPIMotionDecelTime;

Description
 | stop | This value defines the deceleration time (seconds) for a Stop action. The default value is .5 seconds.
 | eStop | This value defines the deceleration time (seconds) for an E-Stop action. The default value is .05 seconds.
See Also


MEIMotionFrame

MEIMotionFrame

typedef	struct MEIMotionFrame {
    long		pointCount;
    MEIXmpFrame		*frame;
    MPIMotionPoint	point;
} MEIMotionFrame;

Description
 | pointCount | The value specifies the number of frames.
 | *frame | This structure contains the frame data for each frame. See MEIXmpFrame for more information.
 | point | This structure specifies the points configuration. See MPIMotionPoint for more information.

See Also | MPIMotionPoint


MEIMotionFrameBufferStatus

MEIMotionFrameBufferStatus

typedef struct MEIMotionFrameBufferStatus {
    long	size;
    long	frameCount;
} MEIMotionFrameBufferStatus;

Description
 | size | This value specifies the size of the controller's frame buffer.
 | frameCount | This value specifies the number of frames in the controller's frame buffer.
See Also


MPIMotionMessage and MEIMotionMessage

MPIMotionMessage / MEIMotionMessage

MPIMotionMessage

typedef enum {
    MPIMotionMessageMOTION_INVALID,
    MPIMotionMessageAXIS_NOT_FOUND,
    MPIMotionMessageAXIS_COUNT,
    MPIMotionMessageTYPE_INVALID,
    MPIMotionMessageATTRIBUTE_INVALID,
    MPIMotionMessageNOT_READY,
    MPIMotionMessageIDLE,
    MPIMotionMessageMOVING,
    MPIMotionMessageSTOPPING,
    MPIMotionMessageSTOPPING_ERROR,
    MPIMotionMessageERROR,
    MPIMotionMessageAUTO_START,
    MPIMotionMessagePROFILE_ERROR,
    MPIMotionMessagePATH_ERROR,
    MPIMotionMessageFRAMES_LOW,
    MPIMotionMessageFRAMES_EMPTY,
} MPIMotionMessage;

Description
 | MPIMotionMessageMOTION_INVALID | This message code occurs when the motion supervisor number is not valid.
 | MPIMotionMessageAXIS_NOT_FOUND | This message code occurs when an axis that is being removed is not a member of the motion supervisor.
 | MPIMotionMessageAXIS_COUNT | This message code occurs when the axis count exceeds MEIXmpMAX_COORD_AXES.
 | MPIMotionMessageTYPE_INVALID | This message code occurs when the MPIMotionType is not valid.
 | MPIMotionMessageATTRIBUTE_INVALID | This message code occurs when the MPIMotionAttrMask is not valid.
 | MPIMotionMessageNOT_READY | This message code occurs when the controller is in the MPIStateINIT and is not ready to generate motion profiles.
 | MPIMotionMessageIDLE | This message code occurs when mpiMotionModify(…) or mpiMotionAction(…) is called when the motion supervisor is in the IDLE state.
 | MPIMotionMessageMOVING | This message code occurs when mpiMotionStart(…) or mpiMotionAction(…) is called when the motion supervisor is in the MOVING state.
 | MPIMotionMessageSTOPPING | This message code occurs when mpiMotionStart(…), mpiMotionModify(…) or mpiMotionAction(…) is called when the motion supervisor is in the STOPPING state. Motion cannot be started or modified at this time.
 | MPIMotionMessageSTOPPING_ERROR | This message code occurs when mpiMotionStart(…), mpiMotionModify(…) or mpiMotionAction(…) is called when the motion supervisor is in the STOPPING_ERROR state. Motion cannot be started or modified at this time.
 | MPIMotionMessageERROR | This message code occurs when mpiMotionStart(…), mpiMotionModify(…) or mpiMotionAction(…) is called when the motion supervisor is in the ERROR state. Motion cannot be started or modified at this time.
 | MPIMotionMessageAUTO_START | This message code occurs when mpiMotionModify(…) was called when the motion supervisor was in the IDLE state and was automatically converted into an mpiMotionStart(…).
 | MPIMotionMessagePROFILE_ERROR | This message code occurs when the velocity must be reversed, but mpiMotionModify(…) was called with the NO_REVERSAL attribute.
 | MPIMotionMessagePATH_ERROR | This message code occurs when the path motion time slice is set to less than one controller sample period.
 | MPIMotionMessageFRAMES_LOW | XMP internal point list buffer is low.
 | MPIMotionMessageFRAMES_EMPTY | XMP internal point list ran out of frames.

MEIMotionMessage

typedef enum {
    MEIMotionMessageRESERVED0,
    MEIMotionMessageRESERVED1,
    MEIMotionMessageRESERVED2,
    MEIMotionMessageNO_AXES_MAPPED,
} MEIMotionMessage;

Description
 | MEIMotionMessageRESERVED0 | Reserved for specialized use.
 | MEIMotionMessageRESERVED1 | Reserved for specialized use.
 | MEIMotionMessageRESERVED2 | Reserved for specialized use.
 | MEIMotionMessageNO_AXES_MAPPED | Returned from methods that require at least one axes to be associated to motion supervisor object.

See Also | MPIMotionType | MPIMotionAttrMask | mpiMotionModify | mpiMotionAction mpiMotionStart


MPIMotionParams and MEIMotionParams

MPIMotionParams / MEIMotionParams

MPIMotionParams

typedef	struct MPIMotionParams {
    MPIMotionJog	jog;

    MPIMotionPT		pt;
    MPIMotionPVT	pvt;
    MPIMotionSPLINE	spline;
    MPIMotionBESSEL	bessel;
    MPIMotionBSPLINE	bspline;

    MPIMotionSCurve	   sCurve;
    MPIMotionSCurve	   sCurveJerk;
    MPIMotionTrapezoidal   trapezoidal;

    MPIMotionVelocity	velocity;
    MPIMotionVelocity	velocityJerk;

    MPIMotionAttributes	attributes;

    void		*external;
} MPIMotionParams;

Description
 | pt | This structure contains the parameters for a PT motion type. Please see MPIMotionPT data type for more information.
 | pvt | This structure contains the parameters for a PVT motion type. Please see MPIMotionPVT data type for more information.
 | spline | This structure contains the parameters for a SPLINE motion type. Please see MPIMotionSPLINE data type for more information.
 | bessel | This structure contains the parameters for a BESSEL motion type. Please see MPIMotionBESSEL data type for more information.
 | bspline | This structure contains the parameters for a BSPLINE motion type. Please see MPIMotionBSPLINE data type for more information.
 | sCurve | This structure contains the parameters for a S_CURVE motion type. Please see MPIMotionSCurve data type for more information.
 | velocity | This structure contains the parameters for a VELOCITY motion type. Please see MPIMotionVelocity data type for more information.
 | velocityJerk | This structure contains the parameters for a VELOCITY_JERK motion type. Please see MPIMotionVelocity data type for more information.
 | attributes | This structure contains the parameters for motion attributes. Please see MPIMotionAttributes data type for more information.
 | *external | This points to an external structure, containing controller specific parameters. Presently, this only supports MEIMotionAttributes. Please see MEIMotionAttributes data type for more information.

MEIMotionParams

typedef		struct MEIMotionParams {
    MEIMotionFrame	   frame;
    MPIMotionAttributes    attributes;
    MEIMotionAttributes    attributesMEI;
} MEIMotionParams;

Description
 | frame | This structure contains the frame data and points configuration. See MEIMotionFrame for more information.
 | attributes | This structure contains the motion attributes data. See MPIMotionAttributes for more information.
 | attributesMEI | This structure contains the motion attributes data. See MEIMotionAttributes for more information.

See Also | MEIMotionFrame | MPIMotionAttributes | MEIMotionAttributes


MPIMotionPoint

MPIMotionPoint

typedef struct MPIMotionPoint {
    long	retain;		/* FALSE => flush points after use */
    long	final;		/* FALSE => more points to come */
    long	emptyCount;	/* # of remaining points to trigger empty event, -1 => disable */
} MPIMotionPoint;

Description
 | retain | This value specifies whether or not the points should be stored in a buffer after execution. If retain=0, the points will not be stored after execution. If retain=1, the points will be stored in a buffer. This feature is useful for backing up on path.
 | final | This value specifies if more points will be loaded. If final=1, no more points will be loaded. If final=0, more points can be loaded using mpiMotionModify(…) with the MPIMotionAttrMaskAPPEND attribute mask.
 | emptyCount | This value specifies the minimum number of points in the buffer. If the number of points in the buffer is below emptyCount, an E_STOP action will occur. When emptyCount is (-1), the buffer low trigger is disabled.

See Also | mpiMotionModify | MPIMotionAttrMaskAPPEND | MPIMotionPT


MPIMotionPT

MPIMotionPT

typedef		struct MPIMotionPT {
    long      pointCount;
    double    *position;
    double    *time;
    MPIMotionPoint	point;
} MPIMotionPT;

Description
 | pointCount | This value specifies the number of points.
 | position | This array stores the positions for the motion profile. There is one position value per point, per axis. The length of the array must be equal to pointCount multiplied by the number of axes. The positions are interleaved in the array by the axis index.
 | time | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | point | This structure contains the point configuration. Please see MPIMotionPoint data type for more information.

See Also | MPIMotionPoint


MPIMotionPVT

MPIMotionPVT

typedef	struct MPIMotionPVT {
    long		pointCount;
    double		*position;
    double		*velocity;
    double		*time;
    MPIMotionPoint	point;
} MPIMotionPVT;

Description
 | pointCount | This value specifies the number of points.
 | position | This array stores the positions for the motion profile. There is one position value per point, per axis. The length of the array must be equal to pointCount multiplied by the number of axes. The positions are interleaved in the array by the axis index.
 | velocity | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | time | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | point | This structure contains the point configuration. Please see MPIMotionPoint data type for more information.

See Also | MPIMotionPoint


MPIMotionSCurve

MPIMotionSCurve

typedef struct MPIMotionSCurve {
    MPITrajectory   *trajectory;
    double          *position;
} MPIMotionSCurve;

Description
 | *trajectory | This structure specifies the parameters for the motion profile.
 | *position | This array specifies the target positions for the axes. There is one position for each axis.
See Also


MPIMotionSCurveJerk

MPIMotionSCurveJerk

typedef MPIMotionSCurve MPIMotionSCurveJerk;
Description

MPIMotionSCurveJerk is a copy of MPIMotionSCurve.

See Also | MPIMotionSCurve


MPIMotionTrapezoidal

MPIMotionTrapezoidal

typedef MPIMotionSCurve MPIMotionTrapezoidal;
Description

MPIMotionTrapezoidal is a copy of MPIMotionSCurve.

See Also | MPIMotionSCurve


MPIMotionSPLINE

MPIMotionSPLINE

typedef		struct MPIMotionSPLINE {
    long		pointCount;
    double		*position;
    double		*time;

    MPIMotionPoint	point;
} MPIMotionSPLINE;

Description
 | pointCount | This value specifies the number of points.
 | *position | This array stores the positions for the motion profile. There is one position value per point, per axis. The length of the array must be equal to pointCount multiplied by the number of axes. The positions are interleaved in the array by the axis index.
 | *time | This array stores the times for the motion profile. There is one time value per point. The time specifies the number of seconds between the specified position, and the next position (point). The length of the time array must be equal to pointCount.
 | point | This structure contains the point configuration. Please see MPIMotionPoint data type for more information.

See Also | MPIMotionPoint


MPIMotionTrapezoidal

MPIMotionTrapezoidal

typedef struct MPIMotionTrapezoidal {
    MPITrajectory   *trajectory;
    double          *position;
} MPIMotionTrapezoidal;

Description
 | *trajectory | This structure specifies the parameters for the motion profile.
 | *position | This array specifies the target positions for the axes. There is one position for each axis.
See Also


MEIMotionTrace

MEIMotionTrace

typedef enum {

    MEIMotionTraceSTATUS,
    MEIMotionTracePARAMS,
} MEIMotionTrace;

Description
 | MEIMotionTraceSTATUS | This trace bit enables motion status tracing for mpiMotion calls.
 | MEIMotionTracePARAMS | This trace bit enables motion parameters tracing for mpiMotion calls.
See Also


MPIMotionType and MEIMotionType

MPIMotionType / MEIMotionType

MPIMotionType

typedef enum {
    MPIMotionTypeINVALID,
    MPIMotionTypeJOG,

    MPIMotionTypePT,
    MPIMotionTypePVT,
    MPIMotionTypeSPLINE,
    MPIMotionTypeBESSEL,
    MPIMotionTypeBSPLINE,
    MPIMotionTypeBSPLINE2,

    MPIMotionTypeS_CURVE,
    MPIMotionTypeTRAPEZOIDAL,
    MPIMotionTypeS_CURVE_JERK,

    MPIMotionTypeVELOCITY,
    MPIMotionTypeVELOCITY_JERK,
    MPIMotionTypeMASK,
} MPIMotionType;
Description

MPIMotionType specifies the particular motion profile algorithm to be generated with mpiMotionStart(…) and mpiMotionModify(…).

MPIMotionTypePT | This type fits constant velocity profile segments through a list of position and time points. Please see MPIMotionPT for more information.
MPIMotionTypePVT | This type fits jerk profile segments through a list of position, velocity and time points. Please see MPIMotionPVT for more information.
MPIMotionTypeSPLINE | This type fits a Cubic spline through a specified list of position and time points. Please see MPIMotionSPLINE data type for more information.
MPIMotionTypeBESSEL | This type fits a Bessel spline through a specified list of position and time points. Please see MPIMotionBESSEL data type for more information.
MPIMotionTypeBSPLINE | This type fits a 3rd order B spline through a list of position and time points. Please see MPIMotionBSPLINE data type for more information.
MPIMotionTypeBSPLINE2 | This type fits a 2nd order B spline through a list of position and time points. Please see MPIMotionBSPLINE data type for more information.
MPIMotionTypeS_CURVE | This type specifies point to point motion using a S-Curve velocity profile. The profile is specified by acceleration, velocity, deceleration, jerkPercent, and final position. Please see MPIMotionSCurve data type for more information.
MPIMotionTypeS_CURVE_JERK | This type specifies point to point motion using a S-Curve velocity profile. The profile is specified by acceleration, velocity, deceleration, accelerationJerk, decelerationJerk, and final position. Please see MPIMotionSCurve data type for more information.
MPIMotionTypeTRAPEZOIDAL | This type specifies simple point to point motion using a trapezoidal velocity profile. The profile trajectory is specified by acceleration, velocity, deceleration and final position. Please see MPIMotionTrapezoidal data type for more information.
MPIMotionTypeVELOCITY | This type specifies S-Curve acceleration to a constant velocity. The profile trajectory is specified by acceleration, velocity, and jerkPercent. Please see MPIMotionVelocity data type for more information.
MPIMotionTypeVELOCITY_JERK | This type specifies S-Curve acceleration to a constant velocity. The profile trajectory is specified by acceleration, velocity, accelerationJerk and decelerationJerk. Please see MPIMotionVelocity data type for more information.

MEIMotionType

typedef enum {
    MEIMotionTypeFRAME,
} MEIMotionType;

Description
 | MEIMotionTypeFRAME | This motion type is used to construct motion profiles at the frame level.

See Also | mpiMotionStart | mpiMotionModify | mpiMotionTYPE


MPIMotionVelocity

MPIMotionVelocity

typedef struct MPIMotionVelocity {
    MPITrajectory	*trajectory;
} MPIMotionVelocity;

Description
 | *trajectory | This structure specifies the parameters for the motion profile, except deceleration is ignored. Please see MPITrajectory data type for more information.

See Also | MPITrajectory


mpiMotionAction

Declaration
long mpiMotionAction(MPIMotion motion,
                     MPIAction action)
Required Header stdmpi.h
Description

MotionAction performs the specified action on the Motion object (motion).

The deceleration stop and Estop times can be set with:

mpiMotionConfigSet(MPIMotion motion, MPIMotionConfig *config, void *external);

where the structure MPIMotionConfig, contains the elements:

MPIMotionConfig.decelTime.stop /* seconds */
MPIMotionConfig.decelTime.eStop /* seconds */

If "action" is | Then
MPIActionABORT or MPIActionE_STOP or MPIActionE_STOP_ABORT | the Motion will perform an emergency stop and/or abort on all axes, and then change to the error state (MPIStateSTOPPING_ERROR to MPIStateERROR). Before starting another Motion, you must first make a call to mpiMotionAction(motion, MPIActionRESET).
MPIActionABORT | MotionAction will disable the PID control (or other algorithm), set the DAC output to the offset value, and disable the amp enable outputs. After the abort completes, the Motion will be set to the ERROR state .
MPIActionE_STOP | MotionAction will decelerate the axis (or axes) to a stop in the time specified by the “eStop” time. After the Motion stops, the Motion will be set to the ERROR state.
MPIActionE_STOP_ABORT | MotionAction will decelerate the axis (or axes) to a stop in the time specified by the “eStop” time. Next, MotionAction will generate an MPIActionABORT. After the abort completes, the Motion is set to the ERROR state. The E_STOP_ABORT first performs an E_STOP, and then performs an ABORT. The E_STOP decelerates the axis to a stop, then the ABORT disables PID control and disables the amp enable output.
MPIActionRESET | if the Motion (motion) is in the error state (MPIStateERROR), the Motion will change to the idle state (MPIStateIDLE), so that motion can be restarted. If the error state was caused by an Abort action, then the command position will be set equal to the actual position during the Reset.
MPIActionRESUME | if the Motion is in the idle state (MPIStateIDLE), it will change to the moving state (MPIStateMOVING), and the Motion will resume if it was stopped by a prior call to mpiMotionAction(motion, MPIActionSTOP).
MPIActionSTOP | if the Motion is in the moving state (MPIStateMOVING), it will performing a stop on all axes and change to the idle state (MPIStateSTOPPING to MPIStateIDLE). MPIActionSTOP decelerates the axis (or axes) to a stop in the time specified by the “stop” time. After the motion stops, the Motion is set to the ERROR state.
Return Values
MPIMessageOK if MotionAction successfully performs the specified action on the Motion object
See Also


mpiMotionATTR

Declaration

#define	 mpiMotionATTR(type,attr)
((type) |= mpiMotionAttrMaskBIT(attr))
Required Header stdmpi.h
Description

MotionATTR turns on the specified motion attribute mask bits in the motion type.

See Also | MPIMotionAttr | MPIMotionAttrMask


mpiMotionAttrMaskBIT

Declaration
#define mpiMotionAttrMaskBIT(attr) (0x1 << (attr))
Required Header stdmpi.h
Description

MotionAttrMaskBIT converts the motion attribute into the motion attribute mask.

See Also | MPIMotionAttr | MPIMotionAttrMask


mpiMotionAxis

Declaration
const MPIAxis mpiMotionAxis(MPIMotion motion,
                            long      index)
Required Header stdmpi.h
Description

MotionAxis returns the element at the position on the list indicated by index.

motion | a handle to the Motion object.
index | a position in the list.

Return Values
handle | to the indexth Axis of a Motion (motion)
MPIHandleVOID | if motion is invalid if index is less than 0 if index is greater than or equal to mpiMotionAxisCount(motion)
MPIMessageARG_INVALID | index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | motion is an invalid handle.
See Also


mpiMotionAxisAppend

Declaration
long mpiMotionAxisAppend(MPIMotion  motion,
                         MPIAxis    axis)
Required Header stdmpi.h
Description

MotionAxisAppend appends an Axis (axis) to a Motion (motion).

motion | a handle to the Motion object.
axis | a handle to an Axis object.

Return Values
MPIMessageOK | if MotionAxisAppend successfully appends an Axis to a Motion object
MPIMessageHANDLE_INVALID | Either motion or axis is an invalid handle.
MPIMessageUNSUPPORTED | The list already contains the maximum number of elements (MEIXmpMAX_COORD_AXES). -or- motion and axis are on different controllers.
MPIMessageOBJECT_NOT_ENABLED | axis is not an enabled axis.
MPIMessageOBJECT_ON_LIST | axis is already on the list.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiMotionAxisCount

Declaration
long mpiMotionAxisCount(MPIMotion motion)
Required Header stdmpi.h
Description

MotionAxisCount returns the number of elements on the list.

motion | a handle to the Motion object.

Return Values
number | of Axes in a Motion (motion)
-1 | if motion is invalid
0 | if motion is empty

See Also | mpiMotionAxis | mpiMotionAxisAppend


mpiMotionAxisFirst

Declaration
const MPIAxis mpiMotionAxisFirst(MPIMotion  motion)
Required Header stdmpi.h
Description

MotionAxisFirst return the first element in the list. This function can be used in conjuntion with mpiMotionAxisNext() in order to iterate through the list.

motion | a handle to the Motion object.

Return Values
handle | to the first Axis of a Motion (motion)
MPIHandleVOID | if motion is invalid if motion is empty
MPIMessageHANDLE_INVALID | motion is an invalid handle.

See Also | mpiMotionAxisNext | mpiMotionAxisLast


mpiMotionAxisInsert

Declaration
long mpiMotionAxisInsert(MPIMotion motion,
                         MPIAxis   axis,
                         MPIAxis   insert)
Required Header stdmpi.h
Description

MotionAxisInsert inserts an Axis (insert) in a Motion (motion), just after the specified Axis (axis).

Return Values
MPIMessageOK if MotionAxisInsert successfully inserts an Axis (insert) in a Motion (motion) following a specified Axis (axis)
See Also | mpiMotionAxis


mpiMotionAxisIndex

Declaration
long mpiMotionAxisIndex(MPIMotion motion,
                        MPIAxis   axis)
Required Header stdmpi.h
Description

MotionAxisIndex returns the position of "axis" on the list.

motion | a handle to the Motion object.
axis | a handle to an Axis object.

Return Values
index | of an Axis (axis) in a Motion (motion)
-1 | if motion is invalid if the Axis (axis) was not found in the Motion (motion)

See Also | mpiMotionAxis


mpiMotionAxisLast

Declaration
const MPIAxis mpiMotionAxisLast(MPIMotion motion)
Required Header stdmpi.h
Description

MotionAxisLast returns the last element in the list. This function can be used in conjuntion with mpiMotionAxisPrevious() in order to iterate through the list backwards.

motion | a handle to the Motion object.

Return Values
handle | to the last Axis of a Motion (motion)
MPIHandleVOID | if motion is invalid if motion is empty
MPIMessageHANDLE_INVALID | Either motion or axis is an invalid handle.

See Also | mpiMotionAxisPrevious


mpiMotionAxisListGet

Declaration
long mpiMotionAxisListGet(MPIMotion  motion,
                          long       *axisCount,
                          MPIAxis    *axisList)
Required Header stdmpi.h
Description

MotionAxisListGet gets the coordinate system of a Motion object (motion).

MotionAxisListGet writes the number of axes (in the coordinate system) to a location (pointed to by axisCount), and also writes an array (of axisCount Axis handles) to another location (pointed to by axisList).

Return Values
MPIMessageOK if MotionAxisListGet successfully gets the coordinate system of a Motion object
See Also | mpiMotionAxisListSet | mpiMotionAxis


mpiMotionAxisListSet

Declaration
long mpiMotionAxisListSet(MPIMotion  motion,
                          long       axisCount,
                          MPIAxis    *axisList)
Required Header stdmpi.h
Description

MotionAxisListSet creates a coordinate system of axisCount dimensions, using the Axis handles specified by axisList. Any existing coordinate system is completely replaced.

The axisList parameter is the address of an array of axisCount Axis handles, or is NULL (if axisCount is equal to zero).

A coordinate system may also be created incrementally (i.e. one Axis at a time) by using the append and/or insert methods described in this section. The initial Axis of a coordinate system may be specified using the axis parameter of mpiMotionCreate(...). The list methods in this section may be used to examine and manipulate a coordinate system (i.e. axis list) regardless of how it was created.
Return Values
MPIMessageOK if MotionAxisListSet successfully creates a coordinate system
See Also | mpiMotionCreate | mpiMotionAxisListGet | mpiMotionAxis


mpiMotionAxisNext

Declaration
const MPIAxis mpiMotionAxisNext(MPIMotion motion,
                                MPIAxis   axis)
Required Header stdmpi.h
Description

MotionAxisNext returns the next element following "axis" on the list. This function can be used in conjuntion with mpiMotionAxisFirst() in order to iterate through the list.

motion | a handle to the Motion object.
axis | a handle to an Axis object.

Return Values
handle | to the Axis just after the specified Axis (axis) in a Motion (motion)
MPIHandleVOID | if motion is invalid if the specified Axis (axis) is the last axis in a Motion (motion)
MPIMessageHANDLE_INVALID | Either motion or axis is an invalid handle.

See Also | mpiMotionAxisFirst | mpiMotionAxisPrevious


mpiMotionAxisPrevious

Declaration
const MPIAxis mpiMotionAxisPrevious(MPIMotion motion,
                                    MPIAxis   axis)
Required Header stdmpi.h
Description

MotionAxisPrevious returns the previous element prior to "axis" on the list. This function can be used in conjuntion with mpiMotionAxisLast() in order to iterate through the list backwards.

motion | a handle to the Motion object.
axis | a handle to an Axis object.

Return Values
handle | to the Axis preceding the specified Axis (axis) in a Motion (motion)
MPIHandleVOID | if motion is invalid if the specfied Axis (axis) is the first Axis in a Motion (motion)
MPIMessageHANDLE_INVALID | Either motion or axis is an invalid handle.

See Also | mpiMotionAxisLast | mpiMotionAxisNext


mpiMotionAxisRemove

Declaration
long mpiMotionAxisRemove(MPIMotion  motion,
                         MPIAxis    axis)
Required Header stdmpi.h
Description

MotionAxisRemove removes an Axis (axis) from a Motion (motion).

Return Values
MPIMessageOK if MotionAxisRemove successfully removes the Axis from the Motion object
See Also


mpiMotionConfigGet

Declaration
long mpiMotionConfigGet(MPIMotion        motion,
                        MPIMotionConfig  *config,
                        void             *external)
Required Header stdmpi.h
Description

MotionConfigGet gets the configuration of a Motion object (motion) and puts (writes) it in the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIMotionConfig{} or is NULL.

Return Values
MPIMessageOK if MotionConfigGet successfully gets the configuration of a Motion object and writes it into the structure(s)
See Also | mpiMotionConfigSet | MEIMotionConfig


mpiMotionConfigSet

Declaration
long mpiMotionConfigSet(MPIMotion       motion,
                        MPIMotionConfig *config,
                        void            *external)
Required Header stdmpi.h
Description

MotionConfigSet sets (writes) the configuration of a Motion object (motion) using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIMotionConfig{} or is NULL.
Return Values
MPIMessageOK if MotionConfigSet successfully writes the configuration of a Motion object using data from the structure(s)
See Also | mpiMotionConfigGet | MEIMotionConfig


mpiMotionControl

Declaration
const MPIControl mpiMotionControl(MPIMotion  motion)
Required Header stdmpi.h
Description

MotionControl returns a handle to the Control object with which the motion is associated.

motion | a handle to the Motion object

Return Values
MPIControl | handle to a Control object
MPIHandleVOID | if motion is invalid

See Also | mpiMotionCreate | mpiControlCreate


mpiMotionCreate

Declaration
const MPIMotion mpiMotionCreate(MPIControl control,
                                long       number,
                                MPIAxis    axis)
Required Header stdmpi.h
Description

MotionCreate creates a Motion object associated with the motion supervisor identified by number located on motion controller control. MotionCreate is the equivalent of a C++ constructor.

If number is -1, MotionCreate selects the next unused motion supervisor. The axis parameter specifies the initial element in the list of Axis objects which determine the coordinate system (axis may be MPIHandleVOID).

Return Values
handle | handle to a Motion object
MPIHandleVOID | if the object could not be created

See Also | mpiMotionDelete | mpiMotionValidate


mpiMotionDelete

Declaration
long mpiMotionDelete(MPIMotion motion)
Required Header stdmpi.h
Description

MotionDelete deletes a Motion object (motion) and invalidates its handle. MotionDelete is the equivalent of a C++ destructor.

Deleting a Motion object does not delete any of the Axis objects in the coordinate system.
Return Values
MPIMessageOK if MotionDelete successfully deletes a Motion object and invalidates its handle
See Also | mpiMotionCreate | mpiMotionValidate


mpiMotionEventNotifyGet

Declaration
long mpiMotionEventNotifyGet(MPIMotion    motion,
                             MPIEventMask *eventmask,
                             void         *external)
Required Header stdmpi.h
Description

MotionEventNotifyGet writes the event mask (that specifies the event type(s) for which host notification has been requested) to the location pointed to by eventMask, and also writes it into the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventmask, i.e, the event notification information in eventmask and in external is not the same information. Note that eventmask or external can be NULL (but not both NULL).

Event notification is enabled for event types specified in eventmask, which is a bit mask generated by the logical OR of the MPIEventMask bits associated with the desired MPIEventType values.
Event notification is disabled for event types not specified in eventmask.

XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL.
The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).

Return Values
MPIMessageOK if MotionEventNotifyGet successfully writes the event mask to the location(s)
See Also | MPIEventType | MEIEventNotifyData | MEIEventStatusInfo mpiMotionEventNotifySet


mpiMotionEventNotifySet

Declaration
long mpiMotionEventNotifySet(MPIMotion    motion,
                             MPIEventMask eventmask,
                             void         *external)
Required Header stdmpi.h
Description

MotionEventNotifySet requests host notification of the event(s) that are generated by motion and specified by eventMask, and also specified by the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventmask, i.e, the event notification information in eventmask and in external is not the same information. Note that eventmask or external can be NULL (but not both NULL).

Event notification is enabled for event types specified in eventMask, a bit mask generated by the bitwise OR of the MPIEventMask bits associated with the desired MPIEventType values. Event notification is disabled for event types that are not specified in eventMask.

The mask of event types generated by a Motion object consists of bits from MPIEventMaskMOTION and MPIEventMaskAXIS.

XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL.
The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).

To... | Then...
enable host notification of all events | set eventmask to MPIEventMaskALL
disable host notification of all events | set eventmask to MPIEventTypeNONE
Return Values
MPIMessageOK if MotionEventNotifySet successfully requests host notification of the event(s) that are specified by eventMask and generated by motion
See Also | MPIEventType | MEIEventNotifyData | MEIEventStatusInfo mpiEventMaskMOTION | mpiEventMaskAXIS | mpiMotionEventNotifyGet


mpiMotionEventReset

Declaration
long mpiMotionEventReset(MPIMotion    motion,
                         MPIEventMask eventMask)
Required Header stdmpi.h
Description

MotionEventReset resets the event(s) that are specified in eventMask and generated by motion.
Your application must call MotionEventReset only after one or more latchable events have occurred.

Return Values
MPIMessageOK if MotionEventReset successfully resets the event(s) that are specified in eventMask and generated by motion
See Also


mpiMotionFlashConfigGet

Declaration
long mpiMotionFlashConfigGet(MPIMotion       motion,
                             void            *flash,
                             MPIMotionConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

MotionFlashConfigGet gets the flash configuration for a Motion object (motion) and puts (writes) it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Motion’s flash configuration information in external is in addition to the Motion’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL). The implementation-specific flash argument is used to access flash memory.

XMP Only

external either points to a structure of type MEIMotionConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if MotionFlashConfigGet successfully gets the Motion’s flash configuration and writes it into the structure(s).
See Also | mpiMotionFlashConfigSet


mpiMotionFlashConfigSet

Declaration
long mpiMotionFlashConfigSet(MPIMotion       motion,
                             void            *flash,
                             MPIMotionConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

MotionFlashConfigSet sets (writes) the flash configuration of a Motion object (motion) using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Motion’s flash configuration information in external is in addition to the Motion’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL). The implementation-specific flash argument is used to access flash memory.
XMP Only

external either points to a structure of type MEIMotionConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.

Return Values
MPIMessageOK if MotionFlashConfigSet successfully sets (writes) the Motion’s flash configuration using data from the structure(s)
See Also | MEIMotionConfig | MEIFlash | mpiMotionFlashConfigGet


mpiMotionFrameBufferStatus

meiMotionFrameBufferStatus

Declaration

        long meiMotionFrameBufferStatus(MPIMotion                   motion,
                                        MEIMotionFrameBufferStatus  *status)
Required Header stdmpi.h
Description

MotionFrameBufferStatus gets a Motion object (motion) frame buffer status and writes it to the structure pointed to by status.

motion | a handle to the Motion object
*status | a pointer to the motion frame buffer status structure returned by the method
Return Values
MPIMessageOK if MotionFrameBufferStatus successfully gets the frame buffer status
See Also | MEIMotionFrameBufferStatus


mpiMotionMemory

Declaration
long mpiMotionMemory(MPIMotion  motion,
                     void       **memory)
Required Header stdmpi.h
Description

MotionMemory sets (writes) the address [that is used to access a Motion’s (motion) memory] to the contents of memory. This address (or an address calculated from it) is passed as the src argument to mpiMotionMemoryGet(...), and also as the dst argument to mpiMotionMemorySet(...).

Return Values
MPIMessageOK if MotionMemory successfully writes the address (used to access a Motion’s memory) to the contents of memory
See Also | mpiMotionMemoryGet | mpiMotionMemorySet


mpiMotionMemoryGet

Declaration
long mpiMotionMemoryGet(MPIMotion motion,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description

MotionMemoryGet copies count bytes of a Motion’s (motion) memory (starting at address src) to application memory (starting at address dst).

Return Values
MPIMessageOK if MotionMemoryGet successfully copies count bytes of a Motion’s memory to application memory
See Also | mpiMotionMemorySet | mpiMotionMemory


mpiMotionMemorySet

Declaration
long mpiMotionMemorySet(MPIMotion motion,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description

MotionMemorySet copies count bytes of application memory (starting at address src) to a Motion’s (motion) memory (starting at address dst).

Return Values
MPIMessageOK if MotionMemorySet successfully copies count bytes of application memory to a Motion’s memory
See Also | mpiMotionMemoryGet | mpiMotionMemory


mpiMotionModify

Declaration
long mpiMotionModify(MPIMotion       motion,
                     MPIMotionType   type,
                     MPIMotionParams *params)
Required Header stdmpi.h
Description

MotionModify modifies the parameters of a Motion object (motion) if motion is in progress (MPIStateMOVING). The types of motion whose parameters can be modified while moving are MPIMotionTypeTRAPEZOIDAL, MPIMotionTypeS_CURVE, MPIMotionTypeVELOCITY, MPIMotionTypePT and MPIMotionTypePVT.

Use the MPIMotionAttrAUTO_START attribute to automatically start a motion profile if the MotionModify call is made too late (i.e., after the previous move has finished).

Return Values
MPIMessageOK | if MotionModify successfully modifies the parameters of a Motion object
MPIMotionMessageIDLE | if no Motion was in progress when MotionModify was called. In order for MotionModify to work, there must be a Motion in progress.
MPIMotionMessageAUTO_START | if MotionModify was called when no motion was in progress and the Auto-Start attribute was specified. In this case, the MotionModify is automatically converted into a MotionStart.
MPIMotionMessagePROFILE_ERROR | if the controller cannot generate the motion profile (based on the specified motion parameters and attributes).
For more Returns, click here |
See Also


mpiMotionNumber

Declaration
long mpiMotionNumber(MPIMotion  motion,
                     long       *number)
Required Header stdmpi.h
Description

MotionNumber writes the index of a Motion object (motion, on the motion controller that the Motion object is associated with) to the contents of number.
Return Values
MPIMessageOK if MotionNumber successfully writes the index of a Motion object to the contents of number
See Also


mpiMotionParamsGet

Declaration
long mpiMotionParamsGet(MPIMotion       motion,
                        MPIMotionParams *params)
Required Header stdmpi.h
Description

MotionParamsGet reads the parameters of a Motion object (motion) and writes it to the structure pointed to by params. These motion parameters will be used if mpiMotionStart(…) is called with Null motion params.

motion | a handle to the Motion object
*params | a pointer to the motion parameters structure returned by the method

Return Values
MPIMessageOK | if MotionParamsGet successfully returns the parameters associated with a Motion object
motion parameters | that are associated with a Motion object (motion). To set these motion parameters, call either mpiMotionParamsSet(...) or mpiMotionStart(...)

See Also | mpiMotionParamsSet | mpiMotionStart | meiMotionParamsValidate


mpiMotionParamsSet

Declaration
long mpiMotionParamsSet(MPIMotion       motion,
                        MPIMotionParams *params)
Required Header stdmpi.h
Description

.MotionParamsSet sets the parameters of a Motion object (motion). These motion parameters will be used if mpiMotionStart(...) is called with a Null motion parameter.

If Motion (motion) is active, MotionParamsSet will set motion parameters “on-the-fly,” i.e., at the first opportunity.
Return Values
MPIMessageOK if MotionParamsSet successfully sets the parameters of a Motion object
See Also | mpiMotionStart | mpiMotionParamsGet


meiMotionParamsValidate

Declaration
long meiMotionParamsValidate(MPIMotion       motion,
                             MPIMotionType   type,
                             MPIMotionParams *params,
                             MEIXmpAction    action,
                             long            *points)
Required Header stdmei.h
Description

MotionParamsValidate validates the type-specific motion parameters pointed to by params, using the coordinate system of motion.

If "*point" is | Then
not Null | the number of points specified by params is written to the location (pointed to by points)
Return Values
MPIMessageOK if MotionParamsValidate successfully validates the type-specific motion parameters using the coordinate system of motion
See Also


mpiMotionPositionGet

Declaration
long mpiMotionPositionGet(MPIMotion  motion,
                          double     *actual,
                          double     *command)
Required Header stdmpi.h
Description

MotionPositionGet gets the actual and command position values for all axes associated with a Motion (motion). The actual and command arguments each point to an array with a size equal to the number of axes associated with motion.

Return Values
MPIMessageOK if MotionPositionGet successfully gets the actual and command position values for all axes associated with a Motion object
See Also | mpiMotionPositionSet


mpiMotionPositionSet

Declaration
long mpiMotionPositionSet(MPIMotion motion,
                          double    *actual,
                          double    *command)
Required Header stdmpi.h
Description

MotionPositionSet sets the actual and command position values for all axes associated with a Motion (motion). The actual and command arguments each point to an array with a size equal to the number of axes associated with motion.

Return Values
MPIMessageOK if MotionPositionSet successfully sets the actual and command position values for all axes associated with a Motion object
See Also | mpiMotionPositionGet


mpiMotionStart

Declaration
long mpiMotionStart(MPIMotion       motion,
                    MPIMotionType   type,
                    MPIMotionParams *params)
Required Header stdmpi.h
Description

MotionStart changes a Motion object (motion) from the idle state (MPIStateIDLE) to the moving state (MPIStateMOVING), by initiating a motion of the given type using the specified parameters (params).If params is Null, then the motion parameters that were set by the most recent call to mpiMotionParamsSet(...) will be used to define the motion.

The coordinate system is defined by the ordered list of Axis object(s) that have been associated with the Motion object (motion). There must be at least one Axis in the coordinate system.

Return Values
MPIMessageOK | MotionStart successfully changes a Motion object from the idle state to the moving state
MPIMotionMessageMOVING | if MotionStart was called when a Motion is in progress
For more Returns, click here |
See Also | mpiMotionParamsSet | MPIState | See diagram on how mpiMotionStart works


mpiMotionStatus

Declaration
long mpiMotionStatus(MPIMotion  motion,
                     MPIStatus  *status,
                     void       *external)
Required Header stdmpi.h
Description

MotionStatus gets a Motion’s (motion) status and writes it to the structure pointed to by status, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Motion’s status information in external is in addition to the Motion’s status information in status, i.e., the status information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIMotionStatus{} or is NULL.

Return Values
MPIMessageOK if MotionStatus successfully writes the Motion’s status to the structure(s)
See Also


mpiMotionTrajectory

Declaration
long mpiMotionTrajectory(MPIMotion     motion,
                         MPITrajectory *trajectory)
Required Header stdmpi.h
Description

MotionTrajectory gets the trajectories for all axes associated with a Motion object (motion). The trajectory argument points to an array of MPITrajectory structures, with a size equal to the number of axes associated with the Motion object (motion).

Return Values
MPIMessageOK if MotionTrajectory successfully gets the trajectories for all axes associated with a Motion object
See Also


mpiMotionTYPE

Declaration

#define	 mpiMotionTYPE(type) 	((type) & MPIMotionTypeMASK)
Required Header stdmpi.h
Description

MotionType masks off all other bits in type, leaving the motion type.

See Also | MPIMotionType


mpiMotionValidate

Declaration
long mpiMotionValidate(MPIMotion motion)
Required Header stdmpi.h
Description

MotionValidate validates the Motion object (motion) and its handle. Always call mpiMotionValidate after creating a new Motion object.
Return Values
MPIMessageOK if Motion is a handle to a valid object.
See Also | mpiMotionCreate | mpiMotionDelete


Motor Objects

Introduction

A Motor object manages a single motor on a controller. It represents the physical connections between the motor, drive, and associated I/O. The Motor object contains encoder data, limit switch, home sensor, amp fault and amp enable states, DAC outputs, and other status information.

For simple systems, there is a one-to-one relationship between the Axis, Filter and Motor objects.

For information about using absolute encoders with the MPI click here.

Methods
Create, Delete, Validate Methods
 | mpiMotorCreate | Create Motor object
 | mpiMotorDelete | Delete Motor object
 | mpiMotorValidate | Validate Motor object

Configuration and Information Methods
 | mpiMotorAmpEnableGet | Get state of amp enable output
 | mpiMotorAmpEnableSet | Set state of amp enable output
 | mpiMotorAxisMapGet | Get object map of axes
 | meiMotorCommutationModeGet | Gets the commutation mode of a motor.
 | meiMotorCommutationModeSet | Sets the commutation mode of a motor.
 | mpiMotorConfigGet | Get motor configuration
 | mpiMotorConfigSet | Set motor configuration
 | meiMotorConfigStepper | Configures a motor for stepper mode.
 | meiMotorDacConfigGet | Get a Motor's (motor) Dac configuration
 | meiMotorDacConfigSet | Set a Motor's (motor) Dac configuration
 | mpiMotorFeedbackGet | Get feedback position
 | mpiMotorFlashConfigGet | Get flash config of motor
 | mpiMotorFlashConfigSet | Set flash config of motor
 | mpiMotorIoGet | Get dedicated I/O bits
 | mpiMotorIoSet | Set dedicated I/O bits
 | mpiMotorStatus / meiMotorStatus | Get motor status
 | mpiMotorType | Get Motor type

Event Methods
 | mpiMotorEventConfigGet | Get motor’s event configuration
 | mpiMotorEventConfigSet | Set motor’s event configuration
 | mpiMotorEventNotifyGet | Get motor’s event mask for host notification.
 | mpiMotorEventNotifySet | Set motor’s event mask for host notification.
 | mpiMotorEventReset | Reset events specified in event mask
 | mpiMotorEventWait | Set the contents of the structure pointed to by status.

Memory Methods
 | mpiMotorMemory | Get address of motor memory
 | mpiMotorMemoryGet | Copy motor memory to application memory
 | mpiMotorMemorySet | Copy application memory to motor memory

Action Methods
 | meiMotorEncoderInit | Initializes an absolute encoder.
 | meiMotorEncoderReset | Resets an absolute encoder.

Relational Methods
 | mpiMotorControl | Get handle to associated Control object
 | mpiMotorFilterMapGet | Get object map of associated Filters
 | mpiMotorFilterMapSet | Set the Filters using object map
 | mpiMotorNumber | Get index number of motor (in Control list)
Other Methods
 | meiMotorCompareListGet |
 | mpiMotorDedicatedInAddrGet | Get the address of the Dedicated IO for the Motor
 | meiMotorDedicatedIoAddrDecode |
 | meiMotorDedicatedOutAddrGet |
 | meiMotorEncoderRatio | Get encoder ratio from the XMP.
 | meiMotorRelatedStepMotorGet |

Data Types
MPIMotorBrake
MPIMotorBrakeMode
MPIMotorConfig / MEIMotorConfig
MEIMotorDacConfig
MEIMotorDacChannelConfig
MEIMotorDacChannelStatus
MEIMotorDacStatus
MPIMotorEncoderFault
MPIMotorEncoderFaultMask
MPIMotorEventConfig / MEIMotorEventConfig
MPIMotorEventTrigger
MEIMotorInput
MPIMotorIo
MPIMotorMessage / MEIMotorMessage
MEIMotorOutput
MEIMotorResourceNumber
MEIMotorStatus
MEIMotorStepper
MEIMotorTransceiver
MEIMotorTransceiverConfig
MEIMotorTransceiverExtendedId
MEIMotorTransceiverExtendedMask
MEIMotorTransceiverId
MEIMotorTransceiverMask
MPIMotorType
MEIMotorTypeInfo
Macros
mpiMotorEncoderFaultMaskBIT


Working with Absolute Encoders

Currently, only absolute motor encoders of Yaskawa SGDM Sigma Series II Servopacks are supported by the MPI. Custom firmware is needed in order to use these absolute encoders. Contact MEI for more information.

The encoders are automatically interrogated at power-up or after a controller reset. Axis Origin and Command Positions are set to correctly reflect the absolute position of the motor with no position error initially. The absolute position is the position within a single revolution.

The encoder interrogation is controlled by a SEN signal (to the drive) which must be connected to a configured XMP Transceiver or User Out signal. There are no restrictions as to which XMP signal is used except that current drive limitations may limit the number of drives connected to the same XMP signal.

The MEIMotorEncoder{} structure has been added to the MEIMotorConfig{} object:

typedef struct MEIMotorEncoder {
    MEIXmpEncoderType     type;
    long                  countsPerRev;
} MEIMotorEncoder;

typedef struct MEIMotorConfig {
    MEIMotorEncoder    Encoder[MEIXmpMotorEncoders];
    MEIXmpIO           StatusOutput[MEIXmpMotorStatusOutputs];

    MEIMotorTransceiver     Transceiver[MEIXmpMotorTransceivers];
    long                    UserOutInvert;     /* Opto Polarity */
    MEIMotorStepper         Stepper;
    long                    EncoderTermination;

    /* Commutation is read-only from field Theta to end*/
    MEIXmpCommutationBlock     Commutation;

    MEIXmpLimitData     Limit[MEIXmpLimitLAST];

    MEIMotorFilterInput     FilterInput[MEIXmpMotorFilterInputs];
} MEIMotorConfig;

Return to Motor Objects page


Special Note: Using mpiMotorConfigSet with Absolute Encoders

All absolute encoder configuration through the MPI is made using mpiMotorConfigSet() calls. The below sample code demonstrates the correct way to configure the XMP for Yaskawa absolute encoders.

When using a motor's User Output:

returnValue =
    mpiMotorFlashConfigGet(motor,
                   NULL,
                   &motorConfig,
                   &motorConfigMEI);

    motorConfig.encoderPhase = TRUE; /* Reverse */

    /* Config User Output for SEN line */
    motorConfigMEI.UserOutInvert = TRUE;

    motorConfigMEI.Encoder[0].type = MEIXmpEncoderTypeABS_0; /* Yaskawa encoder */
    motorConfigMEI.Encoder[0].countsPerRev = 65536;		 /* 65536 for 16-bit
                            encoders,131072 for 17-bit */

    returnValue =
        mpiMotorFlashConfigSet(motor,
                       NULL,
                       &motorConfig,
                       &motorConfigMEI);
    msgCHECK(returnValue);

    returnValue =
        mpiMotorConfigSet(motor,
                  &motorConfig,
                  &motorConfigMEI);
    msgCHECK(returnValue);

When using a motor's Transceiver Output:

returnValue =
        mpiMotorFlashConfigGet(motor,
                       NULL,
                       &motorConfig,
                       &motorConfigMEI);

    motorConfig.encoderPhase = TRUE; /* Reverse */

    /* Config transceiver for SEN line */
    motorConfigMEI.Transceiver[0].Config = MEIMotorTransceiverConfigOUTPUT;
    motorConfigMEI.Transceiver[0].Invert = TRUE;

    motorConfigMEI.Encoder[0].type = MEIXmpEncoderTypeABS_0; /* Yaskawa encoder */
    motorConfigMEI.Encoder[0].countsPerRev = 65536;		 /* 65536 for 16-bit
                            encoders,  131072 for 17-bit */
returnValue =
        mpiMotorFlashConfigSet(motor,
                       NULL,
                       &motorConfig,
                       &motorConfigMEI);
    msgCHECK(returnValue);

    returnValue =
        mpiMotorConfigSet(motor,
                      &motorConfig,
                      &motorConfigMEI);

In the above sample code, the steps for configuration are:
  1. Choose a transceiver, or User Opto, to be used for the encoders SEN line. The only restriction is that this transceiver must be on the same controller as the absolute encoder (not necessarily the same Motion Block).
  2. Get the current motor configuration from flash memory.
  3. Configure the encoder phase for the absolute encoder to Reverse.
  4. For a User Opto, configure UserOutInvert to be TRUE. When using a transceiver, configure for Output, and Inverted.
  5. Configure the encoder type and counts per revolution.
  6. Save the current motor configuration from flash memory.
Once configured, the initialization of all axes associated with the motors having absolute encoders is automatic at power up or reset. The SEN line is toggled and the origin and command position are calculated and set from the absolute data sent by the drive.
IMPORTANT NOTE:
The drive must be powered but should not be enabled.

Determining the countPerRev Parameter

The magnitude countsPerRev parameter is detemined by the number of encoder counts (after quadrature) for one revolution of the motor. The sign of the countsPerRev is derimined by the direction for positive rotation for the motor. For Yaskawa drives this is determined by the drive parameter P000.0. P000.0 = 0 (“Standard Rotation”, factory default setting) will cause the motor to move in a counter-clockwise (CCW) direction for positive increases in encoder counts. For Standard Rotation (Pn000.0 = 0) the countPerRev parameter should be positive.

P000.0 = 1 (“Reverse Rotation”) will cause the motor to move in a clockwise (CCW) direction for positive increases in encoder counts. For Reverse Rotation the countsPerRev parameter should be negative.

For example the following code would be used for a drive congfigured for Standard Rotation where the number of counts for one revolution of the motor shaft is 8,192:

motorConfigMEI.Encoder[0].countsPerRev = 8192;

If the same drive were configured for Reverse Rotation the code would be:

motorConfigMEI.Encoder[0].countsPerRev = -8192;

For both Standard and Reverse Rotation the encoderPhase parameter should be TRUE (encoder reversed).

Return to mpiMotorConfigSet


Special Note: Using mpiMotorConfigSet with Absolute Encoders

Special Note: MPIMotorEventConfig and Motor Limit Configuration

Two fields, directionFlag and duration, are built into the MPIMotorEventConfig{} structure. From motor.h:

typedef enum {
    MPIMotorEncoderFaultMaskNONE     = 0x0,

    MPIMotorEncoderFaultMaskBW_DET   = mpiMotorEncoderFaultMaskBIT(MPIMotorEncoderFaultBW_DET),
    MPIMotorEncoderFaultMaskILL_DET  = mpiMotorEncoderFaultMaskBIT(MPIMotorEncoderFaultILL_DET),
    MPIMotorEncoderFaultMaskABS_ERR  = mpiMotorEncoderFaultMaskBIT(MPIMotorEncoderFaultABS_ERR),

    MPIMotorEncoderFaultMaskALL      = (mpiMotorEncoderFaultMaskBIT(MPIMotorEncoderFaultLAST) - 1)
} MPIMotorEncoderFaultMask;

typedef union {
    long	polarity;	/* 0 => active low, else active high */
    long	position;	/* MPIEventTypeLIMIT_SW_[POS|NEG] */
    float	error;		/* MPIEventTypeLIMIT_ERROR */
    long	mask;		/* MPIEventTypeENCODER_FAULT */
} MPIMotorEventTrigger;

typedef struct MPIMotorEventConfig {
    MPIAction               action;
    MPIMotorEventTrigger    trigger;
    long                    direction;
    float                   duration;     /* seconds */
} MPIMotorEventConfig;

The directionFlag field is used to configure MPIEventTypeLIMIT_HW_NEG, MPIEventTypeLIMIT_HW_POS, MPIEventTypeLIMIT_SW_NEG, and MPIEventTypeLIMIT_SW_POS. A value of TRUE for this field will force the command direction for motion to be used by the Xmp controller to qualify these limit events. A value of FALSE for this field will cause the limit event to depend on the state of the limit. If the limit has been exceeded (actual position > software positive limit, actual position < software negative limit, positive or negative hardware overtravel is TRUE) the limit event will be based direction of commanded motion, in exactly the same way as for directionFlag = TRUE. If the limit has not been exceeded the limit event and status will be based solely on the limit input (hardware limits) or actual position (software limits), ignoring the direction of commanded motion. The default status of durationFlag is FALSE (ignore direction). The directionFlag is ignored (returned FALSE from “get” methods) for case MPIEventTypeAMP_FAULT, MPIEventTypeHOME, and MPIEventTypeLIMIT_ERROR.

The duration field may used in the configuration of all MPI Motor Events. A positive value for this field will require the limit condition to exist for duration seconds before an event will occur. This field is useful in overriding noisy limit inputs. For example, an overtravel limit with infrequent short (< 1msec) noise spikes on the limit input will ignore the noise of the limit is configured with a duration of 0.05. A spike whose duration was at least 0.05 seconds (50 milliseconds) would be required before an overtravel event would occur. The default value for duration is 0.0.

Return to MPIMotorEventConfig


MPIMotorBrake

MPIMotorBrake

typedef struct MPIMotorBrake {
    MPIMotorBrakeMode   mode;
    float               enableDelay;
    float               disableDelay;

} MPIMotorBrake;
Description

MotorBrake allows the ability to enable and disable a brake when the motor's amp enable output is enabled or disabled.

The reason for this is easiest to imagine on a vertical axis of motion: If you release the brake before enabling servo control on a vertical axis, the axis will not be controlled and will fall under the influence of gravity. Likewise, when setting a brake on a vertical axis, you want to set the brake before turning off the amplifier so that no motion occurs when disabling the servo control.

NOTE: the only output capable of being used for a brake is the USER I/O 0 output of the motor.

mode | Specifies whether a brake is to be tied to the motor's amp enable output.
enableDelay | The amount of time the brake is enabled before servo control is disabled. NOTE: the brake is enabled immediately, the delay is for servo control.
disableDelay | The amount of time servo control is turned on before the brake is disabled.
See Also


MPIMotorBrakeMode

MPIMotorBrakeMode

typedef enum{
     MPIMotorBrakeModeINVALID = -1,
     MPIMotorBrakeModeNONE,
     MPIMotorBrakeModeDELAY,

} MPIMotorBrakeMode;
Description

MotorBrakeMode specifies whether a brake enable is tied to the amp enable output.

MPIMotorBrakeModeNONE | No brake enable output is tied to the amp enable output.
MPIMotorBrakeModeDELAY | Ties a brake enable output to the amp enable output.
See Also


MPIMotorConfig and MEIMotorConfig

MPIMotorConfig / MEIMotorConfig

MPIMotorConfig

typedef struct MPIMotorConfig {
    MPIMotorType    type;

    /* Event configuration, ordered by MPIEventType */
    MPIMotorEventConfig		event[MPIEventTypeMOTOR_LAST];

    long    ampEnablePolarity;	/* FALSE => active lo, else active hi */
    long    encoderPhase;	/* 0 => normal, else reversed */
    long    captureOnChange;	/* 0 => normal, else enabled */

    float            abortDelay;
    float            enableDelay;
    MPIMotorBrake    brake;

    MPIObjectMap     filterMap;

    MPIMotorIo	      io;
} MPIMotorConfig;

Description
 | event | Structure to configure various Motor Events. See MPIMotorEventConfig description.
 | ampEnablePolarity | Configures Amplifier Enable Output polarity. For active low signal = FALSE, for Active High = TRUE
 | encoderPhase | Configures encoder phasing. Normal (A rising, B rising, A falling, etc.) = 0, Reversed = non-zero.
 | captureOnChange | Configures Captures objects for this motor to Capture on Rising and Falling transitions.
 | abortDelay | Sets time value, in seconds, to delay Abort action after Event has occured.
 | enableDelay | Sets time value, in seconds, to delay Enabling of the amplifier after commanded.
 | brake | Settings for tying a brake enable output to the amp enable output.
 | filterMap | Get/Set a map of Filter Objects to which the Motor is mapped. Default mapping is Filter 0 to Motor 0, Fitler 1 to Motor 1, etc. See also MPIObjectMap description in Object section.
 | io | Structure to read the Motor input and set Motor output values.. See MPIMotorIo description.

MEIMotorConfig

typedef struct MEIMotorConfig {
    MEIMotorEncoder      Encoder[MEIXmpMotorEncoders];
    MEIXmpIO             StatusOutput[MEIXmpMotorStatusOutputs];
    MEIMotorTransceiver  Transceiver[MEIXmpMotorTransceivers];
    MEIMotorTransceiver  TransceiverExtended[MEIXmpMotorTransceiversExtended];
    long                 UserOutInvert;    /* Opto Polarity */
    MEIMotorStepper      Stepper;
    long                 EncoderTermination;
    long                 SIM4;
    MEIMotorDacConfig    Dac;
    long                 pulseEnable;     /* 0 => normal, else pulse output */
    long                 pulseWidth;      /* 0.1 to 25.5 microseconds */

    /* Commutation is read-only from field Theta to end*/
    MEIXmpCommutationBlock	Commutation;

    MEIXmpLimitData	Limit[MEIXmpLimitLAST];

    MEIXmpMotorTorqueLimitConfig TorqueLimitConfig;

    long AmpDisableWithLSR;	/* TRUE => XMP disables amp when LSR is active */

    MEIMotorFilterInput	FilterInput[MEIXmpMotorFilterInputs];
} MEIMotorConfig;

Description
 | Encoder | Structure to configure Motor Encoder type and parameters
 | Transceiver | Structure to configure Motor Transceivers. See MEIMotorTransceiver description.
 | TransceiverExtended | Structure to configure Motor Extended Transceivers. See MEIMotorTransceiver description.
 | UserOutInvert | Inverts the User Opto Polarity when wired as an Output.
 | Stepper | Structure to configure Motor Stepper parameters. See MEIMotorStepper description.
 | EncoderTermination | Enables encoder termination when set to 1. Enables 100 ohm resistor between complementary encoder channels. Set to 0 (zero) to disable.
 | SIM4 | Enables use of SIM4 scale interpolation module when set to 1. Set to 0 (zero) to disable.
 | Dac | Structure that includes Command and Auxiliary DAC configuration for each motor. See MEIMotorDacConfig description.
 | pulseEnable | Enables the Divide-by-N output pulse. See MEICompareConfig description.
 | pulseWidth | Sets width of Step pulse. Valid values range from a minimum width of 0.1usec to a maximum width of 25.5usec.

See Also | mpiMotorConfigGet | mpiMotorConfigSet


MEIMotorDacConfig

MEIMotorDacConfig

typedef struct MEIMotorDacConfig {
    MEIXmpDACPhase		Phase;
    MEIMotorDacChannelConfig	Cmd;
    MEIMotorDacChannelConfig	Aux;
} MEIMotorDacConfig;
Description

MotorDacConfig is a structure that includes Command and Auxiliary DAC configuration for each motor.

See Also


MEIMotorDacChannelConfig

MEIMotorDacChannelConfig

typedef struct MEIMotorDacChannelConfig {
    float		Offset;	/* volts */
    float		Scale;
    MEIXmpDACInputType	InputType;
    MEIXmpGenericValue	*Input;
} MEIMotorDacChannelConfig;
Description

MotorDacChannelConfig is a structure used to configure the DAC settings.

Offset | Set DAC Offset value. Valid values range from -10 Volts to +10 Volts.
See Also


MEIMotorDacChannelStatus

MEIMotorDacChannelStatus

typedef struct MEIMotorDacChannelStatus {
    float	level;	/* volts */
} MEIMotorDacChannelStatus;
Description

MotorDacChannelStatus is a structure that returns the DAC output value.

level | level reflects the DAC output value. Valid values range from -10 Volts to +10 Volts.
See Also


MEIMotorDacStatus

MEIMotorDacStatus

typedef struct MEIMotorDacStatus {
    MEIMotorDacChannelStatus	cmd;
    MEIMotorDacChannelStatus	aux;
} MEIMotorDacStatus;
Description

MotorDacStatus is a structure that returns the Status for both Command and Auxiliary DACs. It is used to read the cmd and aux DAC level (in volts) from the controller.
See Also


MPIMotorEncoderFault

MPIMotorEncoderFault

typedef enum {
    MPIMotorEncoderFaultINVALID,
    MPIMotorEncoderFaultBW_DET,
    MPIMotorEncoderFaultILL_DET,
    MPIMotorEncoderFaultABS_ERR,

} MPIMotorEncoderFault;
Description

MotorEncoderFault is an enumeration used to get/set Encoder Fault.

MPIMotorEncoderFaultBW_DET | Encoder Broken Wire detection enabled. Error returned if complementary signals are in the same state. (e.g. A+ and A- return 5V.)
MPIMotorEncoderFaultILL_DET | Encoder Illegal State detection enabled.
MPIMotorEncoderFaultABS_ERR | Absolute encoder error detection enabled.
See Also


MPIMotorEncoderFaultMask

MPIMotorEncoderFaultMask

typedef enum {
     MPIMotorEncoderFaultMaskNONE,
     MPIMotorEncoderFaultMaskBW_DET,
     MPIMotorEncoderFaultMaskILL_DET,
     MPIMotorEncoderFaultMaskABS_ERR,
     MPIMotorEncoderFaultMaskALL
} MPIMotorEncoderFaultMask;
Description

MotorEncoderFaultMask is an enumeration to mask bits from MPIMotorEncoderFault register.

MPIMotorEncoderFaultMaskBW_DET | Mask for Broken Wire detection
MPIMotorEncoderFaultMaskILL_DET | Mask for Illegal State detection
MPIMotorEncoderFaultMaskABS_ERR | Mask for Absolute Encoder Error
See Also


MPIMotorEventConfig and MEIMotorEventConfig

MPIMotorEventConfig / MEIMotorEventConfig

MPIMotorEventConfig

typedef struct MPIMotorEventConfig {
    MPIAction		  action;
    MPIMotorEventTrigger  trigger;
    long		  direction;
    float		  duration;	/* seconds */
} MPIMotorEventConfig;
Description

MotorEventConfig is a structure used to configure Motor Events.

direction | for Hardware and Software limits, enabling "direction" requires the direction of motion to be in direction of Limit.
duration | time that Limit (e.g. Home, Pos. and Neg. Limits, User Limit) must be asserted before Event is generated. Value in seconds.

MEIMotorEventConfig

typedef MEIXmpLimitData	MEIMotorEventConfig;
typedef struct {
    MEIXmpLimitCondition    Condition[MEIXmpLimitConditions];
    MEIXmpStatus            Status;
    MEIXmpLogic             Logic;
    MEIXmpLimitOutput       Output;
    long                    Count;
    long                    State;
} MEIXmpLimitData;
Description
condition | is a structure that configures the conditioanl statements evaluated to generate a Limit Event. Each limit may have up to two conditions (MEIXmpLimitConditions = 2). This structure is described in further detail in App Note 215.
status | an enum that defines what actions the XMP will take when a user limit evaluates TRUE. Always set Status to at least MEIXmpStatusLIMIT to notify the motor object that a limit has occurred. Valid Status values are listed in the "Values of Status" table below.
logic | an enum that sets the logic applied between the two condition block outputs, Condition[0] and Condition[1]. Valid Logic values are listed in the "Values of Status" table below.
output | is a structure that allows specific action to be taken when the Limit Event is generated. In addition to generatign a Motion Action, a Limit can write to any other valid XMP Firmware register defined in the *OutputPtr with value described by AndMask and OrMask. This structure is described in further detail in App Note 215.
count | For internal use only. The MPI method, mpiMotorEventConfigSet(...) will not write these values.
state | For internal use only. The MPI method, mpiMotorEventConfigSet(...) will not write these values.

Value of Status | Action to be taken
MEIXmpStatusLIMIT | None
MEIXmpStatusLIMIT | MEIXmpStatusPAUSE | Axes attached to the motor will be Paused
MEIXmpStatusLIMIT | MEIXmpStatusSTOP | Axes attached to the motor will be Stopped
MEIXmpStatusLIMIT | MEIXmpStatusABORT | Axes attached to the motor will be Aborted
MEIXmpStatusLIMIT | MEIXmpStatusESTOP | Axes attached to the motor will be E-Stopped
MEIXmpStatusLIMIT | MEIXmpStatusESTOP_ABORT | Axes attached to the motor will be E-Stopped and Aborted

Value of Logic | Evaluates | Motor object notified that a limit has occurred if...
MEIXmpLogicNEVER | Nothing | No event is generated
MEIXmpLogicSINGLE | Condition[0] | Condition[0] = = TRUE
MEIXmpLogicOR | Condition[0], Condition[1] | (Condition[0] || Condition[1]) = = TRUE
MEIXmpLogicAND | Condition[0], Condition[1] | (Condition[0] && Condition[1]) = = TRUE
other MEIXmpLogic enums | For internal use only. |
See Also | Special Note: MPIMotorEventConfig and Motor Limit Configuration See App Note 215 for a more in-depth breakdown of this structure. mpiMotorEventConfigGet | mpiMotorEventConfigSet


MPIMotorEventTrigger

MPIMotorEventTrigger

typedef union {
    long	polarity;	/* 0 => active low, else active high */
    long	position;	/* MPIEventTypeLIMIT_SW_[POS|NEG] */
    float	error;		/* MPIEventTypeLIMIT_ERROR */
    long	mask;		/* MPIEventTypeENCODER_FAULT */
} MPIMotorEventTrigger;

Description
 | polarity | configures the polarity for Motor Event. Active Low = 0, Active High = non-zero.
 | position | configures position at which Positive and Negative Software limits generate Events.
See Also


MPIMotorIo

MPIMotorIo

typedef struct MPIMotorIo {
    unsigned long	input;
    unsigned long	output;
} MPIMotorIo;
Description

MotorIo is a structure used to read the Motor input and set Motor output values.

input | for XMP users, 'input' value reflects MEIMotorInput. See MEIMotorInput description.
output | for XMP users, 'output' value reflects MEIMotorOutput. See MEIMotorOutput description.

See Also | mpiMotorIoGet | mpiMotorIoSet


MEIMotorInput

MEIMotorInput

typedef enum {
    MEIMotorInputSIM4_INDEX,
    MEIMotorInputSIM4_ENCB,
    MEIMotorInputSIM4_ENCA,
    MEIMotorInputXCVR_A,
    MEIMotorInputXCVR_B,
    MEIMotorInputXCVR_C,

    MEIMotorInputBROKEN_WIRE,
    MEIMotorInputILLEGAL_STATE,

    MEIMotorInputOVERTRAVEL_POS,
    MEIMotorInputOVERTRAVEL_NEG,
    MEIMotorInputHOME,
    MEIMotorInputAMP_FAULT,
    MEIMotorInputINDEX,

    MEIMotorInputUSER,
    MEIMotorInputCAPTURE,
} MEIMotorInput;
Description

MotorInput is an enumeration of the Motor Input register.
See Also


MPIMotorMessage and MEIMotorMessage

MPIMotorMessage / MEIMotorMessage

MPIMotorMessage

typedef enum {

    MPIMotorMessageMOTOR_INVALID,

} MPIMotorMessage;
Description

MotorMessage is an enumeration of Motor error messages that can be returned by the MPI library.

MEIMotorMessage

typedef enum {
    MEIMotorMessageABS_ENCODER_FAULT,
    MEIMotorMessageABS_ENCODER_TIMEOUT,
    MEIMotorMessageMOTOR_NOT_ENABLED,

} MEIMotorMessage;
Description

MotorMessage is an enumeration of Motor error messages that can be returned by the MPI library.
See Also


MEIMotorOutput

MEIMotorOutput

typedef enum {
    MEIMotorOutputXCVR_A,
    MEIMotorOutputXCVR_B,
    MEIMotorOutputXCVR_C,
    MEIMotorOutputBRAKE_ENABLE,
    MEIMotorOutputUSER,
    MEIMotorOutputCOMPARE,
} MEIMotorOutput;
Description

MotorOuput lists the Motor Output enumeration values.
See Also


MEIMotorResourceNumber

MEIMotorResourceNumber

typedef enum {
    MEIMotorResourceNumberINVALID,
    MEIMotorResourceNumber0,
    MEIMotorResourceNumber1,
    MEIMotorResourceNumber2,
    MEIMotorResourceNumber3,
    MEIMotorResourceNumber4,
    MEIMotorResourceNumber5,
    MEIMotorResourceNumber6,
    MEIMotorResourceNumber7,
    MEIMotorResourceNumber8,
    MEIMotorResourceNumber9,
    MEIMotorResourceNumber10,
    MEIMotorResourceNumber11,
    MEIMotorResourceNumber12,
    MEIMotorResourceNumber13,
    MEIMotorResourceNumber14,
    MEIMotorResourceNumber15,
    MEIMotorResourceNumber16,
    MEIMotorResourceNumber17,
    MEIMotorResourceNumber18,
    MEIMotorResourceNumber19,
    MEIMotorResourceNumber20,
    MEIMotorResourceNumber21,
    MEIMotorResourceNumber22,
    MEIMotorResourceNumber23,
    MEIMotorResourceNumber24,
    MEIMotorResourceNumber25,
    MEIMotorResourceNumber26,
    MEIMotorResourceNumber27,
    MEIMotorResourceNumber28,
    MEIMotorResourceNumber29,
    MEIMotorResourceNumber30,
    MEIMotorResourceNumber31,

}MEIMotorResourceNumber;
Description

MotorResourceNumber is an enumeration value used only for XMP-Pulse controllers. All other XMP controllers should have the Step Resource Number set equal to the Motor number. XMP-Pulse users can set the Resource Number to allow sharing of a single motor block's resources between two stepper motors. e.g. Motors 0 and 16 could both be configured to use the output signals from Motor Block 0 by each having their Motor Resource Number set to 0.

See Also


MEIMotorStepper

MEIMotorStepper

typedef struct MEIMotorStepper {
    float	PulseWidth;	/* output pulse width  (sec) */
    long	Loopback;	/* TRUE = count step pulses in encoder reg. */
    MEIMotorResourceNumber	ResourceNumber;
} MEIMotorStepper;
Description

MotorStepper is a structure used to configure Stepper Motor parameters.

PulseWidth | sets width of Step pulse. Valid values range from a minimum width of 0.1 usec to maximum width of 25.5 usec.
LoopBack | enables Step Loopback feature. When enabled, step output pulses counted to generate Actual Position. When disabled, external feedback device is required to generate actual position.
See Also


MEIMotorStatus

MEIMotorStatus

typedef struct MEIMotorStatus {
    MEIMotorDacStatus	dac;
} MEIMotorStatus;
Description

MotorStatus is a structure that returns XMP specific Motor Status registers.
See Also


MEIMotorTransceiver

MEIMotorTransceiver

typedef struct MEIMotorTransceiver {
    long                         Invert;
                  /* TRUE = invert (not valid for INPUT) */
    MEIMotorTransceiverConfig    Config;
} MEIMotorTransceiver;
Description

MotorTransceiver is a structure used to configure Transceiver parameters.

Invert | Inverts polarity of Transceiver Output. Not valid when the Transeiver is configured as an Input.
Config | Enumeration to configure Transceiver usage. See MEIMotorTransceiverConfig description.
See Also


MEIMotorTransceiverConfig

MEIMotorTransceiverConfig

typedef enum {
    MEIMotorTransceiverConfigINVALID,
    MEIMotorTransceiverConfigINPUT,		  /* 0 */
    MEIMotorTransceiverConfigOUTPUT,		  /* 1 */
    MEIMotorTransceiverConfigSTEP,    		  /* 2 */
    MEIMotorTransceiverConfigDIR,     		  /* 3 */
    MEIMotorTransceiverConfigCW,      		  /* 4 */
    MEIMotorTransceiverConfigCCW,     		  /* 5 */
    MEIMotorTransceiverConfigQUAD_A, 		  /* 6 */
    MEIMotorTransceiverConfigQUAD_B, 		  /* 7 */
    MEIMotorTransceiverConfigCOMPARE,		  /* 8 */
    MEIMotorTransceiverConfigDIAG,		  /* 9 */
    MEIMotorTransceiverConfigNOT_AVAILABLE,

} MEIMotorTransceiverConfig;
Description

MotorTranceiverConfig is a structure used to configure various Motor Events.

MEIMotorTransceiverConfigINPUT | Transceiver configured as Input
MEIMotorTransceiverConfigOUTPUT | Transceiver configured as Output
MEIMotorTransceiverConfigSTEP | Transceiver configured as Step pulse output
MEIMotorTransceiverConfigDIR | Transceiver configured as Direction signal output
MEIMotorTransceiverConfigCW | Transceiver configured as Clockwise Step Output
MEIMotorTransceiverConfigCCW | Transceiver configured as Counterclockwise Step Output
MEIMotorTransceiverConfigQUAD_A | Transceiver configured as Quadrature A Output
MEIMotorTransceiverConfigQUAD_B | Transceiver configured as Quadrature B Output
MEIMotorTransceiverConfigCOMPARE | Transceiver configured for use as Compare Output
See Also


MEIMotorTransceiverExtendedId

MEIMotorTransceiverExtendedId

typedef enum {
    MEIMotorTransceiverExtendedIdINVALID,

    MEIMotorTransceiverExtendedIdD,
    MEIMotorTransceiverExtendedIdE,
    MEIMotorTransceiverExtendedIdF,

} MEIMotorTransceiverExtendedId;
Description

MotorTranceiverExtendedId is an enumeration of Extended Transceiver Identification. Not valid on all XMP controllers.
See Also


MEIMotorTransceiverExtendedMask

MEIMotorTransceiverExtendedMask

typedef enum {
    MEIMotorTransceiverExtendedMaskD,
    MEIMotorTransceiverExtendedMaskE,
    MEIMotorTransceiverExtendedMaskF,
} MEIMotorTransceiverExtendedMask;
Description

MotorTransceiverExtendedMask is an enumeration of Extended Transceiver I/O masks. Not valid on all XMP controllers.
See Also


MEIMotorTransceiverId

MEIMotorTransceiverId

typedef enum {
    MEIMotorTransceiverIdINVALID,

    MEIMotorTransceiverIdA,
    MEIMotorTransceiverIdB,
    MEIMotorTransceiverIdC,

} MEIMotorTransceiverId
Description

MotorTraceiverId is an enumeration of Transceiver Identification.
See Also


MEIMotorTransceiverMask

MEIMotorTransceiverMask

typedef enum {
    MEIMotorTransceiverMaskA,
    MEIMotorTransceiverMaskB,
    MEIMotorTransceiverMaskC,
} MEIMotorTransceiverMask;
Description

MotorTranceiverMask is an enumeration of Extended Transceiver I/O masks. Not valid on all XMP controllers.
See Also


MPIMotorType

MPIMotorType

typedef enum {
    MPIMotorTypeINVALID,

    MPIMotorTypeSERVO,
    MPIMotorTypeSTEPPER,
    MPIMotorTypeSERCOS_DRIVE,

} MPIMotorType;
Description

MotorType is an enumeration of valid Motor Types.

MPIMotorTypeSERVO | Motor configured as Servo
MPIMotorTypeSTEPPER | Motor configured as Stepper
MPIMotorTypeSERCOS_DRIVE | Motor configured as SERCOS drive
See Also


MEIMotorTypeInfo

MEIMotorTypeInfo

typedef union {
    struct {
        long	sercosNumber;
        long	nodeNumber;
    } sercos;
} MEIMotorTypeInfo;
Description

MotorTypeInfo is a union with one member (a sercos structure) that contains the sercosNumber and nodeNumber for that motor.
See Also


mpiMotorAmpEnableGet

Declaration
long mpiMotorAmpEnableGet(MPIMotor  motor,
                          long      *ampEnable)
Required Header stdmpi.h
Description

MotorAmpEnableGet gets the state of the amp enable output for a Motor (motor) and writes it in the location pointed to by ampEnable. Note that the actual state of amp enable output also depends upon the actual wiring and the polarity chosen in the instance of the MPIMotorConfig structure.

If "ampEnable" is | Then
FALSE (0) | the amp is disabled
TRUE (1) | the amp is enabled
Return Values
MPIMessageOK if MotorAmpEnableGet successfully writes the Motor’s amp enable output state to the location
See Also | MPIMotorConfig | mpiMotorAmpEnableSet


mpiMotorAmpEnableSet

Declaration
long mpiMotorAmpEnableSet(MPIMotor  motor,
                          long      ampEnable)
Required Header stdmpi.h
Description

MotorAmpEnableSet sets the state of the amp enable output for a Motor (motor) to ampEnable. Note that the actual state of amp enable output also depends upon the actual wiring and the polarity chosen in the instance of the MPIMotorConfig structure.

If "ampEnable" is | Then
FALSE (0) | the amp will be disabled
TRUE (1) | the amp will be enabled
Return Values
MPIMessageOK if MotorAmpEnableset successfully sets the Motor’s amp enable output state to ampEnable
See Also | MPIMotorConfig | mpiMotorAmpEnableGet


mpiMotorAxisMapGet

Declaration
long mpiMotorAxisMapGet(MPIMotor      motor,
                        MPIObjectMap  *map)
Required Header stdmpi.h
Description

MotorAxisMapGet gets the object map of the Axes associated with a Motor (motor) and writes it into the structure pointed to by map.
Return Values
MPIMessageOK if MotorAxisMapGet successfully writes the Motor’s object map of Axes to the structure
See Also


mpiMotorConfigGet

Declaration
long mpiMotorConfigGet(MPIMotor       motor,
                       MPIMotorConfig *config,
                       void           *external)
Required Header stdmpi.h
Description

MotorConfigGet gets a Motor’s (motor) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIMotorConfig{} or is NULL.

Return Values
MPIMessageOK if MotorConfigGet successfully writes the Motor’s configuration to the structure(s)
See Also | MEIMotorConfig | mpiMotorConfigSet


mpiMotorConfigSet

Declaration
long mpiMotorConfigSet(MPIMotor       motor,
                       MPIMotorConfig *config,
                       void           *external)
Required Header stdmpi.h
Description

MotorConfigSet sets a Motor’s (motor) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIMotorConfig{} or is NULL.
Return Values
MPIMessageOK if MotorConfigSet successfully sets the Motor’s configuration using data from the structure(s)
See Also | mpiMotorConfigGet Special Note: Using mpiMotorConfigSet with Absolute Encoders


meiMotorConfigStepper

Declaration
long meiMotorConfigStepper(MPIMotor       motor,
                           MEIMotorConfig *config,
                           long           stepperNumber)
Required Header stdmei.h
Description

MotorConfigStepper modifies the motor configuration structure pointed to by config, to use a step engine (stepperNumber) from another motor. By default, each motor uses its own step engine. Do NOT use more than one motor per step engine. Use the methods mpiMotorConfigGet/Set(…) to read/write the motor configuration from/to the controller.

motor | a handle to the Motion object
*config | a pointer to the motion frame buffer status structure returned by the method
stepperNumber | index to a step engine
Return Values
MPIMessageOK if MotorConfigStepper successfully modifies the motor configuration structure pointed to by config
See Also | mpiMotorConfigGet | mpiMotorConfigSet


meiMotorCommutationModeGet

Declaration
long meiMotorCommutationModeGet(MPIMotor       motor,
                                MEIXmpCommMode *mode)
Required Header stdmei.h
Description

MotorCommutationModeGet gets the commutation mode of a Motor (motor) and writes it to the location pointed to by mode.

Return Values
MPIMessageOK if MotorCommutationModeGet successfully gets the commutation mode of a Motor and writes it to the location
See Also | meiMotorCommutationModeSet


meiMotorCommutationModeSet

Declaration
long meiMotorCommutationModeSet(MPIMotor       motor,
                                MEIXmpCommMode mode)
Required Header stdmei.h
Description

MotorCommutationModeSet sets the commutation mode of a Motor (motor) to mode.

Return Values
MPIMessageOK if MotorCommutationModeSet successfully sets the commutation mode of a Motor to mode
See Also | meiMotorCommutationModeGet


mpiMotorControl

Declaration
const MPIControl mpiMotorControl(MPIMotor motor)
Required Header stdmpi.h
Description

MotorControl returns a handle to the Control object with which the motor is associated.

motor | a handle to the Motor object

Return Values
MPIControl | handle to a Control object
MPIHandleVOID | if motor is invalid

See Also | mpiMotorCreate | mpiControlCreate


meiMotorCompareListGet

Declaration
long meiMotorCompareListGet(MPIMotor motor,
                            long	  *compareCount,
                            long	  *compareList);
Required Header stdmei.h
Description

MotorCompareListGet sets compareCount to the number of compares that motor has. It sets compareList to the number of the compare object for each compare.

Return Values
MPIMessageOK if motor is a valid MPIMotor object.
See Also


mpiMotorCreate

Declaration
const MPIMotor mpiMotorCreate(MPIControl control,
                              long       number)
Required Header stdmpi.h
Description

MotorCreate creates a Motor object associated with the motor identified by number, and located on the motion controller (control). MotorCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Motor object
MPIHandleVOID | if the Motor object could not be created

See Also | mpiMotorDelete | mpiMotorValidate


meiMotorDacConfigGet

Declaration
long meiMotorDacConfigGet(MPIMotor          motor,
                          MEIMotorDacConfig *dacConfig,
                          MEIFlash          flash);
Required Header stdmei.h
Description

MotorDacConfigGet gets a Motor's (motor) Dac configuration and writes it to the structure pointed to by dacConfig. The dac configuration located in flash is retrieved if the flash structure is not NULL.

Return Values
MPIMessageOK if MotorDacConfigGet successfully writes the Motor's Dac configuration to the config structure
See Also | meiMotorDacConfigSet | MEIMotorDacConfig


meiMotorDacConfigSet

Declaration
long meiMotorDacConfigSet(MPIMotor          motor,
                          MEIMotorDacConfig *dacConfig,
                          MEIFlash          flash);
Required Header stdmei.h
Description

MotorDacConfigSet configures a Motor's (motor) Dac using data from the structure pointed to by dacConfig. The dac configuration located in flash is set if the flash structure is not NULL.

Return Values
MPIMessageOK if MotorDacConfigSet successfully writes the Motor's Dac configuration to the controller
See Also | meiMotorDacConfigGet | MEIMotorDacConfig


mpiMotorDedicatedInAddrGet

Declaration
long mpiMotorDedicatedInAddrGet(MPIMotor   motor,
                                long       motorNumber)
Required Header stdmpi.h
Description

MotorDedicatedInAddrGet gets the address of the Dedicated IO for the Motor that is specified by motorNumber.

Return Values
Address The address of where the Dedicated IO is located in XMP memory.
See Also


meiMotorDedicatedIoAddrDecode

Declaration
long meiMotorDedicatedIOAddrDecode(MPIMotor    motor,
                                   long        addr,
                                   long*       motorNumber);
Required Header stdmei.h
Description

MotorDedicatedIoAddrDecode takes an addr and decodes which motor's dedicated IO this addr points to, and then sets motorNumber to that motor's motorNumber.

Return Values
MPIMessageOK if motor is a valid handle and addr is a valid address (eg. it is located in the motor memory space on the controller).
See Also


meiMotorDedicatedOutAddrGet

Declaration
long meiMotorDedicatedOutAddrGet(MPIMotor   motor,
                                 long       motorNumber);
Required Header stdmei.h
Description

MotorDedicatedOutAddrGet gets the address of the Dedicated IO for the Motor that is specified by motorNumber.

Return Values
Address The address of where the Dedicated IO is located in XMP memory.
See Also


mpiMotorDelete

Declaration
long mpiMotorDelete(MPIMotor motor)
Required Header stdmpi.h
Description

MotorDelete deletes a Motor object and invalidates its handle (motor). MotorDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if MotorDelete successfully deletes a Motor object and invalidates its handle
See Also | mpiMotorCreate | mpiMotorValidate


mpiMotorEncoderFaultMaskBIT

Declaration

#define	mpiMotorEncoderFaultMaskBIT(fault)	(0x1 << (fault))
Required Header stdmpi.h
Description

MotorEncoderFaultMaskBIT converts the motor encoder fault into the motor encoder fault mask.

See Also | MPIMotorEncoderFault | MPIMotorEncoderFaultMask


meiMotorEncoderInit

meiMotorEndcoderInit

Declaration
long meiMotorEncoderInit(MPIMotor       motor,
                         MEIMotorOutput output,
                         MPIObjectMap   map)
Required Header stdmei.h
Description

MotorEncoderInit inititalizes one or more absolute encoders associated with the specified MPIObjectMap map, using an output signal associated with the motor.

Return Values
MPIMessageOK | if meiMotorEncoderInit(...) successfully initializes absolute encoder(s).
MEIMotorMessage ABS_ENCODER_FAULT | Returned when a protocol error occurs during the serial data transmission from the drive to controller.
MEIMotorMessage ABS_ENCODER_TIMEOUT | Returned when the controller does not receive serial data from the drive.

See Also | MPIObjectMap | meiMotorEncoderInit


meiMotorEncoderReset

Declaration
long meiMotorEncoderReset(MPIMotor motor)
Required Header stdmei.h
Description

MotorEncoderReset clears the broken wire and illegal state detection latches for the encoder associated with the specified motor.
Return Values
MPIMessageOK if MotorEncoderReset(...) successfully resets the motor’s encoder value.
See Also


meiMotorEncoderRatio

Declaration
long meiMotorEncoderRatio(MPIControl           control,
                          long                 motorNumber,
                          long                 encoderNumber,
                          MEIMotorEncoderRatio *ratio)
Required Header stdmei.h
Description

MotorEncoderRatio gets encoder ratio from the XMP.

Return Values
MPIMessageOK | if meiMotorEncoderRatio successfully gets encoder ration from the XMP.
MPIMessageARG_INVALID | if arguments are not valid
See Also


mpiMotorEventConfigGet

Declaration
long mpiMotorEventConfigGet(MPIMotor            motor,
                            MPIEventType        eventType,
                            MPIMotorEventConfig *eventConfig,
                            void                *external)
Required Header stdmpi.h
Description

MotorEventConfigGet gets the Motor’s (motor) configuration for the event specified by eventType and writes it into the structure pointed to by eventConfig, and also writes it to the implementation-specific structure pointed to by external (if external is not NULL).

The event configuration information in external is in addition to the event configuration information in eventConfig, i.e, the event configuration information in eventConfig and in external is not the same information. Note: Set eventConfig or external to NULL. One must be NULL, the other must be passed a pointer.
XMP Only

external either points to a structure of type MEIMotorEventConfig{} or is NULL.

Return Values
MPIMessageOK if MotorEventConfigGet successfully writes the Motor’s configuration for the event to the structure(s)
See Also | MEIMotorEventConfig | mpiMotorEventConfigSet


mpiMotorEventConfigSet

Declaration
long mpiMotorEventConfigSet(MPIMotor            motor,
                            MPIEventType        eventType,
                            MPIMotorEventConfig *eventConfig,
                            void                *external)
Required Header stdmpi.h
Description

MotorEventConfigSet

XMP Only

external either points to a structure of type MEIMotorEventConfig{} or is NULL.

Return Values
MPIMessageOK if MotorEventConfigGet successfully writes the Motor’s configuration for the event to the structure(s)
See Also | MEIMotorEventConfig | mpiMotorEventConfigGet


mpiMotorEventNotifyGet

Declaration
long mpiMotorEventNotifyGet(MPIMotor     motor,
                            MPIEventMask *eventMask,
                            void         *external)
Required Header stdmpi.h
Description

MotorEventNotifyGet writes the event mask (that specifies the event type(s) for which host notification has been requested) to the location pointed to by eventMask, and also writes it into the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventmask, i.e, the event notification information in eventmask and in external is not the same information. Note that eventmask or external can be NULL (but not both NULL).

Event notification is enabled for event types specified in eventmask, which is a bit mask of MPIEventMask bits associated with the desired MPIEventType values. Event notification is disabled for event types not specified in eventmask. The MPIEventMask bits must be set of cleared using the MPIEventMask macros.
XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL. The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).
Return Values
MPIMessageOK if MotorEventNotifyGet successfully writes the event mask to the location(s)
See Also | MPIEventType | MEIEventNotifyData | MEIEventStatusInfo mpiMotorEventNotifySet


mpiMotorEventNotifySet

Declaration
long mpiMotorEventNotifySet(MPIMotor     motor,
                            MPIEventMask eventMask,
                            void         *external)
Required Header stdmpi.h
Description

MotorEventNotifySet requests host notification of the event(s) that are generated by motor and specified by eventMask, and also specified by the implementation-specific location pointed to by external (if external is not NULL).

The event notification information in external is in addition to the event notification information in eventmask, i.e, the event notification information in eventmask and in external is not the same information. Note that eventmask or external can be NULL (but not both NULL).

Event notification is enabled for event types specified in eventMask, a bit mask of MPIEventMask bits associated with the desired MPIEventType values. Event notification is disabled for event types that are not specified in eventMask. The MPIEventMask bits must be set of cleared using the MPIEventMask macros.

The mask of event types generated by a Motor object consists of bits from MPIEventMaskMOTION and MPIEventMaskAXIS.
XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL. The MEIEventNotifyData{} structure is an array of firmware addresses, whose contents are placed into the MEIEventStatusInfo{} structure (of all events generated by this object).

To | Then
enable host notification of all events | set eventmask to MPIEventMaskALL
disable host notification of all events | set eventmask to MPIEventTypeNONE
Return Values
MPIMessageOK if MotorEventNotifySet successfully requests host notification of the event(s) that are specified by eventMask and generated by motor
See Also | MPIEventType | MEIEventNotifyData | MEIEventStatusInfo mpiMotorEventNotifyGet


mpiMotorEventReset

Declaration
long mpiMotorEventReset(MPIMotor     motor,
                        MPIEventMask eventMask)
Required Header stdmpi.h
Description

MotorEventReset resets the event(s) that are specified in eventMask and generated by motor.
Your application must call MotorEventReset only after one or more latchable events have occurred.
Return Values
MPIMessageOK if MotorEventReset successfully resets the event(s) that are specified in eventMask and generated by motor
See Also


mpiMotorEventWait

Declaration
long mpiNotifyEventWait(MPINotify      notify,
                        MPIEventStatus *status,
                        MPIWait        timeout)
Required Header stdmpi.h
Description

NotifyEventWait sets the contents of the structure pointed to by status, using the status of the first event in the internal FIFO event queue (maintained by a Notify object (notify)), and then removes the first event from the queue. If no event is available in the internal FIFO event queue, NotifyEventWait will wait for timeout milliseconds.

If "timeout" is | Then
MPIWaitPOLL (0) | NotifyEventWait will not wait for an event to arrive
MPIWaitFOREVER (-1) | NotifyEventWait will wait forever for an event to arrive

Return Values
MPIMessageOK | if NotifyEventWait successfully sets the contents of the structure pointed to by status, and then removes the first event from the queue
MPIMessageTIMEOUT | if no event is present and the contents of status are undefined
See Also


mpiMotorFeedbackGet

Declaration
long mpiMotorFeedbackGet(MPIMotor motor,
                         double   *feedback)
Required Header stdmpi.h
Description

MotorFeedbackGet gets the feedback position of a Motor (motor) and writes it into the location pointed to by feedback.

Return Values
MPIMessageOK if MotorFeedbackGet successfully writes the feedback position into the location
See Also | mpiMotorFeedbackConfigSet


mpiMotorFlashConfigGet

Declaration
long mpiMotorFlashConfigGet(MPIMotor       motor,
                            void           *flash,
                            MPIMotorConfig *config,
                            void           *external)
Required Header stdmpi.h
Description

MotorFlashConfigGet gets a Motor’s (motor) flash configuration and writes it in the structure pointed to by config, and also writes it in the implementation-specific structure pointed to by external (if external is not NULL).

The Motor’s flash configuration information in external is in addition to the Motor’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIMotorConfig{} or is NULL.

Return Values
MPIMessageOK if MotorFlashConfigGet successfully writes the Motor’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIMotorConfig | MEIFlash | mpiMotorFlashConfigSet


mpiMotorFlashConfigSet

Declaration
long mpiMotorFlashConfigSet(MPIMotor       motor,
                            void           *flash,
                            MPIMotorConfig *config,
                            void           *external)
Required Header stdmpi.h
Description

MotorFlashConfigSet sets a Motor’s (motor) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Motor’s flash configuration information in external is in addition to the Motor’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIMotorConfig{} or is NULL.
Return Values
MPIMessageOK if MotorFlashConfigSet successfully sets the Motor’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIMotorConfig | MEIFlash | mpiMotorFlashConfigGet


mpiMotorFilterMapGet

Declaration
long mpiMotorFilterMapGet(MPIMotor     motor,
                          MPIObjectMap *map)
Required Header stdmpi.h
Description

MotorFilterMapGet gets the object map of the Filters [that are associated with a Motor (motor)] and writes it into the structure pointed to by map.
Return Values
MPIMessageOK if MotorFilterMapGet successfully writes the Filter’s object map (associated with a Motor) to the structure
See Also | mpiMotorFilterMapSet


mpiMotorFilterMapSet

Declaration
long mpiMotorFilterMapSet(MPIMotor     motor,
                          MPIObjectMap map)
Required Header stdmpi.h
Description

MotorFilterMapSet sets the Filters [that are associated with a Motor (motor)], using data from the object map specified by map.

Return Values
MPIMessageOK if MotorFilterMapSet successfully sets the Filters using data from the object map
See Also | mpiMotorFilterMapGet


mpiMotorIoGet

Declaration
long mpiMotorIoGet(MPIMotor    motor,
                   MPIMotorIo  *io)
Required Header stdmpi.h
Description

MotorIoGet gets a Motor’s (motor) dedicated I/O bits and writes them into the structure pointed to by io.
Return Values
MPIMessageOK if MotorIoGet successfully writes the Motor’s dedicated I/O bits to the structure
See Also | mpiMotorIoSet


mpiMotorIoSet

Declaration
long mpiMotorIoSet(MPIMotor    motor,
                   MPIMotorIo  *io)
Required Header stdmpi.h
Description

MotorIoSet sets a Motor’s (motor) dedicated I/O bits using data from the structure pointed to by io.

Return Values
MPIMessageOK if MotorIoSet successfully sets the Motor’s dedicated I/O bits using data from the structure
See Also | mpiMotorIoGet


mpiMotorMemory

Declaration
long mpiMotorMemory(MPIMotor  motor,
                    void      **memory)
Required Header stdmpi.h
Description

MotorMemory writes an address [which can be used to access a Motor’s (motor) memory] to the contents of memory. This address, or an address calculated from it, can be passed as the src parameter to MPIMotorMemoryGet(...) and as the dst parameter to MPIMotorMemorySet(...).

Return Values
MPIMessageOK MotorMemory successfully writes the Motor’s address to the contents of memory
See Also | MPIMotorMemoryGet | MPIMotorMemorySet


mpiMotorMemoryGet

Declaration
long mpiMotorMemoryGet(MPIMotor motor,
                       void     *dst,
                       void     *src,
                       long     count)
Required Header stdmpi.h
Description

MotorMemoryGet copies count bytes of a Motor’s (motor) memory (starting at address src) to application memory (starting at address dst).
Return Values
MPIMessageOK if MotorMemoryGet successfully copies data from Motor memory to application memory
See Also | mpiMotorMemorySet | mpiMotorMemory


mpiMotorMemorySet

Declaration
long mpiMotorMemorySet(MPIMotor motor,
                       void     *dst,
                       void     *src,
                       long     count)
Required Header stdmpi.h
Description

MotorMemorySet copies count bytes of application memory (starting at address src) to a Motor’s (motor) memory (starting at address dst).

Return Values
MPIMessageOK if MotorMemorySet successfully copies data from application memory to Motor memory
See Also | mpiMotorMemoryGet | mpiMotorMemory


mpiMotorNumber

Declaration
long mpiMotorNumber(MPIMotor motor,
                    long     *number)
Required Header stdmpi.h
Description

MotorNumber writes the index of a Motor (motor, on the motion controller that motor is associated with) to the contents of number.

Return Values
MPIMessageOK if MotorNumber successfully writes the Motor’s index to the contents of number
See Also


meiMotorRelatedStepMotorGet

Declaration
long meiMotorRelatedStepMotorGet(MPIMotor    motor,
                                 long        *motorNumber)
Required Header stdmei.h
Description

MotorRelatedStepMotorGet searches for another motor that shares the resources of the motor provided. It then sets motorNumber to that motor's number. This scenario is only possible among Stepper Motors on a XMP Pulse controller. If there are no related motors found, motorNumber is set to MEIMotorResourceNumberINVALID.
Return Values
MPIMessageOK if motor is a valid MPIMotor object.
See Also | See the Software section of the XMP Pulse App Note 218.


mpiMotorStatus and meiMotorStatus

mpiMotorStatus / meiMotorStatus

mpiMotorStatus
Declaration
long mpiMotorStatus(MPIMotor    motor,
                    MPIStatus   *status,
                    void        *external)
Required Header stdmpi.h
Description

MotorStatus writes a Motor’s (motor) status into the structure pointed to by status, and also into the implementation-specific structure pointed to by external (if external is not NULL).

The motor’s status information in external is in addition to the motor’s status information in status, i.e, the status configuration information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

motor | a handle to the Motor object
*status | a pointer to the motor status structure returned by the method
*external | external either points to a structure of type MEIMotorStatus{…} or is NULL
Return Values
MPIMessageOK if MotorStatus successfully gets the status of a Motor object.
See Also | MPIStatus | MEIMotorStatus

meiMotorStatus
Declaration
long meiMotorStatus(MPIControl   control,
                    long         motorNumber
                    MPIStatus    *status,
                    void         *external)
Required Header stdmei.h
Description

MotorStatus gets a Motor's status and writes it to the structure pointed to by status, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

control | a handle to the Control object
motorNumber | index to the motor
*status | a pointer to the motor status structure returned by the method
*external | external either points to a structure of type MEIMotorStatus{…} or is NULL
Return Values
MPIMessageOK if MotorStatus successfully gets the status of a Motor object.
See Also | MPIStatus | MEIMotorStatus


mpiMotorType

Declaration
long mpiMotorType(MPIMotor     motor,
                  MPIMotorType *type)
Required Header stdmpi.h
Description

MotorType writes a Motor’s (motor) type into the structure pointed to by type.
Return Values
MPIMessageOK if MotorType successfully writes the Motor’s type to the structure(s)
See Also


mpiMotorValidate

Declaration
long mpiMotorValidate(MPIMotor motor)
Required Header stdmpi.h
Description

MotorValidate validates a Motor object and its handle (motor).
Return Values
MPIMessageOK if Motor is a handle to a valid object.
See Also | mpiMotorCreate | mpiMotorDelete


Node Objects

Introduction |
 | A Node object manages an individual SERCOS node. A SERCOS node may be a drive or I/O module.
Methods
Create, Delete, Validate Methods
 | mpiNodeCreate | Create Node object
 | mpiNodeDelete | Delete Node object
 | mpiNodeValidate | Validate Node object

Configuration and Information Methods
 | mpiNodeConfigGet | Get Node config
 | mpiNodeConfigSet | Set Node config
 | mpiNodeFlashConfigGet | Get flash configuration for Node
 | mpiNodeFlashConfigSet | Set flash configuration for Node
 | mpiNodeIdnDataGet |
 | mpiNodeIdnDataSet |
 | mpiNodeIdnFieldGet / meiNodeIdnFieldGet |
 | mpiNodeIdnFieldSet / meiNodeIdnFieldSet |
 | mpiNodeServiceProcedure | Execute the procedure in the node described by idn
 | mpiNodeStatus | Get the status of a Node

Memory Methods
 | mpiNodeMemory | Get address of Node memory

Relational Methods
 | mpiNodeIdnListGet | Get IdnList associated with a Node
 | mpiNodeIdnListSet | Set IdnList associated with a Node
 | mpiNodeNumber | Get index number of Node
 | mpiNodeSercos |
Other Methods
 | meiNodeOperationMode |
 | meiNodeRealTimeControlWordGet |
 | meiNodeRealTimeControlWordSet | Write the real time control word to a node.
 | meiNodeRealTimeStatusWordGet |
 | meiNodeTelegramType |
Data Types
MPINodeConfig / MEINodeConfig
MPINodeIdnListType
MEINodeIdnCyclic
MEINodeIdnData
MPINodeMode
MEINodeRealTimeBit
MEINodeRealTimeWord
Macros
mpiNodeIdnDataGET


MPINodeConfig and MEINodeConfig

MPINodeConfig / MEINodeConfig

MPINodeConfig

typedef struct MPINodeConfig {
    long	address;	/* SERCOS address 1 ..254 */
    long	motorNumber;
    long	filterNumber;
    MPINodeMode	mode;
} MPINodeConfig;

Description
 | address | In SERCOS each Node has a unique address on the ring(1 - 254).
 | motorNumber | The number of the MPIMotor associated with the SERCOS Node (1:1).
 | filterNumber | The number of the Filter associeated with the SERCOS Node (1:1).
 | mode | The position control algorithm used by the node.

MEINodeConfig

typedef struct MEINodeConfig {
    long		Enabled;
    long		StatusInvertMask;
    MEINodeIdnCyclic	At[MEIXmpNodeCyclicCountMAX];
    MEINodeRealTimeBit	RealTimeStatus[MEIXmpNodeRealTimeBitCountMAX];
    MEINodeRealTimeWord	RealTimeStatusWord;
    long		ControlInvertMask;
    MEINodeIdnCyclic	Mdt[MEIXmpNodeCyclicCountMAX];
    MEINodeRealTimeBit	RealTimeControl[MEIXmpNodeRealTimeBitCountMAX];
    long		HostRealTimeControlWord;
    MEINodeRealTimeWord	RealTimeControlWord;
} MEINodeConfig;
Description

NodeConfig is the configuration data that defines the operation of a Node.

Enabled | this variable reports whether or not the Node is enabled.
StatusInvertMask | a bit mask that is used to identify which status bits are inverted.
At | a list of IDNs that make up the AT data for a Node.
RealTimeStatus | in the RealTimeStatusWord there are 2 bits that can be assigned through IDN's to report certain events.
RealTimeStatusWord | located in the AT, this word is a bit mask that is used to report the status of a node.
ControlInvertMask | a bit mask that is used to identify which control bits are inverted.
Md | a list of IDNs that make up the MDT data that is sent to a Node.
RealTimeControl | in the RealTimeControlWord there are 2 bits that can be assigned through IDNs to trigger certain actions or report status from the controller to the Node.
HostRealTimeControlWord |
RealTimeControlWord | located in the MDT, this word is a bit mask that is used to control the node and report controller status.

See Also | mpiNodeConfigGet | mpiNodeConfigSet


MEINodeIdnCyclic

MEINodeIdnCyclic

typedef struct MEINodeIdnCyclic {
    long	IDNumber;
    long	UsageFlags;	/* Gain Scheduling, etc… */
    union {
    long	*Src;		/* Host address */
    long	*Dst;		/* Host address */
    } Data;
} MEINodeIdnCyclic;

Description
 | IDNumber | the number of the IDN
 | UsageFlags | a bit mask that defines how the IDN is used
 | Data | a pointer to where the data is located
See Also


MEINodeIdnData

MEINodeIdnData

typedef struct MEINodeIdnData {
    MPIIdnNumber	idnNumber;
    MPIIdnData		idnData;
} MEINodeIdnData;

Description
 | idnNumber | The number of an IDN.
 | idnData | The data of an IDN.

See Also | mpiMotionCreate | mpiControlConfigGet


MPINodeIdnListType

MPINodeIdnListType

typedef enum {
    MPINodeIdnListTypeINVALID,

    MPINodeIdnListTypePHASE2,
    MPINodeIdnListTypePHASE3,
    MPINodeIdnListTypeAMPLIFIER,
    MPINodeIdnListTypeMASTER_DATA,

} MPINodeIdnListType;

Description
 | MPINodeIdnListTypePHASE2 | List of IDN's that must be configured in phase 2
 | MPINodeIdnListTypePHASE3 | List of IDN's that must be configured in phase 3
 | MPINodeIdnListTypeAMPLIFIER | List of IDN's that are transmitted cyclically in the AT
 | MPINodeIdnListTypeMASTER_DATA | List of IDN's that are transmitted cyclically in the MDT
See Also


MPINodeMode

MPINodeMode

typedef enum {
    MPINodeModeINVALID,

    MPINodeModeNONE,

    /*	 servo_command_feedback 	*/
    MPINodeModeOPENLOOP_TORQUE,
    MPINodeModeOPENLOOP_VELOCITY,
    MPINodeModeOPENLOOP_POSITION_MOTOR,
    MPINodeModeOPENLOOP_POSITION_EXTERNAL,
    MPINodeModeOPENLOOP_POSITION_DUAL,

    MPINodeModePOSITION_TORQUE_MOTOR,
    MPINodeModePOSITION_TORQUE_EXTERNAL,
    MPINodeModePOSITION_VELOCITY_MOTOR,
    MPINodeModePOSITION_VELOCITY_EXTERNAL,

} MPINodeMode;
Description

NodeMode defines the different types of control algorithms that are supported under SERCOS and can be used by a node.

See Also


MEINodeRealTimeBit

MEINodeRealTimeBit

typedef struct MEINodeRealTimeBit {
    union {
        long	*Src;	/* Host address */
        long	*Dst;	/* Host address */
    } Data;
    long	BitMask;
} MEINodeRealTimeBit;
Description

The SERCOS RealTimeBit can be in the Status Word or Control Word. This is why Data can be either a Src or Dst. These pointers point to a 32-bit word. Since we are only looking at a bit, BitMask is used to mask off all the bits that are not of interest.

See Also | For more information, please refer to a SERCOS Specification Manual.


MEINodeRealTimeWord

MEINodeRealTimeWord

typedef struct MEINodeRealTimeWord {
    long	  	InvertMask;
    MEINodeRealTimeBit	Bit[MEIXmpNodeRealTimeWordBitCountMAX];
} MEINodeRealTimeWord;
Description

Each Node has a NodRealTimeWord for Control and Status, each of which is made up of 16 (MEIXmpNodeRealTimeWordBitCountMAX ) bits. The InvertMask is used to specify the polarity of each bit.

See Also | For more information, please refer to a SERCOS Specification Manual.


mpiNodeConfigGet

Declaration
long mpiNodeConfigGet(MPINode       node,
                      MPINodeConfig *config,
                      void          *external)
Required Header stdmpi.h
Description

NodeConfigGet gets a Node object’s (node) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEINodeConfig{} or is NULL.

Return Values
MPIMessageOK if NodeConfigGet successfully writes the Node object’s configuration to the structure(s)
See Also | MEINodeConfig | mpiNodeConfigSet


mpiNodeConfigSet

Declaration
long mpiNodeFlashConfigSet(MPINode       node,
                           void          *flash,
                           MPINodeConfig *config,
                           void          *external)
Required Header stdmpi.h
Description

NodeFlashConfigSet sets a Node object’s (node) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL). The Node object’s flash configuration information in external is in addition to the Node object’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEINodeConfig{} or is NULL.
Return Values
MPIMessageOK if NodeFlashConfigSet successfully sets the Node object’s flash configuration using data from the structure(s) flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEINodeConfig | MEIFlash | mpiNodeConfigGet


mpiNodeCreate

Declaration
const mpiNodeCreate(MPISercos sercos,
                    long      number)
Required Header stdmpi.h
Description

NodeCreate creates a node object associated with the node identified by number located on a SERCOS ring, sercos. NodeCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Node object
MPIHandleVOID | if the object could not be created

See Also | mpiNodeValidate | mpiNodeDelete


mpiNodeDelete

Declaration
long mpiNodeDelete(MPINode node)
Required Header stdmpi.h
Description

NodeDelete deletes a Node object and invalidates its handle (node). NodeDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if NodeDelete successfully deletes the Node object and invalidates its handle
See Also | mpiNodeCreate | mpiNodeValidate


mpiNodeFlashConfigGet

Declaration
long mpiNodeFlashConfigGet(MPINode       node,
                           void          *flash,
                           MPINodeConfig *config,
                           void          *external)
Required Header stdmpi.h
Description

NodeFlashConfigGet gets a Node object’s (node) flash configuration and writes it in the structure pointed to by config, and also writes it in the implementation-specific structure pointed to by external (if external is not NULL).

The Node object’s flash configuration information in external is in addition to the Node object’s flash configuratiosn information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEINodeConfig{} or is NULL.
Return Values
MPIMessageOK if NodeFlashConfigGet successfully writes the Node object’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEINodeConfig | MEIFlash | mpiNodeFlashConfigSet


mpiNodeFlashConfigSet

Declaration
long mpiNodeFlashConfigSet(MPINode       node,
                           void          *flash,
                           MPINodeConfig *config,
                           void          *external)
Required Header stdmpi.h
Description

mpiNodeFlashConfigSet sets a Node object’s (node) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Node object’s flash configuration information in external is in addition to the Node object’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEINodeConfig{} or is NULL.
Return Values
MPIMessageOK if NodeFlashConfigSet successfully sets the Node object’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEINodeConfig | MEIFlash | mpiNodeFlashConfigGet


meiNodeIdnDataGet and meiNodeIdnDataGET

meiNodeIdnDataGet / mpiNodeIdnDataGET

meiNodeIdnDataGet
Declaration
long meiNodeIdnDataGet(MPIControl       control,
                       MEIMotorTypeInfo *motorInfo,
                       long             count,
                       MEINodeIdnData   *idnData)
Required Header stdmei.h
Description NodeIdnDataGet reads the idn data and writes it to the structure pointed to by idnData. The data is read from the controller associated with the control object and the nodeNumber specified in the structure pointed to by motorInfo.
control | a handle to a Control object
*motorInfo | a pointer to a MEIMotorTypeInfo structure
count | number of MEINodeIdnData structures to read
*idnData | a pointer to an array of MEINodeIdnData structures
Return Values
MPIMessageOK if NodeIdnDataGet successfully reads the idn data.

meiNodeIdnDataGET
Declaration

#define     mpiNodeIdnDataGET(node, idn)
            mpiNodeIdnFieldGet((node), (idn), MPIIdnFieldDATA)
Required Header stdmpi.h
Description NodeIdnDataGET reads the data field from an idn located on a node, and writes them into the idn object.
See Also | meiNodeIdnDataSet


mpiNodeIdnDataGET

Declaration

#define     mpiNodeIdnDataGET(node, idn)
            mpiNodeIdnFieldGet((node), (idn), MPIIdnFieldDATA)
Required Header stdmpi.h
Description NodeIdnDataGET gets all of the fields from an idn located on a node, and writes them into the idn object.
See Also


meiNodeIdnDataSet and mpiNodeIdnDataSET

meiNodeIdnDataSet / mpiNodeIdnDataSET

meiNodeIdnDataSet
Declaration
long meiNodeIdnDataSet(MPIControl       control,
                       MEIMotorTypeInfo *motorInfo,
                       long             count,
                       MEINodeIdnData   *idnData)
Required Header stdmei.h
Description NodeIdnDataSet writes the idn data from the structure pointed to by idnData. The data is written to the controller associated with the control object and the nodeNumber specified in the structure pointed to by motorInfo.
control | a handle to a Control object
*motorInfo | a pointer to a MEIMotorTypeInfo structure
count | number of MEINodeIdnData structures to read
*idnData | a pointer to an array of MEINodeIdnData structures
Return Values
MPIMessageOK if NodeIdnDataSet successfully writes the idn data.

mpiNodeIdnDataSET
Declaration

#define     mpiNodeIdnDataSET(node, idn)
            mpiNodeIdnFieldSet((node), (idn), MPIIdnFieldDATA)
Required Header stdmpi.h
Description NodeIdnDataSET writes the data fields from an idn object to the idn located on a node.
See Also | meiNodeIdnDataGet | meiNodeIdnDataGET


mpiNodeIdnFieldGet and meiNodeIdnFieldGet

mpiNodeIdnFieldGet / meiNodeIdnFieldGet

mpiNodeIdnFieldGet
Declaration
long mpiNodeIdnFieldGet(MPINode     node,
                        MPIIdn      idn,
                        MPIIdnField field)
Required Header stdmpi.h
Description

NodeIdnFieldGet reads the specified field from an idn located on a node and writes it into the idn object.

node | a handle to the Node object
idn | a handle to an Idn object
field | enumeration corresponding to each element in the structure MPIIdnElement
Return Values
MPIMessageOK if NodeIdnFieldGet successfully reads the specified field.

meiNodeIdnFieldGet
Declaration
long meiNodeIdnFieldGet(MPINode     node,
                        MPIIdn      idn,
                        MPIIdnField field)
Required Header stdmei.h
Description NodeIdnFieldGet reads the specified field from the node into the idn.
Return Values
MPIMessageOK if NodeIdnFieldGet successfully reads the specified field.
See Also | mpiNodeIdnFieldSet


mpiNodeIdnFieldSet and meiNodeIdnFieldSet

mpiNodeIdnFieldSet / meiNodeIdnFieldSet

mpiNodeIdnFieldSet
Declaration
long mpiNodeIdnFieldSet(MPIIdn        idn,
                        MPIIdnField   field,
                        void          *value)
Required Header stdmpi.h
Description

NodeIdnFieldSet writes a value to a specified field located in the idn on a node. The node is determined by the association between the idn object and the node object.

idn | a handle to an Idn object
*value | a pointer to a void
Return Values
MPIMessageOK if NodeIdnFieldSet successfully writes the specified field.
See Also | mpiNodeIdnFieldGet

meiNodeIdnFieldSet
Declaration
long meiNodeIdnFieldSet(MPINode     node,
                        MPIIdn      idn,
                        MPIIdnField field)
Required Header stdmei.h
Description NodeIdnFieldSet writes the specified field to the node from the idn object.
Return Values
MPIMessageOK if NodeIdnFieldSet successfully writes the specified field.
See Also | mpiNodeIdnFieldGet | meiNodeIdnFieldGet


mpiNodeIdnGET

Declaration

#define     mpiNodeIdnGET(node, idn)
            mpiNodeIdnFieldGet((node), (idn), MPIIdnFieldALL)
Required Header stdmpi.h
Description NodeIdnGET gets all of the fields from an idn located on a node, and writes them into the idn object.
See Also


mpiNodeIdnListGet

Declaration
long mpiNodeIdnListGet(MPINode            node,
                       MPINodeIdnListType type,
                       MPIIdnList         idnList)
Required Header stdmpi.h
Description

NodeIdnListGet gets the Node’s (node) Idn list specified by type and writes it to idnList. The existing Idn list at idnList (if any) will be deleted.
Return Values
MPIMessageOK if NodeIdnListGet successfully gets and writes the Node’s Idn list to idnList
See Also | mpiNodeIdnListSet


mpiNodeIdnListSet

Declaration
long mpiNodeIdnListSet(MPINode            node,
                       MPINodeIdnListType type,
                       MPIIdnList         idnlist)
Required Header stdmpi.h
Description

NodeIdnListSet sets the Node’s (node) Idn list (specified by type) using data from idnList. The existing Idn list of the Node (if any) will be deleted.
Return Values
MPIMessageOK if NodeIdnListSet successfully sets the Node’s Idn list using data from idnList
See Also | mpiNodeIdnListGet


mpiNodeIdnSET

Declaration

#define     mpiNodeIdnSET(node, idn)
            mpiNodeIdnFieldSet((node), (idn), MPIIdnFieldDATA)
Required Header stdmpi.h
Description NodeIdnSET sets all of the fields from an idn located on a node, and writes them into the idn object.
See Also


mpiNodeMemory

Declaration
long mpiNodeMemory(MPINode   node,
                   void      **memory)
Required Header stdmpi.h
Description

NodeMemory writes an address [that is used to access Node (node) memory] to the contents of memory.
Return Values
MPIMessageOK if NodeMemory successfully writes the Node memory address to the contents of memory
See Also


mpiNodeNumber

Declaration
long mpiNodeNumber(MPINode node,
                   long    *number)
Required Header stdmpi.h
Description

NodeNumber writes the index of a Node object (node, on the motion controller that the Node object is associated with) to the location pointed to by number.

Return Values
MPIMessageOK if NodeNumber successfully writes the Node object’s index to the location
See Also


meiNodeOperationMode

Declaration
long meiNodeOperationMode(MPINode node,
                          long    *operationMode)
Required Header stdmei.h
Description NodeOperationMode returns in operationMode the sercos defined operation mode based on the MEI-defined operation mode.
Return Values
MPIMessageOK if successful
See Also


meiNodeRealTimeControlWordGet

Declaration
long meiNodeRealTimeControlWordGet(MPINode node,
                                   long    *realTimeControlWord)
Required Header stdmei.h
Description NodeRealTimeControlWordGet reads the real time control word from a node and writes it into the location pointed to by realTimeControlWord.
node | a handle to a Node object
*realTimeControlWord | a pointer to a long
Return Values
MPIMessageOK if NodeRealTimeControlWordGet successfully reads the real time control word.
See Also | mpiNodeRealTimeControlWordSet


meiNodeRealTimeControlWordSet

Declaration
long meiNodeRealTimeControlWordSet(MPINode node,
                                   long    realTimeControlWord)
Required Header stdmei.h
Description NodeRealTimeControlWordSet writes the real time control word to a node.
node | a handle to a Node object
*realTimeControlWord | a long value
Return Values
MPIMessageOK if NodeRealTimeControlWordSet successfully writes the real time control word.
See Also | mpiNodeRealTimeControlWordGet


meiNodeRealTimeStatusWordGet

Declaration
long meiNodeRealTimeStatusWordGet(MPINode node,
                                  long    *realTimeStatusWord)
Required Header stdmei.h
Description NodeRealTimeStatusWordGet reads the real time status word from a node and writes it into the location pointed to by realTimeStatusWord.
node | a handle to a Node object
*realTimeStatuslWord | a point to a long
Return Values
MPIMessageOK if NodeRealTimeStatusWordGet successfully reads the real time status word.
See Also


mpiNodeSercos

Declaration
const MPISercos  mpiNodeSercos(MPINode  node)
Required Header stdmpi.h
Description

NodeSercos returns a handle to Sercos object passed to the Node Object in the mpiNodeCreate() function call.
Return Values
MPIMessageOK if successful
See Also | mpiNodeCreate


mpiNodeServiceProcedure

Declaration
long mpiNodeServiceProcedure(MPINode                  node,
                             MPISercosProcedureAction action,
                             MPIIdn                   idn,
                             unsigned long            *status)
Required Header stdmpi.h
Description

NodeServiceProcedure executes the procedure in the node described by idn. The extent of the execution of the procedure is defined by the action parameter (see the MPISercosProcedureAction structure for the different actions).

Return Values
MPIMessageOK | if sucessful in executing action
MPISercosMessagePROCEDURE_ERROR | if an error occurs in the drive during execution
MPISercosMessagePROCEDURE_DATA_INVALID | if procedure data is invalid
MPISercosMessagePROCEDURE_TIMEOUT | if a timeout occurs and the procedure has not completed.
See Also


mpiNodeStatus

Declaration
long mpiNodeStatus(MPINode       node,
                   MPINodeStatus *status,
                   void          *external)
Required Header stdmpi.h
Description

NodeStatus writes a Node’s (node) status into the structure pointed to by status, and also into the implementation-specific structure pointed to by external (if external is not NULL).

The Node’s status information in external is in addition to the Node’s status information in status, i.e, the status configuration information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEINodeStatus{} or is NULL.

Return Values
MPIMessageOK if NodeStatus successfully writes the Node’s status to the structure(s)
See Also


meiNodeTelegramType

Declaration
long meiNodeTelegramType(MPINode node,
                         long    *telegramType)
Required Header stdmei.h
Description NodeTelegramType reads the telegram type from a node and writes it into the location pointed to by telegramType.
node | a handle to a Node object
*telegramType | a pointer to a long
Return Values
MPIMessageOK if NodeTelegramType successfully reads the telegram type.
See Also


mpiNodeValidate

Declaration
long mpiNodeValidate(MPINode node)
Required Header stdmpi.h
Description

NodeValidate validates the Node object and its handle (node).
Return Values
MPIMessageOK if Node is a handle to a valid object.
See Also | mpiNodeCreate | mpiNodeDelete


Notify Objects

Introduction

A thread uses a Notify object to wait for event notification. For each thread intended to wait for events from an object (or objects), your application must create a Notify object. The source of firmware events are Motion, Sequence, and Recorder objects.

When it is desired to wait for event notifications from a single source, that source (i.e., object handle) can be passed as the second argument to mpiNotifyCreate(...). After a Notify object is appended to the EventMgr list of Notify objects, make a call to mpiNotifyEventWait(...) to instruct the Notify object to wait for event notification.
Methods
Create, Delete, Validate Methods
 | mpiNotifyCreate | Create a Notify object
 | mpiNotifyDelete | Delete a Notify object
 | mpiNotifyValidate | Validate a Notify object

Event Methods
 | mpiNotifyEvent | Check to see if events have occurred
 | mpiNotifyEventFlush | Flush pending events from event queue
 | mpiNotifyEventMaskGet | Get event mask
 | mpiNotifyEventMaskSet | Set event mask
 | mpiNotifyEventWait | Get next event from queue or wait timeout msec for it to arrive
 | mpiNotifyEventWake | Wake up thread waiting for notify object

Relational Methods
 | List Methods for Event Sources
 | mpiNotifySource | Get the indexth event source in list
 | mpiNotifySourceAppend | Append an event source to list
 | mpiNotifySourceCount | Count number of event sources in list
 | mpiNotifySourceFirst | Get first event source in list
 | mpiNotifySourceIndex | Get index value for event source in list
 | mpiNotifySourceInsert | Place event source after source in list
 | mpiNotifySourceLast | Get last event source in list
 | mpiNotifySourceListGet | Get list of event sources
 | mpiNotifySourceListSet | Create a list of event sources
 | mpiNotifySourceNext | Get next event source after source in list
 | mpiNotifySourcePrevious | Get the event source before source in list
 | mpiNotifySourceRemove | Remove event source from list
Data Types
MPINotifyMessage
MEINotifyTrace


MPINotifyMessage

MPINotifyMessage

typedef enum {

    MPINotifyMessageNOTIFY_INVALID,
    MPINotifyMessageWAIT_IN_PROGRESS,
} MPINotifyMessage;

Description
 | MPINotifyMessageNOTIFY_INVALID
 | Meaning | The MPINotify handle passed to an MPINotify method is invalid.
 | Possible Causes | Either the handle was never initialized or the mpiNotifyCreate method failed.
 | Recommendations | Use mpiNotifyValidate after mpiNotifyCreate to see if the returned handle is valid.
 | MPINotifyMessageWAIT_IN_PROGRESS
 | Meaning | The MPINotify object is already set to wait for an event in another thread.
 | Possible Causes |
 | Recommendations | Have each thread use its own set of MPINotify objects.
Sample Code
MPIControl    control;
MPINotify      notify;
long              returnValue;
…

notify =
    mpiNotifyCreate(control);
returnValue =
    mpiNotifyValidate(notify);

See Also | MPINotify | mpiNotifyCreate | mpiNotifyValidate


MEINotifyTrace

MEINotifyTrace

typedef enum {

    MEINotifyTraceTHREAD,
} MEINotifyTrace;
Description
MEINotifyTraceTHREAD will display trace information when notify objects are set to wait, are finished waiting, and when they are signaled to wake.
See Also


mpiNotifyCreate

Declaration
const MPINotify mpiNotifyCreate(MPIEventMask mask,
                                void         *source)
Required Header stdmpi.h
Description

NotifyCreate creates a Notify object that will accept event notifications for the events that are specified in mask. The source argument specifies the initial element in the list of event sources, from which event notification will be accepted. If source is NULL, then event notification will be accepted from all event sources. NotifyCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Notify object
MPIHandleVOID | if the object could not be created

See Also | mpiNotifyDelete | mpiNotifyValidate


mpiNotifyDelete

Declaration
long mpiNotifyDelete(MPINotify notify)
Required Header stdmpi.h
Description

NotifyDelete deletes a Notify object and invalidates its handle (notify). NotifyDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if NotifyDelete successfully deletes a Notify object and invalidates its handle
See Also | mpiNotifyCreate | mpiNotifyValidate


mpiNotifyEvent

Declaration
long mpiNotifyEvent(MPINotify      notify,
                    MPIEventStatus *status)
Required Header stdmpi.h
Description

NotifyEvent first checks to see if the type field of status matches a bit in the event mask maintained by a Notify object (notify).

IF
the type field of status matches a bit in the event mask,

AND
the event source list maintained by the Notify object (notify) is empty or the source field of status matches a source in the event source list,

THEN
a Notify object (notify) will place the event in a FIFO event queue and signal that an event has been received.

If a thread is waiting for event notification (after having called mpiNotifyEventWait(notify)), the signal will awaken it. Otherwise, the next call to mpiNotifyEventWait(notify) will return immediately with status.

Return Values
MPIMessageOK if the Notify object (notify) successfully places the event in a FIFO event queue and signals that an event has been received
See Also | mpiNotifyEventWait


mpiNotifyEventFlush

Declaration
long mpiNotifyEventFlush(MPINotify   notify)

Required Header

 stdmpi.h
Description

NotifyEventFlush flushes any pending events from the internal FIFO event queue maintained by a Notify object (notify).

Return Values
MPIMessageOK if NotifyEventFlush successfully flushes the pending events from the internal FIFO event queue maintained by the Notify object
See Also


mpiNotifyEventMaskGet

Declaration

long mpiNotifyEventMaskGet(MPINotify    notify,
                           MPIEventMask *mask)
Required Header stdmpi.h
Description

NotifyEventMaskGet writes an event mask (that specifies the event type(s) for which event notification is accepted by a Notify object (notify)) to the location pointed to by mask.
Return Values
MPIMessageOK if NotifyEventMaskGet successfully writes the event mask to the location pointed to by mask
See Also | mpiNotifyEventMaskSet


mpiNotifyEventMaskSet

Declaration
long mpiNotifyEventMaskSet(MPINotify    notify,
                           MPIEventMask mask)
Required Header stdmpi.h
Description

NotifyEventMaskSet sets the event type(s) for which notification will be accepted by a Notify object (notify), as specified by mask.

Event notification is accepted for event types specified in mask, a bit mask of MPIEventMask bits (associated with the desired MPIEventType values). The MPIEventMask bits must be set or cleared using the MPIEventMask macros. Event notification is denied for event types not specified in mask.

Return Values
MPIMessageOK if NotifyEventMaskSet successfully sets the event type(s) for which notification will be accepted by a Notify object
See Also | MPIEventType | mpiNotifyEventMaskGet


mpiNotifyEventWake

Declaration
long mpiNotifyEventWake(MPINotify      notify,
                        MPIEventStatus *status)
Required Header stdmpi.h
Description

NotifyEventWake wakes a thread that is waiting for an event notification from a Notify object (notify). The awakened thread will return from its call to mpiNotifyEventWait(notify, status, timeout) with the contents of status set to the contents of status. If status is NULL, status will indicate an event of type MPIEventTypeNONE.

NotifyEventWake is different from NotifyEvent, because event notification is not accepted based on the event type or source (NotifyEvent); instead event notification is always accepted (NotifyEventWake).

Return Values
MPIMessageOK if NotifyEventWake successfully wakes a thread that is waiting for an event notification from a Notify object
See Also | mpiNotifyEventWait | MPIEventType


mpiNotifyEventWait

Declaration
long mpiNotifyEventWait(MPINotify      notify,
                        MPIEventStatus *status,
                        MPIWait        timeout)
Required Header stdmpi.h
Description

NotifyEventWait sets the contents of the structure pointed to by status, using the status of the first event in the internal FIFO event queue (maintained by a Notify object (notify)), and then removes the first event from the queue. If no event is available in the internal FIFO event queue, NotifyEventWait will wait for timeout milliseconds.

If "timeout" is | Then
MPIWaitPOLL (0) | NotifyEventWait will not wait for an event to arrive
MPIWaitFOREVER (-1) | NotifyEventWait will wait forever for an event to arrive

Return Values
MPIMessageOK | if NotifyEventWait successfully sets the contents of the structure pointed to by status, and then removes the first event from the queue
MPIMessageTIMEOUT | if no event is present and the contents of status are undefined

See Also | mpiNotifyEventWake


mpiNotifySource

Declaration
void* mpiNotifySource(MPINotify notify,
                      long      index)
Required Header stdmpi.h
Description

NotifySource returns the element at the position on the list indicated by index.

notify | a handle to the Notify object.
index | a position in the list.

Return Values
indexth event source | in the event source list maintained by a Notify object (notify)
NULL | if notify is invalid if index is less than 0 if index is greater than or equal to mpiNotifySourceCount(notify)
MPIMessageARG_INVALID | if index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | if index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | if notify is an invalid handle.
See Also


mpiNotifySourceAppend

Declaration
long mpiNotifySourceAppend(MPINotify notify,
                           void      *source)
Required Header stdmpi.h
Description

NotifySourceAppend appends an event source (source) to the list of event sources maintained by a Notify object (notify).

notify | a handle to the Notify object.
source | a pointer with an arbitrary (but non-NULL) value.

Return Values
MPIMessageOK | if NotifySourceAppend successfully appends source to the list of event sources maintained by a Notify object
MPIMessageHANDLE_INVALID | Either source is NULL or notify is an invalid handle.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiNotifySourceCount

Declaration
long mpiNotifySourceCount(MPINotify notify)
Required Header stdmpi.h
Description

NotifySourceCount returns the number of elements on the list.

notify | a handle to the Notify object.

Return Values
number of event sources | in the event source list maintained by a Notify object (notify)
-1 | if notify is invalid
0 | if the event source list is empty
See Also


mpiNotifySourceFirst

Declaration
void* mpiNotifySourceFirst(MPINotify notify)
Required Header stdmpi.h
Description

NotifySourceFirst returns the first element in the list. This function can be used in conjuntion with mpiNotifySourceNext() in order to iterate through the list.

notify | a handle to the Notify object.

Return Values
first event source | in the event source list maintained by a Notify object (notify)
NULL | if notify is invalid or if the event source list is empty
MPIMessageHANDLE_INVALID | if notify is an invalid handle.

See Also | mpiNotifySourceNext | mpiNotifySourceLast


mpiNotifySourceInsert

Declaration
long mpiNotifySourceInsert(MPINotify notify,
                           void      *source,
                           void      *insert)
Required Header stdmpi.h
Description

NotifySourceInsert places the event source (pointed to by insert) after a specified event source (source), in the list of event sources that are maintained by a Notify object (notify).
Return Values
MPIMessageOK if NotifySourceInsert successfully places the event source after the specified event source, in the list of event sources that are maintained by a Notify object
See Also


mpiNotifySourceIndex

Declaration
long mpiNotifySourceIndex(MPINotify notify,
                          void      *source)
Required Header stdmpi.h
Description

NotifySourceIndex returns the position of source on the list.

notify | a handle to the Notify object.
source | a pointer with an arbitrary (but non-NULL) value.

Return Values
index of source | in the event source list maintained by a Notify object (notify)
-1 | if notify is invalid if the event source (source) was not found in the event source list
See Also


mpiNotifySourceLast

Declaration
void* mpiNotifySourceLast(MPINotify notify)
Required Header stdmpi.h
Description

NotifySourceLast returns the last element in the list. This function can be used in conjuntion with mpiNotifySourcePrevious() in order to iterate through the list backwards.

notify | a handle to the Notify object.

Return Values
last event source | in the list maintained by a Notify object (notify)
NULL | if notify is invalid if the event source list is empty

See Also | mpiNotifySourcePrevious | mpiNotifySourceFirst


mpiNotifySourceListGet

Declaration
long mpiNotifySourceListGet(MPINotify notify,
                            long      *sourceCount,
                            void      **sourceList)
Required Header stdmpi.h
Description

NotifySourceListGet returns the event source list for a Notify object (notify). NotifySourceListGet writes the number of event sources in the event source list to the location (pointed to by sourceCount), and also writes an array of sourceCount event source pointers to the location (pointed to by sourceList).

Return Values
MPIMessageOK if NotifySourceListGet successfully returns the event source list for a Notify object
See Also | mpiNotifySourceListSet | NotifySourceAppend | NotifySourceInsert | mpiNotifyCreate


mpiNotifySourceListSet

Declaration
long mpiNotifySourceListSet(MPINotify notify,
                            long      sourceCount,
                            void      **sourceList)
Required Header stdmpi.h
Description

NotifySourceListSet creates an event source list of length sourceCount, using the source pointers specified by sourceList. The sourceList argument is the address of an array of sourceCount event source pointers, or is NULL (if sourceCount = 0). Any existing event source list is completely replaced after using NotifySourceListSet.

You can also create an event source list incrementally (i.e., created one source at a time) by using NotifySourceAppend/Insert methods. To specify the first event source of a list, use the source argument of mpiNotifyCreate(...). Use the NotifySourceList methods to examine and manipulate an event source list, regardless of how you created it.
Return Values
MPIMessageOK if NotifySourceListSet successfully creates an event source list using the source pointers specified by sourceList
See Also | NotifySourceAppend | NotifySourceInsert | mpiNotifyCreate | mpiNotifySourceListGet


mpiNotifySourceNext

Declaration
void * mpiNotifySourceNext(MPINotify  notify,
                           void       *source)
Required Header stdmpi.h
Description

NotifySourceNext returns the next element following "source" on the list. This function can be used in conjuntion with mpiNotifySourceFirst() in order to iterate through the list.

notify | a handle to the Notify object.
source | a pointer with an arbitrary (but non-NULL) value.

Return Values
event source | before the event source (source) in the event source list maintained by a Notify object (notify)
NULL | if notify is invalid if the event source (source) is the first event source in the event source list
MPIMessageHANDLE_INVALID | Either source is NULL or notify is an invalid handle.

See Also | mpiNotifySourcePrevious


mpiNotifySourcePrevious

Declaration
void * mpiNotifySourcePrevious(MPINotify notify,
                               void      *source)
Required Header stdmpi.h
Description

NotifySourcePrevious returns the previous element prior to "source" on the list. This function can be used in conjuntion with mpiNotifySourceLast() in order to iterate through the list backwards.

notify | a handle to the Notify object.
source | a pointer with an arbitrary (but non-NULL) value.

Return Values
event source | before the event source (source) in the event source list maintained by a Notify object (notify)
NULL | if notify is invalid if the event source (source) is the first event source in the event source list
MPIMessageHANDLE_INVALID | Either source is NULL or notify is an invalid handle.

See Also | mpiNotifySourceNext


mpiNotifySourceRemove

Declaration
long mpiNotifySourceRemove(MPINotify notify,
                           void      *source)
Required Header stdmpi.h
Description

NotifySourceRemove removes an event source (source) from the list of event sources maintained by a Notify object (notify).

Return Values
MPIMessageOK if NotifySourceRemove successfully removes the event source (source) from the list of event sources maintained by a Notify object
See Also


mpiNotifyValidate

Declaration
long mpiNotifyValidate(MPINotify notify)
Required Header stdmpi.h
Description

NotifyValidate validates a Notify object and its handle (notify).
Return Values
MPIMessageOK if Notify is a handle to a valid object.
See Also | mpiNotifyCreate | mpiNotifyDelete


Object Objects

Introduction |
 | Each Object shares some common functionality with other objects. The Object module encapsulates the common object methods and macros into a single module. This makes object handling consistent and more efficient.
Methods
Create, Delete, Validate Methods
 | mpiObjectValidate

Configuration and Information Methods
 | mpiObjectModuleId
 | mpiObjectTimeoutGet
 | mpiObjectTimeoutSet
 | meiObjectTraceGet
 | meiObjectTraceSet

Data Types
MPIObjectMap
Macros
 | mpiObjectMapAND_ASSIGN
 | mpiObjectMapASSIGN
 | mpiObjectMapBitCountMAX
 | mpiObjectMapBitGET
 | mpiObjectMapBitSET
 | mpiObjectMapCLEAR
 | mpiObjectMapCOMPLEMENT
 | mpiObjectMapIS_CLEAR
 | mpiObjectMapIS_EQUAL
 | mpiObjectMapIS_VALID
 | mpiObjectMapMAX
 | mpiObjectMapOR_ASSIGN
 | meiObjectTraceGET
 | meiObjectTraceSET


MPIObjectMap

MPIObjectMap

typedef unsigned long	MPIObjectMap;
Description
MPIObjectMap A map of MPI objects. An ObjectMap is a bitmap, where each numbered bit represents the presence or absence of the correspondingly numbered object. Valid maps are Axis/Filter and Filter/Motor. The Axis/Filter map can also be read, but setting this map must be done through the corresponding Filter objects.
See Also


mpiObjectMapAND_ASSIGN

Declaration

#define	  mpiObjectMapAND_ASSIGN(dst,src)	((dst) &= (src))
Required Header stdmpi.h
Description

Bitwise ANDs the dst object map with the src object map and assigns the result to dst.

See Also | mpiObjectMapASSIGN


mpiObjectMapASSIGN

Declaration

#define	   mpiObjectMapASSIGN(dst,src)	 ((dst) = (src))
Required Header stdmpi.h
Description

ObjectMapASSIGN assigns src object map to the dst object map.

See Also | mpiObjectMapAND_ASSIGN


mpiObjectMapBitCountMAX

Declaration
#define	  mpiObjectMapBitCountMAX(map)	(sizeof(map) * 8)
Required Header stdmpi.h
Description

ObjectMapBitCountMAX calculates the maximum bit count for the specified object map.
See Also


mpiObjectMapBitGET

Declaration

#define mpiObjectMapBitGET(map,bit)(((map) &  (0x1 << (bit))) ? 1 : 0)
Required Header stdmpi.h
Description

ObjectMapBitGET gets the bit number's state for the specified object map.

See Also | mpiObjectMapBitSET


mpiObjectMapBitSET

Declaration
#define	 mpiObjectMapBitSET(map,bit,value) \
            (((value) == 0) \
            ? ((map) &= ~(0x1 << (bit))) \
            : ((map) |=  (0x1 << (bit))))
Required Header stdmpi.h
Description

ObjectMapBitSET sets object map's specified bit number to the specified value.

See Also | mpiObjectMapBitGET


mpiObjectMapCLEAR

Declaration
#define mpiObjectMapCLEAR(map)  ((map) = 0x0)
Required Header stdmpi.h
Description

ObjectMapCLEAR sets the object map to zero.
See Also


mpiObjectMapCOMPLEMENT

Declaration
#define mpiObjectMapCOMPLEMENT(map)	((map) = ~(map))
Required Header stdmpi.h
Description

ObjectMapCOMPLEMENT performs bitwise complement to the object map and assigns the result to map.
See Also


mpiObjectMapIS_CLEAR

Declaration
#define mpiObjectMapIS_CLEAR(map)	((map) == 0x0)
Required Header stdmpi.h
Description

ObjectMapIS_CLEAR compares the map to 0x0. If the map is zero, it returns a non-zero value.
See Also


mpiObjectMapIS_EQUAL

Declaration

#define	  mpiObjectMapIS_EQUAL(map1,map2)	((map1) == (map2))
Required Header stdmpi.h
Description

ObjectMapIS_EQUAL compares map1 to map2. If the maps are equal, it returns a non-zero value.
See Also


mpiObjectMapIS_VALID

Declaration
#define	  mpiObjectMapIS_VALID(map,count) \
        (((count) >= (sizeof(map) * 8)) || \
        (((~((0x1 << (count)) - 1)) & (map)) == 0))
Required Header stdmpi.h
Description

ObjectMapIS_VALID checks if the map is within the count range. If the map is valid, it returns a non-zero value.
See Also


mpiObjectMapMAX

Declaration

#define	mpiObjectMapMAX(map,count)	((map) = (0x1 << (count)) - 1)
Required Header stdmpi.h
Description

ObjectMapMAX calculates the maximum object map with the specified count.
See Also


mpiObjectMapOR_ASSIGN

Declaration
#define    mpiObjectMapOR_ASSIGN(dst,src)    ((dst) |= (src))
Required Header stdmpi.h
Description

Bitwise ORs the dst object map with the src object map and assigns the result to dst.

See Also | mpiObjectMapASSIGN


mpiObjectModuleId

Declaration
long mpiObjectModuleId(MPIHandle    handle,
                       MPIModuleId  *moduleId)
Required Header stdmpi.h
Description

The ObjectModuleId function writes the MPIModuleId of the object (handle) to the location pointed to by moduleId.
Return Values
MPIMessageOK if ObjectModuleId successfully writes the MPIModuleId to the location
See Also


mpiObjectTimeoutGet

Declaration
long mpiObjectTimeoutGet(MPIHandle handle,
                         MPIWait   *timeout)
Required Header stdmpi.h
Description

The ObjectTimeoutGet method gets the timeout value for the object (handle), and writes it to the location pointed to by timeout.
Return Values
MPIMessageOK if ObjectTimeoutGet successfully writes the timeout value to the location
See Also | mpiObjectTimeoutSet


mpiObjectTimeoutSet

Declaration
long mpiObjectTimeoutSet(MPIHandle handle,
                         MPIWait   timeout)
Required Header stdmpi.h
Description

ObjectTimeoutSet sets the timeout value for an object (handle) to timeout.

The timeout value is used in a multi-threaded environment when an MPI function must block to wait for a shared resource to become available. The default timeout value is MPIWaitFOREVER.

If "timeout" is | Then
MPIWaitFOREVER | ObjectTimeoutSet will wait until the resource becomes available
MPIWaitPOLL | ObjectTimeoutSet will not wait for the resource to become available. If the shared resource is not available, a timeout will be considered to have occurred.
a value | ObjectTimeoutSet will wait timeout milliseconds for the resource to become available

Return Values
MPIMessageOK | if ObjectTimeoutSet successfully sets the timeout value of the object
MPIMessageTIMEOUT | if a timeout occurs before the shared resource becomes available

See Also | mpiObjectTimeoutGet


meiObjectTraceGet and meiObjectTraceGET

meiObjectTraceGet / meiObjectTraceGET

meiObjectTraceGet
Declaration
long meiObjectTraceGet(MPIHandle    handle,
                       MEITraceMask *traceMask)
Required Header stdmei.h
Description

ObjectTraceGet gets an Object's trace mask and writes it to the value pointed to by traceMask.

handle | a handle to an object
*traceMask | a pointer to the value of an object's trace mask
Return Values
MPIMessageOK if ObjectTraceGet successfully gets the trace mask for an object.

meiObjectTraceGET
Declaration

#define  meiObjectTraceGET(object)	(((MEIObject)(object))->trace)
Required Header stdmei.h
Description

ObjectTraceGET gets the object's global trace mask.

See Also | meiObjectTraceSET | meiObjectTraceSet


meiObjectTraceSet and meiObjectTraceSET

meiObjectTraceSet / meiObjectTraceSET

meiObjectTraceSet
Declaration
long meiObjectTraceSet(MPIHandle    handle,
                       MEITraceMask traceMask)
Required Header stdmei.h
Description

ObjectTraceSet sets an Object's trace mask to the value specified by traceMask.

handle | a handle to an object
traceMask | the value of an object's trace mask
Return Values
MPIMessageOK if ObjectTraceSet successfully sets the trace mask for an object.

meiObjectTraceSET
Declaration

#define  meiObjectTraceSET(object,mask)
                                (((MEIObject)(object))->trace = (mask))
Required Header stdmei.h
Description

ObjectTraceSET sets the object's global trace mask.

See Also | meiObjectTraceGET | meiObjectTraceGet


mpiObjectValidate

Declaration
long mpiObjectValidate(MPIHandle   handle,
                       MPIModuleId moduleId)
Required Header stdmpi.h
Description

The ObjectValidate method verifies that the object (handle) is of the type moduleId.

Return Values
MPIMessageOK if handle is a handle to a valid object of type moduleId.
See Also


Path Objects

Introduction

A Path object manages coordinated multi-axis motion profiles. It is used when the motion profiles in an N-Dimensional space are required to follow a specific coordinated trajectory. Motion paths are constructed with high level linear and arc segments and downloaded to the controller. The controller calculates the real-time individual axis profiles.

Generally, Path motion is used when the trajectory through space is more important than the final target position. Several different algorithms can be applied to convert the linear and arc segment path into an interpolated trajectory.

Path trajectory generation is now supported by PT, PVT, SPLINE, BESSEL, BSPLINE, and BSPLINE2 algorithms. Blending of the corners is only available for the 2 bspline algorithms. Blending of a corner is when the path does not hit the corner but goes through a smooth arc.
Methods
Create, Delete, Validate Methods
 | mpiPathCreate | Create a Path object
 | mpiPathDelete | Delete a Path object
 | mpiPathValidate | Validate a Path object

Configuration and Information Methods
 | mpiPathParamsGet
 | mpiPathParamsSet

Relational Methods
 | mpiPathAppend

Action Methods
 | mpiPathMotionParamsGenerate
Data Types
MPIPathArc
MPIPathArcCenter
MPIPathArcEndPoint
MPIPathAttr
MPIPathDirection
MPIPathElement
MPIPathElementAttributes
MPIPathElementAttrMask
MPIPathElementType
MPIPathLine
MPIPathMessage
MPIPathParams
MPIPathPoint
Constants
MPIPathPointDIMENSION_MAX


MPIPathArc

MPIPathArc

typedef struct MPIPathArc {
    struct {
        double	start;
        double	included;
    } angle;
    double	radius;
} MPIPathArc;
Description

PathArc specifies the parameters for an arc path element. It supports 2 dimensional arcs only. All arcs start at the end position for the last path element added to the path or the present command position if the arc is the first element in the path.

start | This value defines the arc's starting angle. Units are in degrees.
included | This value defines the relative travel angle. Units are in degrees. Positive values specify counter-clockwise motion and negative values specify clockwise motion.
radius | This value defines the distance from the center to the arc edge. Units are in counts.

See Also | MPIPathElement | MPIPathParams | MPIPathArcCenter


MPIPathArcCenter

MPIPathArcCenter

typedef struct MPIPathArcCenter {
    MPIPathPoint	center;
    double			angle;
} MPIPathArcCenter;
Description

PathArcCenter specifies the parameters for an arc path element. It supports 2 dimensional arcs only. All arcs start at the end position for the last path element added to the path or the present command position if the arc is the first element in the path.

center | This structure defines the coordinates for the center point of the arc. Please see MPIPathPoint data type documentation for more information.
angle | This value defines the relative travel angle. Units are in degrees. Positive values specify counter-clockwise motion and negative values specify clockwise motion.

See Also | MPIPathElement | MPIPathParams | MPIPathArc


MPIPathArcEndPoint

MPIPathArcEndPoint

typedef struct MPIPathArcEndPoint {
    MPIPathPoint		center;
    MPIPathPoint		endPoint;
    MPIPathDirection	direction;
} MPIPathArcEndPoint;
Description

PathArcEndPoint specifies the parameters for an arc path element. It supports 2 dimensional arcs only. All arcs start at the end position for the last path element added to the path or the present command position if the arc is the first element in the path.

center | This structure defines the coordinates for the center point of the arc. Please see MPIPathPoint data type documentation for more information.
endPoint | This structure defines the coordinates for the final point of the arc. Please see MPIPathPoint data type documentation for more information.
direction | This value defines the travel direction, counter-clockwise or clockwise. Please see MPIPathDirection data type documentation for more information.

See Also | MPIPathElement | MPIPathParams | MPIPathDirection


MPIPathAttr

MPIPathAttr

typedef enum {
    MPIPathElementAttrINVALID,

    MPIPathElementAttrRELATIVE,
    MPIPathElementAttrID,
    MPIPathElementAttrVELOCITY,
    MPIPathElementAttrACCEL,
    MPIPathElementAttrTIMESLICE,
    MPIPathElementAttrCOUNT,
} MPIPathAttr;
Description

In PathAttr, the path attributes are used to generate the path attribute masks to enable features with mpiPathAppend(…). Please see MPIPathElementAttrMask data type for more information.

See Also | mpiPathAppend


MPIPathDirection

MPIPathDirection

typedef enum {
    MPIPathDirectionCW,
    MPIPathDirectionCCW,
} MPIPathDirection;

Description
 | MPIPathDirectionCW | This value defines the clockwise direction.
 | MPIPathDirectionCCW | This value defines the counter-clockwise direction.

See Also | MPIPathArcEndPoint


MPIPathElement

MPIPathElement

typedef	struct MPIPathElement {
    MPIPathElementType		type;
    long				blending;
    union {
        MPIPathArc		arc;
        MPIPathArcCenter	arcCenter;
        MPIPathArcEndPoint	arcEndPoint;
        MPIPathHelix		helix;
        MPIPathIo		io;
        MPIPathLine		line;
    } params;

    MPIPathElementAttributes	attributes;
} MPIPathElement;

Description
 | type | This value defines the type of path element. Please see MPIPathElementType{…} data type documentation for more information.
 | blending | This value determines whether the corners of the path are rounded or sharp. When set to TRUE, blending is enabled, causing rounded corners. When set to FALSE, blending is disabled, causing sharp corners.
 | arc | This structure defines the arc's start angle, included angle, and radius. This structure is used when the type is MPIPathElementTypeARC. Please see MPIPathArc data type documentation for more information.
 | arcCenter | This structure defines the arc's center and angle. This structure is used when the type is MPIPathElementTypeARC_CENTER. Please see MPIPathArcCenter data type documentation for more information.
 | arcEndPoint | This structure defines the arc's center, end point, and direction. This structure is used when the type is MPIPathElementTypeARC_END_POINT. Please see MPIPathArcEndPoint data type documentation for more information.
 | helix | This structure is not supported and is reserved for future use.
 | io | This structure is not supported and is reserved for future use.
 | line | This structure defines the coordinates for a linear element. This structure is used when the type is MPIPathElementTypeLINE. Please see MPIPathLine data type documentation for more information.
 | attributes | This structure defines the attributes for a path element. Please see MPIPathElementAttributes data type documentation for more information.

See Also | mpiPathAppend


MPIPathElementAttrMask

MPIPathElementAttrMask

typedef	enum {
    MPIPathElementAttrMaskRELATIVE,   = mpiPathElementAttrMaskBIT(MPIPathElementAttrRELATIVE),
    MPIPathElementAttrMaskID,         = mpiPathElementAttrMaskBIT(MPIPathElementAttrID),
    MPIPathElementAttrMaskVELOCITY,   = mpiPathElementAttrMaskBIT(MPIPathElementAttrVELOCITY),
    MPIPathElementAttrMaskACCEL,      = mpiPathElementAttrMaskBIT(MPIPathElementAttrACCEL),
    MPIPathElementAttrMaskTIMESLICE), = mpiPathElementAttrMaskBIT(MPIPathElementAttrTIMESLICE),

    MPIPathElementAttrMaskALL,
} MPIPathElementAttrMask;
Description

In PathElementAttrMask, the path attribute masks are used to enable features with mpiPathAppend(…). The masks are ORed with the MPIPathElementType to enable each feature.

MPIPathElementAttrMaskRELATIVE | This mask enables relative coordinates for path motion. This feature is not supported and is reserved for future use.
MPIPathElementAttrMaskID | This mask enables an identification tag to be stored in the path. Each element can have a unique identification. Please see MPIPathElementAttributes{…} data type documentation for more information.
MPIPathElementAttrMaskVELOCITY | This mask enables a path velocity to be specified for each element. Please see MPIPathElementAttributes{…} data type documentation for more information.
MPIPathElementAttrMaskACCEL | This mask enables a path acceleration to be specified for each element. Please see MPIPathElementAttributes{…} data type documentation for more information.

See Also | MPIPathElementType | mpiPathAppend


MPIPathElementAttributes

MPIPathElementAttributes

typedef struct MPIPathElementAttributes {
    long	id;					/* MPIPathAttrID			*/
    double	velocity;			/* MPIPathAttrVELOCITY		*/
    double	acceleration;		/* MPIPathAttrACCELERATION	*/
    double	timeSlice;			/* MPIPathAttrTIMESLICE		*/
} MPIPathElementAttributes;
Description

In PathElementAttributes, the path attributes define the parameters to be used when specific features are enabled with the path element attribute masks. When using these attributes, be sure to enable the feature with the appropriate MPIPathElementAttrMask{…}.

id | This value defines an identification number to be stored in the path element. During path profile execution, at the start of each element the controller loads the id into the axis' ElementID field. The application can query the controller's axis memory to monitor the path element execution.
velocity | This value defines the velocity for the path element.
acceleration | This value defines the acceleration for the path element.
timeSlice | This value defines the time between interpolation points for the path element. The practical range for the time slice is from 10 msec (.01) to 100 msec (.1). Larger time slice values produce smoother (lower acceleration), less accurate paths. Smaller time slice values produce more accurate (both position and velocity) paths with higher peak accelerations.

See Also | MPIPathElementAttrMask


MPIPathElementType

MPIPathElementType

typedef enum {
    MPIPathElementTypeINVALID,

    MPIPathElementTypeARC,  /* only 2D */
    MPIPathElementTypeARC_CENTER,  /* only 2D */
    MPIPathElementTypeARC_END_POINT, /* both 2D and 3D */
    MPIPathElementTypeHELIX, /* not currently supported */
    MPIPathElementTypeIO, /* not currently supported */
    MPIPathElementTypeLINE, /* both 2D and 3D */

    MPIPathElementTypeMASK,
} MPIPathElementType;

Description
 | MPIPathElementTypeARC | This type generates an arc specified by the arc's start angle, included angle, and radius.
 | MPIPathElementTypeARC_CENTER | This type generates an arc specified by the arc's center and angle.
 | MPIPathElementTypeARC_END_POINT | This type generates an arc specified by the arc's center, end point, and direction.
 | MPIPathElementTypeLINE | This type generates a line specified by the position coordinates.

See Also | MPIPathArc | MPIPathLine


MPIPathLine

MPIPathLine

typedef struct MPIPathLine {
    MPIPathPoint	point;
} MPIPathLine;
Description

PathLine specifies the parameters for a linear path element. It supports up to MPIPathPointDIMENSION_MAX dimensions. All lines start at the end position for the last path element added to the path or the present command position if the line is the first element in the path.

point | This structure defines the end point coordinates for the linear segment.

See Also | MPIPathElement | MPIPathParams | MPIPathPointDIMENSION_MAX


MPIPathMessage

MPIPathMessage

typedef enum {

    MPIPathMessagePATH_INVALID,
    MPIPathMessageILLEGAL_DIMENSION,
    MPIPathMessageILLEGAL_ELEMENT,
    MPIPathMessageARC_ILLEGAL_DIMENSION,
    MPIPathMessageHELIX_ILLEGAL_DIMENSION,
    MPIPathMessageILLEGAL_RADIUS,
    MPIPathMessagePATH_TOO_LONG,
    MPIPathMessageILLEGAL_VELOCITY,
    MPIPathMessageILLEGAL_ACCELERATION,
    MPIPathMessageILLEGAL_TIMESLICE,
    MPIPathMessageINVALID_BLENDING,
} MPIPathMessage;

Description
 | MPIPathMessagePATH_INVALID | This message code occurs when the specified path cannot be created due to missing or invalid parameters.
 | MPIPathMessageILLEGAL_DIMENSION | This message code occurs when the specified dimension is out of range. The dimension must be between 1 and MPIPathPointDIMENSION_MAX or a specific dimension if required for specific path types.
 | MPIPathMessageILLEGAL_ELEMENT | This message code occurs when the specified path cannot be created due to an unsupported sequence of path elements.
 | MPIPathMessageARC_ILLEGAL_DIMENSION | This message code occurs when the specified dimension is out of range. An arc element dimension must be 2.
 | MPIPathMessageHELIX_ILLEGAL_DIMENSION | This message code occurs when the specified dimension is out of range. A helix element dimension must be 2.
 | MPIPathMessageILLEGAL_RADIUS | This message code occurs when the specified radius is less than or equal to zero.
 | MPIPathMessagePATH_TOO_LONG | This message code occurs when the specified path is longer than the statically allocated buffer can store.
 | MPIPathMessageILLEGAL_VELOCITY | This message code occurs when the specified velocity is less than or equal to zero.
 | MPIPathMessageILLEGAL_ACCELERATION | This message code occurs when the specified acceleration is less than or equal to zero.
 | MPIPathMessageILLEGAL_TIMESLICE | This message code occurs when the specified time slice is less than or equal to zero.
 | MPIPathMessageINVALID_BLENDING | This message code occurs when blending is specified but not supported with the particular motion type.
See Also


MPIPathParams

MPIPathParams

typedef struct MPIPathParams {
    long		dimension;
    MPIPathPoint	start;
    double		velocity;
    double		acceleration;
    double		deceleration;
    MPIMotionType	interpolation;
    double		timeSlice;
    double		conversion
                   [MPIPathPointDIMENSION_MAX][MPIPathPointDIMENSION_MAX];
} MPIPathParams;

Description
 | dimension | This value defines the number of axes to coordinate. Please see MPIPathPoint data type documentation for more information.
 | start | This structure defines the initial point for the path.
 | velocity | This value defines the speed along the path. The units are in counts per second.
 | acceleration | This value defines the rate of change of speed to reach the velocity along the path. The units are in counts per second * second.
 | deceleration | This value defines the rate of change of speed to reach zero velocity along the path. The units are in counts per second * second.
 | interpolation | This value specifies the motion algorithm to generate the path. Please see MPIMotionType data type documentation for more information.

See Also | mpiPathParamsGet | mpiPathParmsSet | mpiPathMotionParamsGenerate | MPIPathPointDIMENSION_MAX


MPIPathPoint

MPIPathPoint

typedef struct MPIPathPoint {
    double	position[MPIPathPointDIMENSION_MAX];
} MPIPathPoint;

Description
 | position | This array defines the axis command positions for a path point. There must be one position value for each dimension.

See Also | MPIPathParams | mpiPathParamsGet | mpiPathParmsSet | mpiPathPointDIMENSION_MAX


MPIPathPointDIMENSION_MAX

MPIPathPointDIMENSION_MAX

#define MPIPathPointDIMENSION_MAX	(16)
Description

PathPointDIMENSION_MAX defines the maximum dimensions for path objects.

See Also | MPIPathParams | MPIPathPoint


mpiPathAppend

Declaration
long mpiPathAppend(MPIPath        path,
                   MPIPathElement *element);
Required Header stdmpi.h
Description

PathAppend adds an array of path elements pointed to by element to the end of the path stored in the Path object.
Return Values
MPIMessageOK if PathAppend successfully adds the elements to the path.
See Also | mpiPathCreate | mpiPathMotionParamsGenerate


mpiPathCreate

Declaration
const MPIPath mpiPathCreate();
Required Header stdmpi.h
Description

PathCreate creates a Path object.

Return Values
handle | to a Path object
MPIHandleVOID | if the object could not be created

See Also | mpiPathDelete | mpiPathValidate


mpiPathDelete

Declaration
long mpiPathDelete(MPIPath path);
Required Header stdmpi.h
Description

PathDelete deletes a Path object and invalidates its handle (path). PathDelete is the equivalent of a C++ destructor.

Return Values
MPIMessageOK if PathDelete successfully deletes the Path object and invalidates its handle
See Also | mpiPathCreate | mpiPathValidate


mpiPathMotionParamsGenerate

Declaration
long mpiPathMotionParamsGenerate(MPIPath          path,
                                 MPIMotionParams  *params);
Required Header stdmpi.h
Description

PathMotionParamsGenerate
Return Values
See Also


mpiPathParamsGet

Declaration
long mpiPathParamsGet(MPIPath        path,
                      MPIPathParams  *params,
                      void           *external),
Required Header stdmpi.h
Description

PathParamsGet reads the parameters for a path object and writes them into the structure pointed to by params, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL)

path | a handle to a Path object
*params | a pointer to a MPIPathParams structure
*external | a pointer to a void or NULL
Return Values
MPIMessageOK if PathParamsGet successfully reads the path parameters.
See Also | mpiPathParamsSet


mpiPathParamsSet

Declaration
long mpiPathParamsSet(MPIPath        path,
                      MPIPathParams  *params,
                      void           *external),
Required Header stdmpi.h
Description

PathParamsSet writes the parameters from the structure pointed to by params into the Path object. Also, it writes the implementation-specific structure pointed to by external (if external is not NULL) into the Path object.

path | a handle to a Path object
*params | a pointer to a MPIPathParams structure
*external | a pointer to a void or NULL
Return Values
MPIMessageOK if PathParamsSet successfully writes the path parameters.
See Also | mpiPathParamsGet


mpiPathValidate

Declaration
long mpiPathValidate(MPIPath path);
Required Header stdmpi.h
Description

PathValidate validates the Path object and its handle (command)
Return Values
MPIMessageOK if the Path object and its handle are valid
See Also | mpiPathCreate | mpiPathDelete


Platform Objects

Introduction

The Platform module provides a common interface to platform-specific functionality, such as memory allocation, resource locking, interrupts, signalling, and others.

The Platform object provides low level platform-specific functionality and depends upon the combination of the operating system and the C compiler used for development. Although there are circumstances when your application will want to use Platform functions directly, your application won’t typically call Platform functions; usually the MPI functions will call Platform functions.

The meiObjectGive/Take(...) methods all use the meiPlatformLockGive/Take(...) methods. When you take a lock, you take exclusive access to the resource (i.e., the section of XMP firmware memory associated with that Object). When you give a lock, you release (give up) that exclusive access. Think of it as TakeAccessOf and GiveUpAccess.
Methods
meiPlatformAtol | Convert a numeric string to a long.
meiPlatformKey | Return an input character if an input character is available.
meiPlatformTrace | Display printf(...)-style trace information
meiPlatformTraceEol | Set the end-of-line (eol) to be used by meiPlatformTrace(...).
meiPlatformTraceFile |
meiPlatformTraceFunction |
Data Types
MEIPlatformFileMode
MEIPlatformMessage


MEIPlatformFileMode

MEIPlatformFileMode

typedef enum {
    MEIPlatformFileModeREAD,	/* default */
    MEIPlatformFileModeWRITE,
    MEIPlatformFileModeTEXT,	/* default */
    MEIPlatformFileModeBINARY,
} MEIPlatformFileMode;

Description
 | PlatformFileMode is an enumeration that is used as an argument for methods that open files.
See Also


MEIPlatformMessage

MEIPlatformMessage

typedef enum {

    MEIPlatformMessagePLATFORM_INVALID,
    MEIPlatformMessageDEVICE_INVALID,
    MEIPlatformMessageDEVICE_ERROR,
    MEIPlatformMessageDEVICE_MAP_ERROR,
} MEIPlatformMessage;

Description
 | MEIPlatformMessageDEVICE_INVALID | Unable to communicate to XMP device driver. (WIN32 Only: If you receive this error, verify that that device driver has been started.)
 | MEIPlatformMessageDEVICE_ERROR | A low level device driver call has failed. If you receive this error, check for hardware resource conflicts such as base address and IRQ number.
 | MEIPlatformMessageDEVICE_MAP_ERROR | The device driver is unable to map the XMP memory to host memory system. If you receive this error, check for hardware base address conflict.
See Also


meiPlatformAtol

Declaration
long meiPlatformAtol(const char *ascii)
Required Header stdmei.h
Description

PlatformAtol converts a numeric string to a long. This function returns the converted value as a long.

*ascii | string to be converted

Returns

 converted the numeric text string ascii to a long and returned it
See Also


meiPlatformKey

Declaration
long meiPlatformKey(MPIWait wait)
Required Header stdmei.h
Description

PlatformKey returns an input character (typically a keystroke) if an input character is available.
If an input charater is not available, PlatformKey waits wait milliseconds for an input character to become available.

If "wait" is | Then
MPIWaitFOREVER (-1) | PlatformKey will wait for an input character forever
MPIWaitPOLL (0) | PlatformKey will return immediately
a value (not -1 or 0) | PlatformKey will wait for an input character for wait milliseconds

Return Values
-1 | if no input character was available
0 | PlatformKey has read a non-zero character (typically a function key or other non-ASCII value), and meiPlatformKey(...) should be called AGAIN immediately to receive that non-zero character
a value (not -1 or 0) (an ASCII character) | (typically a keystroke) if an input character is available
See Also


meiPlatformTrace

Declaration
long meiPlatformTrace(const char *format, …)
Required Header stdmei.h
Description

PlatformTrace displays printf(...)-style trace information. An end-of-line character will be appended to the output, newline by default.

Library modules call meiTrace#(...), a macro which can be conditionally compiled to call meiPlatformTrace(...) (by defining the symbol MEI_TRACE when building the library).
Otherwise, calls to meiTrace#(...) are removed by the C preprocessor.

Return Values
MPIMessageOK if PlatformTrace successfully executes
See Also


meiPlatformTraceEol

Declaration
char meiPlatformTraceEol(char eol)
Required Header stdmei.h
Description

The PlatformTraceEol function sets the end-of-line (eol) character that will be used by meiPlatformTrace(...).

Returns

 the previous end-of-line character used by meiPlatformTrace(...)
See Also | meiPlatformTrace


meiPlatformTraceFile

Declaration
long meiPlatformTraceFile(const char *fileName)
Required Header stdmei.h
Description

PlatformTraceFile redirects trace output to fileName, after first closing any previously opened trace file. If no trace file has been explicitly opened, trace output will go to standard output.

Return Values
MPIMessageOK if PlatformTraceFile successfully closes any previously opened trace file and redirects trace output to fileName
See Also | meiPlatformTrace


meiPlatformTraceFunction

Declaration

     MEITraceFunction meiPlatformTraceFunction(MEITraceFunction traceFunction)
Required Header stdmei.h
Description

PlatformTraceFunction displays the trace output using traceFunction, and replaces the internal function that was called by meiPlatformTrace(...) to display the trace output. Use PlatformTraceFunction to enable your application to take control of the display of trace output.

Return Values
the previous traceFunction | if there is a previous function
NULL | if no traceFunction has been specified (the default trace function is used)

See Also | meiPlatformTrace


Recorder Objects

Introduction |
 | The Recorder object provides a mechanism to collect and buffer data from the controller. Only one Recorder object per controller is supported. After the Recorder is configured and started, the controller copies the data from the specified fields to a local buffer every "N" samples. The host can collect the data from the Recorder object using polling or interrupt-based techniques.
 | | Buffer Size |
Methods
Create, Delete, Validate Methods
 | mpiRecorderCreate | Create Recorder object
 | mpiRecorderDelete | Delete Recorder object
 | mpiRecorderValidate | Validate Recorder object

Configuration and Information Methods
 | mpiRecorderConfigGet | Get Recorder’s configuration
 | mpiRecorderConfigSet | Set Recorder’s configuration
 | mpiRecorderFlashConfigGet | Get Recorder’s flash configuration
 | mpiRecorderFlashConfigSet | Set Recorder’s flash configuration
 | mpiRecorderRecordConfig | Configure type of data record that Recorder will capture
 | mpiRecorderStatus | Get status of Recorder

Event Methods
 | mpiRecorderEventNotifyGet | Get event mask of events for which host notification has been requested
 | mpiRecorderEventNotifySet | Set event mask of events for which host notification will be requested
 | mpiRecorderEventReset | Reset the events specified in event mask that are generated by Recorder

Action Methods
 | mpiRecorderRecordGet | Get data records from Recorder
 | mpiRecorderStart | Start recording data records using Recorder
 | mpiRecorderStop | Stop recording data records using Recorder

Memory Methods
 | mpiRecorderMemory | Get address to Recorder’s memory
 | mpiRecorderMemoryGet | Copy data from Recorder memory to application memory
 | mpiRecorderMemorySet | Copy data from application memory to Recorder memory

Relational Methods
 | mpiRecorderControl | Return handle of Control object associated with Recorder
Data Types
MPIRecorderConfig / MEIRecorderConfig
MPIRecorderMessage
MPIRecorderRecord / MEIRecorderRecord
MEIRecorderRecordAxis
MEIRecorderRecordFilter
MPIRecorderRecordPoint
MPIRecorderRecordType / MEIRecorderRecordType
MPIRecorderStatus
MEIRecorderTrace
Constants
MPIRecorderADDRESS_COUNT_MAX


 Recorder Buffer Size

The Data Recorder buffer size can be dynamically allocated. The MPIControlConfig{...} structure has a new element, called recordCount. This element allows the application to change the size of the recorder object's data buffer using the mpiControlConfigGet/Set(...) methods. The Record buffer size (the default is 3064 records) is defined within the MEIXmpDefaultEnabled_Records structure (xmp.h). Each record is the size of one memory word. Using a larger data buffer size can improve the performance of MotionScope running on a slow host or running in Client/Server mode over a congested network.

A new method, meiControlExtMemAvail(...), has been added which will return the size of external memory available for allocation. This value can be added to the current recordCount to expand the record buffer to the maximum possible size.

For more information, see the Special Note on Dynamic Allocation of External Memory Buffers.

Return to Recorder Object's page


MPIRecorderADDRESS_COUNT_MAX

MPIRecorderADDRESS_COUNT_MAX

#define	MPIRecorderADDRESS_COUNT_MAX	(128)

Description
 | RecorderADDRESS_COUNT_MAX defines the maximum number of addresses the Recorder object supports.

See Also | MPIRecorderConfig


MPIRecorderConfig and MEIRecorderConfig

MPIRecorderConfig / MEIRecorderConfig

MPIRecorderConfig

typedef struct MPIRecorderConfig {
    long	period;		/* collect 1 record every `period` milliseconds */
    long	fullCount;	/* >0 => record count to trigger full buffer */

    long	addressCount;	/* number of data point addresses in address[] */
    void	*address[MPIRecorderADDRESS_COUNT_MAX];
} MPIRecorderConfig;

Description
 | period | The number of milliseconds between successive recordings. A value of zero means the recorder will record data every sample.
 | fullCount | If fullCount>0, then the recorder will generate a "recorder full" event when this fullCount number or records are in the recorder buffer.
 | addressCount | The number of XMP memory addresses in address[].
 | *address[] | An array of XMP memory addresses the recorder will record.

MEIRecorderConfig

typedef MPIEmpty	MEIRecorderConfig;

Description
 | RecorderConfig is currently not supported and is reserved for future use.

See Also | mpiRecorderConfigGet | mpiRecorderConfigSet


MPIRecorderMessage

MPIRecorderMessage

typedef enum {

    MPIRecorderMessageRECORDER_INVALID,
    MPIRecorderMessageSTARTED,
    MPIRecorderMessageSTOPPED,
    MPIRecorderMessageNOT_CONFIGURED,
} MPIRecorderMessage;

Description
 | MPIRecorderMessageRECORDER_INVALID
 | Meaning | The MPIRecorder handle passed to an MPIRecorder method is invalid.
 | Possible Causes | Either the handle was never initialized or the MPIRecorderCreate method failed.
 | Recommendations | Use MPIRecorderValidate after MPIRecorderCreate to see if the returned handle is valid.
 | MPIRecorderMessageSTARTED
 | Meaning |
 | Possible Causes | An MPIRecorder method that assumes that recorder has not been started has been called while the recorder was recording data.
 | Recommendations | .
 | MPIRecorderMessageSTOPPED
 | Meaning | .
 | Possible Causes | An MPIRecorder method that assumes that recorder has been started has been called while the recorder was not recording data.
 | Recommendations | .
 | MPIRecorderMessageNOT_CONFIGURED
 | Meaning | .
 | Possible Causes | An MPIRecorder method has been called that assumes that the recorder has been configured. mpiRecorderStart is the most common method to return this error code.
 | Recommendations | .
Sample Code
MPIControl      control;
MPIRecorder   recorder;
long                returnValue;
…

recorder =
    mpRecorderCreate(control);
returnValue =
    mpiRecorderValidate(recorder);

See Also | mpiRecorderCreate | mpiRecorderValidate


MPIRecorderRecord and MEIRecorderRecord

MPIRecorderRecord / MEIRecorderRecord

MPIRecorderRecord

typedef union {
    MPIRecorderRecordPoint	point[MPIRecorderADDRESS_COUNT_MAX];
} MPIRecorderRecord;
Description
point An array of recorded values corresponding to the XMP addresses stored in MPIRecorderConfig.address[].

MEIRecorderRecord

 typedef union {
    MEIRecorderRecordAxis	axis[MEIXmpMAX_Axes];
    MEIRecorderRecordFilter	filter[MEIXmpMAX_Filters];
    MPIRecorderRecord		dummy;	/* ensure proper sizing */
} MEIRecorderRecord;

Description
 | axis | An array of MEIRecorderRecordAxis records.
 | filter | An array of MEIRecorderRecordFilter records.
 | dummy | A dummy structure that ensures that MEIRecorderRecord has the proper size.
See Also


MEIRecorderRecordAxis

MEIRecorderRecordAxis

typedef struct MEIRecorderRecordAxis {
    long    sample;	    /* sample number */
    long    command;        /* command position */
    long    actual;	    /* actual position */
    float   dac;	    /* voltage */
} MEIRecorderRecordAxis;

Description
 | sample | The XMP sample number in which the following values were recorded.
 | command | The command position of the axis.
 | actual | The actual position of the axis.
 | dac | The output of the primary DAC of the motor associated with the axis.
See Also


MEIRecorderRecordFilter

MEIRecorderRecordFilter

typedef struct MEIRecorderRecordFilter {
    long	sample;		/* sample number */
    long	command;	/* command position */
    long	actual;		/* actual position */
    float	dac;		/* voltage */
} MEIRecorderRecordFilter;

Description
 | sample | The XMP sample number in which the following values were recorded
 | command | The command position the filter uses to calculate the filter output.
 | actual | The actual position (of an axis) the filter uses to calculate the filter output.
 | dac | The output of the filter that gets sent to a motor's primary DAC.
See Also


MPIRecorderRecordPoint

MPIRecorderRecordPoint

typedef long MPIRecorderRecordPoint;
Description
MPIRecorderRecordPoint represents one recorder record. This will correspond to the value of one XMP address.
See Also


MPIRecorderType and MEIRecorderType

MPIRecorderRecordType / MEIRecorderRecordType

MPIRecorderRecordType

typedef enum {
    MPIRecorderRecordTypeINVALID,
    MPIRecorderRecordTypePOINT,

} MPIRecorderRecordType;

Description
 | MPIRecorderRecordTypeINVALID | specifies to the data recorder that MPIRecorderRecordPoint records (copies of controller memory locations) are being recorded.
 | MPIRecorderRecordTypePOINT | an invalid record type.

MEIRecorderRecordType

typedef enum {
    MEIRecorderRecordTypeAXIS,
    MEIRecorderRecordTypeFILTER,
} MPIRecorderRecordType;

Description
 | MEIRecorderRecordTypeAXIS | specifies to the data recorder that MEIRecorderRecordAxis records are being recorded.
 | MEIRecorderRecordTypeFILTER | specifies to the data recorder that MEIRecorderRecordFilter records are being recorded.

Remarks
 | Predefined types for setting up the type of data an MPIRecorder object will record. This is used by the mpiRecorderRecordConfig() method.

See Also | MPIRecorder | MEIRecorderRecordAxis | MEIRecorderRecordFilter | mpiRecorderRecordConfig


MPIRecorderStatus

MPIRecorderStatus

typedef struct MPIRecorderStatus {
    long    enabled;
    long    full;
    long    recordCount;
    long    recordCountMax;
} MPIRecorderStatus;

Description
 | enabled | If the recorder is enabled (recording) then enabled will equal TRUE, otherwise enabled will equal FALSE.
 | full | If the recorder is full (the number of stored records >= MPIRecorderConfig.fullCount) then full will equal TRUE, otherwise full will equal FALSE.
 | recordCount | The number of stored records in the recorder.
 | recordCountMax | The maximum number of records the recorder can store.

See Also | mpiRecorderStatus


MEIRecorderRecordTrace

MEIRecorderRecordTrace

typedef enum {

    MEIRecorderTraceRECORD_GET,
    MEIRecorderTraceSTATUS,
    MEIRecorderTraceOVERFLOW,
} MEIRecorderTrace;

Description
 | MEIRecorderTraceRECORD_GET | will display trace information when the data recorder retrieves records.
 | MEIRecorderTraceSTATUS | will display trace information when the MPI retrieves the data recorder status.
 | MEIRecorderTraceOVERFLOW | will display trace information when the data recorder overflows.
See Also


mpiRecorderConfigGet

Declaration
long mpiRecorderConfigGet(MPIRecorder       recorder,
                          MPIRecorderConfig *config,
                          void              *external)
Required Header stdmpi.h
Description

RecorderConfigGet gets a Recorder’s (recorder) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Recorder’s configuration information in external is in addition to the Recorder’s configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIRecorderConfig{} or is NULL.

Return Values
MPIMessageOK if RecorderConfigGet successfully writes the Recorder’s configuration to the structure(s)
See Also | MEIRecorderConfig | mpiRecorderConfigSet


mpiRecorderConfigSet

Declaration
long mpiRecorderConfigSet(MPIRecorder       recorder,
                          MPIRecorderConfig *config,
                          void              *external)
Required Header stdmpi.h
Description

RecorderConfigSet sets a Recorder’s (recorder) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Recorder’s configuration information in external is in addition to the Recorder’s configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIRecorderConfig{} or is NULL.
Return Values
MPIMessageOK if RecorderConfigSet successfully sets the Recorder’s configuration using data from the structure(s)
See Also | MEIRecorderConfig | mpiRecorderConfigGet


mpiRecorderControl

Declaration
const MPIControl mpiRecorderControl(MPIRecorder recorder)
Required Header stdmpi.h
Description

RecorderControl returns a handle to the motion controller (Control object) that a Recorder (recorder) is associated with.

Return Values
handle | to a Control object that a Recorder is associated with
MPIHandleVOID | if the Recorder object is invalid
See Also


mpiRecorderCreate

Declaration
const MPIRecorder mpiRecorderCreate(MPIControl control)
Required Header stdmpi.h
Description

RecorderCreate creates a Recorder object associated with a Control object (control). RecorderCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Recorder object
MPIHandleVOID | if the Recorder object could not be created

See Also | mpiRecorderDelete | mpiRecorderValidate


mpiRecorderDelete

Declaration
long mpiRecorderDelete(MPIRecorder recorder)
Required Header stdmpi.h
Description

RecorderDelete deletes a Recorder object and invalidates its handle (recorder). RecorderDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if RecordeDelete successfully deletes a Recorder object and invalidates its handle
See Also | mpiRecorderCreate | mpiRecorderValidate


mpiRecorderEventNotifyGet

Declaration
long mpiRecorderEventNotifyGet(MPIRecorder  recorder,
                               MPIEventMask *eventMask,
                               void         *external)
Required Header stdmpi.h
Description

RecorderEventNotifyGet writes the event mask into the structure pointed to by eventMask, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL). (The event mask specifies the event type(s) generated by a Recorder (recorder), for which host notification has been requested.)

The event mask information in external is in addition to the event mask information in eventMask, i.e, the mask information in eventMask and in external is not the same mask information. Note that eventMask or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL. An MEIEventNotifyData{} structure is an array of firmware addresses. The contents of these firmware addresses are placed into the MEIEventStatusInfo{} structure (which contains all events generated by this Recorder object).
Return Values
MPIMessageOK if RecorderEventNotifyGet successfully writes the event mask to the structure(s)
See Also | MEIEventNotifyData | MEIEventStatusInfo | mpiRecorderEventNotifySet


mpiRecorderEventNotifySet

Declaration
long mpiRecorderEventNotifySet(MPIRecorder   recorder,
                               MPIEventMask  eventMask,
                               void          *external)
Required Header stdmpi.h
Description

RecorderEventNotifySet requests host notification of the event(s) specified by eventMask and generated by a Recorder (recorder), and also generated by the implementation-specific structure pointed to by external (if external is not NULL).

The events in external are in addition to the events in recorder, i.e, the events in recorder and in external are not necessarily the same events. Note that recorder or external can be NULL (but not both NULL).

Event notification is enabled for the event types specified in eventMask. eventMask is a bit mask generated by the logical OR of the MPIEventMask bits that are associated with the desired MPIEventType values. Event notification is disabled for event types not specified in eventMask.

The mask of event types (generated by a Recorder object) consists of MEIEventMaskRECORDER_FULL and MEIEventMaskRECORDER_DONE.

To | Use "eventMask"
Enable host notification of all Recorder events | MPIEventMaskALL
Disable host notification of all Recorder events | MPIEventTypeNONE
XMP Only

external either points to a structure of type MEIEventNotifyData{} or is NULL. An MEIEventNotifyData{} structure is an array of firmware addresses. The contents of these firmware addresses are placed into the MEIEventStatusInfo{} structure (which contains all events generated by this Recorder object).

Return Values
MPIMessageOK if RecorderEventNotifySet successfully requests host notification of the event(s) as specified by the structure(s)
See Also | MEIEventMaskRECORDER | MEIEventNotifyData | MEIEventStatusInfo mpiRecorderEventNotifyGet


mpiRecorderEventReset

Declaration
long mpiRecorderEventReset(MPIRecorder  recorder,
                           MPIEventMask eventMask)
Required Header stdmpi.h
Description

RecorderEventReset resets the event(s) specified in eventMask and generated by a Recorder (recorder). Your application should call RecorderEventReset only after one or more latchable events have occurred.
Return Values
MPIMessageOK if RecorderEventReset successfully resets the event(s) that are specified in eventMask and generated by a Recorder
See Also


mpiRecorderFlashConfigGet

Declaration
long mpiRecorderFlashConfigGet(MPIRecorder       recorder,
                               void              *flash,
                               MPIRecorderConfig *config,
                               void              *external)
Required Header stdmpi.h
Description

RecorderFlashConfigGet gets the flash configuration (flash) for a Recorder (recorder) and writes it into the structure pointed to by config, and also writes it in the implementation-specific structure pointed to by external (if external is not NULL).

The Recorder’s flash configuration information in external is in addition to the Recorder’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIRecorderConfig{} or is NULL.

Return Values
MPIMessageOK if RecorderFlashConfigGet successfully writes the Recorder’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIRecorderConfig | MEIFlash | mpiRecorderFlashConfigSet


mpiRecorderFlashConfigSet

Declaration
long mpiRecorderFlashConfigSet(MPIRecorder       recorder,
                               void              *flash,
                               MPIRecorderConfig *config,
                               void              *external)
Required Header stdmpi.h
Description

RecorderFlashConfigSet sets the flash configuration (flash) for a Recorder (recorder) using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Recorder’s flash configuration information in external is in addition to the Recorder’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEIRecorderConfig{} or is NULL.

Return Values
MPIMessageOK if RecorderFlashConfigSet successfully sets the Recorder’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIRecorderConfig | MEIFlash | mpiRecorderFlashConfigGet


mpiRecorderMemory

Declaration
long mpiRecorderMemory(MPIRecorder recorder,
                       void        **memory)
Required Header stdmpi.h
Description

RecorderMemory writes an address to the contents of memory. An address can be used to access a Recorder’s (recorder) memory. An address calculated from it can be passed as the src argument to mpiRecorderMemoryGet(...) and as the dst argument to mpiRecorderMemorySet(...).

Return Values
MPIMessageOK if RecorderMemory successfully writes the Recorder’s memory address to the contents of memory
See Also | mpiRecorderMemoryGet | mpiRecorderMemorySet


mpiRecorderMemoryGet

Declaration
long mpiRecorderMemoryGet(MPIRecorder recorder,
                          void        *dst,
                          void        *src,
                          long        count)
Required Header stdmpi.h
Description

RecorderMemoryGet copies count bytes of a Recorder’s (recorder) memory (starting at address src) to application memory (starting at address dst).

Return Values
MPIMessageOK if RecorderMemoryGet successfully copies data from Recorder memory to application memory
See Also | mpiRecorderMemory | mpiRecorderMemorySet


mpiRecorderMemorySet

Declaration
long mpiRecorderMemorySet(MPIRecorder recorder,
                          void        *dst,
                          void        *src,
                          long        count)
Required Header stdmpi.h
Description

RecorderMemorySet copies count bytes of application memory (starting at address src) to a Recorder’s (recorder) memory (starting at address dst).
Return Values
MPIMessageOK if RecorderMemorySet successfully copies data from application memory to Recorder memory
See Also | mpiRecorderMemory | mpiRecorderMemoryGet


mpiRecorderRecordConfig

Declaration
long mpiRecorderRecordConfig(MPIRecorder           recorder,
                             MPIRecorderRecordType type,
                             long                  count,
                             void                  *handle)
Required Header stdmpi.h
Description

RecorderRecordConfig configures the type (type) of record that a Recorder (recorder) will capture.

If "type" is | Then
MPIRecorderRecordTypePOINT | count data points will be recorded, and handle points to an array of count controller addresses
MEIRecorderRecordTypeAXIS | count records of type MPIRecorderRecordAxis{} will be recorded, and handle points to an array of count Axis handles
MEIRecorderRecordTypeFILTER | count records of type MPIRecorderRecordFilter{} will be recorded, and handle points to an array of count Filter handles
Return Values
MPIMessageOK if RecorderRecordConfig successfully configures the type of record that the Recorder will capture
See Also | MPIRecorderRecordAxis | MPIRecorderRecordFilter


mpiRecorderRecordGet

Declaration
long mpiRecorderRecordGet(MPIRecorder       recorder,
                          long              countMax,
                          MPIRecorderRecord *record,
                          long              *count)
Required Header stdmpi.h
Description

RecorderRecordGet obtains a Recorder’s (recorder) data records. The record type must have been configured previously, by a prior call to mpiRecorderRecordConfig(...).

RecorderRecordGet gets a maximum of countMax records and writes them into the location pointed to by record (the location must be large enough to hold them). RecorderRecordGet also writes the actual number of records that were obtained to the location pointed to by count.

If the recorder data buffer is full and recording is enabled, recording will be temporarily disabled while either all or countMax records are obtained, whichever is less. Any records not obtained will be lost.

Return Values
MPIMessageOK if RecorderRecordGet successfully gets the data records
See Also | mpiRecorderRecordConfig


mpiRecorderStop

Declaration
long mpiRecorderStop(MPIRecorder recorder)
Required Header stdmpi.h
Description

RecorderStop instructs a Recorder (recorder) to stop recording data records.
Return Values
MPIMessageOK if RecorderStop successfully stops recording data records
See Also | mpiRecorderStart


mpiRecorderStart

Declaration
long mpiRecorderStart(MPIRecorder  recorder,
                      long         count,
                      long         period,
                      long         fullCount)
Required Header stdmpi.h
Description

RecorderStart instructs a Recorder (recorder) to begin recording data records. The record type must have been configured previously, by a prior call to mpiRecorderRecordConfig(...).

An event of type MPIEventRECORDER_DONE will be generated when the Recorder has finished collecting data records.

count ( for count > 0) | specifies the total number of data records to record
if count = -1 | then recording is continuous, and uncollected records may be overwritten
period if period = 0 | frequency of recording in milliseconds then data will be recorded as quickly as possible (on every sample)
if fullCount > 0 | then an event of type MPIEventRECORDER_COUNT will be generated when the Recorder’s data buffer contains fullCount data records
Return Values
MPIMessageOK if RecorderStart successfully instructs a Recorder to begin recording data records
See Also | mpiRecorderRecordConfig | mpiRecorderStop


mpiRecorderStatus

Declaration
long mpiRecorderStatus(MPIRecorder       recorder,
                       MPIRecorderStatus *status,
                       void              *external)
Required Header stdmpi.h
Description

RecorderStatus gets the status of the Recorder (recorder) and writes it into the structure pointed to by status, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Recorder’s status information in external is in addition to the Recorder’s status information in status, i.e., the status information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MPIRecorderStatus{} or is NULL.

Return Values
MPIMessageOK if RecorderStatus successfully gets the Recorder’s status and writes it into the structure(s)
See Also | MPIRecorderStatus


mpiRecorderValidate

Declaration
long mpiRecorderValidate(MPIRecorder recorder)
Required Header stdmpi.h
Description

RecorderValidate validates the Recorder object and its handle (recorder).

Return Values
MPIMessageOK if Recorder is a handle to a valid object.
See Also | mpiRecorderCreate | mpiRecorderDelete


Sequence Objects

Introduction

A Sequence object manages a set of Commands. The sequence is constructed on the host from a list of commands, then downloaded and executed in the controller. Typically, applications only use Sequences for very small or simple autonomous tasks that require execution in the controller. Due to their embedded execution, debugging can be difficult. It is best to use the host application to execute MPI methods directly for optimum flexibility and performance.

If you are considering using a program Sequencer or Command objects, please contact an MEI Applications Engineer. We recommend that you do NOT implement complex Sequences on your own.
Methods
Create, Delete, Validate Methods
 | mpiSequenceCreate | Create Sequence object
 | mpiSequenceDelete | Delete Sequence object
 | mpiSequenceValidate | Validate Sequence object

Configuration and Information Methods
 | mpiSequenceConfigGet | Get sequence config
 | mpiSequenceConfigSet | Set sequence config
 | mpiSequenceFlashConfigGet | Get sequence flash config
 | mpiSequenceFlashConfigSet | Set sequence flash config
 | mpiSequencePageSize | Set pageSize to number of command slots used by sequence
 | mpiSequenceStatus | Return sequence status

Event Methods
 | mpiSequenceEventNotifyGet | Select an event mask for host notification of events
 | mpiSequenceEventNotifySet | Enable host notification of sequence events
 | mpiSequenceEventReset | Reset sequence events

Action Methods
 | meiSequenceCompile |
 | mpiSequenceLoad | Load sequence commands into firmware
 | mpiSequenceResume | Resume execution of sequence
 | mpiSequenceStart | Start execution of sequence
 | mpiSequenceStep | Execute count steps of a stopped sequence
 | mpiSequenceStop | Stop sequence

Memory Methods
 | mpiSequenceMemory | Set address used to access sequence memory
 | mpiSequenceMemoryGet | Get bytes of sequence memory and put into application memory
 | mpiSequenceMemorySet | Put (set) bytes of application memory into sequence memory

Relational Methods
 | mpiSequenceControl | Get handle to Control
 | mpiSequenceNumber | Get index number of sequence
 | List Methods for Event Sources
 | mpiSequenceCommand | Return handle to indexed command of sequence
 | mpiSequenceCommandAppend | Append command to sequence
 | mpiSequenceCommandCount | Count the number of commands in sequence
 | mpiSequenceCommandFirst | Return handle to first command in sequence
 | mpiSequenceCommandIndex | Return the index of a command in sequence
 | mpiSequenceCommandInsert | Insert command into sequence
 | mpiSequenceCommandLast | Return handle of last command in sequence
 | mpiSequenceCommandListGet | Get list of commands in sequence
 | mpiSequenceCommandListSet | Set list of commands in sequence
 | mpiSequenceCommandNext | Get handle to next command in list
 | mpiSequenceCommandPrevious | Get handle to previous command in list
 | mpiSequenceCommandRemove | Remove command from list

Data Types
MPISequenceConfig / MEISequenceConfig
MPISequenceMessage
MPISequenceState
MPISequenceStatus
MEISequenceTrace


MPISequenceConfig and MEISequenceConfig

MPISequenceConfig / MEISequenceConfig

MPISequenceConfig

typedef MPIEmpty    MPISequenceConfig;
Description

SequenceConfig is currently not supported and is reserved for future use.

MEISequenceConfig

typedef MPIEmpty    MEISequenceConfig;
Description

SequenceConfig is currently not supported and is reserved for future use.

See Also | mpiSequenceConfigGet | mpiSequenceConfigSet


MPISequenceMessage

MPISequenceMessage

typedef enum {

    MPISequenceMessageSEQUENCE_INVALID,
    MPISequenceMessageCOMMAND_COUNT,
    MPISequenceMessageCOMMAND_NOT_FOUND,
    MPISequenceMessageSTARTED,
    MPISequenceMessageSTOPPED,
} MPISequenceMessage;

Description
 | MPISequenceMessageSEQUENCE_INVALID | An invalid sequence number has been specified or a disabled sequence object has been specified.
 | MPISequenceMessageCOMMAND_COUNT | The program sequencer's command count is 0.
 | MPISequenceMessageCOMMAND_NOT_FOUND | The program sequencer command is not a valid command.
 | MPISequenceMessageSTARTED | The program sequencer has already been started.
 | MPISequenceMessageSTOPPED | The program sequencer has already been stopped.
See Also


MPISequenceState

MPISequenceState

typedef enum {
    MPISequenceStateSTOPPED,
    MPISequenceStateSTARTED,
} MPISequenceState;

Description
 | MPISequenceStateSTOPPED | Means that the XMP's on-board program sequencer state is stopped. The program sequencer is in this state after it is created, and is not running. If the program sequencer has already been started, then a call to the MPI method mpiSequenceStop will stop the sequencer, and the sequencer state will be MPISequenceStateSTOPPED.
 | MPISequenceStateSTARTED | Means that the XMP's on-board program sequencer state is running. The program sequencer is in this state after it has been created, and successfully started with a call to the MPI method mpiSequenceStart.
See Also


MPISequenceStatus

MPISequenceStatus

typedef struct MPISequenceStatus {
    MPICommand		command;
    MPISequenceState	state;
} MPISequenceStatus;
Description

MPISequenceStatus is a status structure for MPISequence objects

command | The current command of the MPISequence object
state | The current state of the MPISequence object

See Also | MPISequence | mpiSequenceStatus


MEISequenceTrace

MEISequenceTrace

typedef enum {
    MEISequenceTraceLOAD,

} MEISequenceTrace;
Description

MPISequenceTrace sets tracing on for the mpiSequenceLoad() method.

See Also | MPISequence | MEITrace | mpiSequenceLoad


mpiSequenceConfigGet

Declaration
long mpiSequenceConfigGet(MPISequence sequence,
                          MPISequenceConfig *config,
                          void *external)
Required Header stdmpi.h
Description

SequenceConfigGet gets the configuration of a Sequence object (sequence) and writes it in the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Sequence’s configuration information in external is in addition to the Sequence’s configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEISequenceConfig{} or is NULL.
Return Values
MPIMessageOK if SequenceConfigGet successfully gets and writes the configuration of a Sequence object into the structure(s)
See Also | mpiSequenceConfigSet | MEISequenceConfig


mpiSequenceConfigSet

Declaration
long mpiSequenceConfigSet(MPISequence sequence,
                          MPISequenceConfig *config,
                          void *external)
Required Header stdmpi.h
Description

SequenceConfigSet sets the configuration of a Sequence (sequence) using data from the structure pointed to by config, and also using data from the implementation- specific structure pointed to by external (if external is not NULL).

The Sequence’s configuration information in external is in addition to the Sequence’s configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEISequenceConfig{} or is NULL.
Return Values
MPIMessageOK if SequenceConfigSet successfully sets a Sequence’s configuration using data from the structure(s)
See Also | mpiSequenceConfigGet | MEISequenceConfig


mpiSequenceCommand

Declaration
const MPICommand mpiSequenceCommand(MPISequence sequence,
                                    long        index)
Required Header stdmpi.h
Description

SequenceCommand returns the element at the position on the list indicated by index.

sequence | a handle to the Sequence object.
index | a position in the list.

Return Values
handle | to the indexth Command of a Sequence (sequence)
MPIHandleVOID | if sequence is invalid if index is less than 0 if index is greater than or equal to mpiSequenceCount(sequence)
MPIMessageARG_INVALID | if index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | if index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | if sequence is an invalid handle.
See Also


mpiSequenceCommandAppend

Declaration
long mpiSequenceCommandAppend(MPISequence sequence,
                              MPICommand  command)
Required Header stdmpi.h
Description

SequenceCommandAppend appends a Command (command) to a Sequence (sequence).

sequence | a handle to the Sequence object.
command | a handle to a Command object.

Return Values
MPIMessageOK | if SequenceCommandAppend successfully appends a Command to a Sequence
MPIMessageHANDLE_INVALID | Either sequence or command is an invalid handle.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiSequenceCommandCount

Declaration
long mpiSequenceCommandCount(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceCommandCount returns the number of elements on the list.

sequence | a handle to the Sequence object.

Return Values
number of Commands | in a Sequence (sequence)
-1 | if sequence is invalid
0 | if sequence is empty
See Also


mpiSequenceCommandFirst

Declaration
const MPICommand mpiSequenceCommandFirst(MPISequence  sequence)
Required Header stdmpi.h
Description

SequenceCommandFirst returns the first element in the list. This function can be used in conjuntion with mpiSequenceCommandNext() in order to iterate through the list.

sequence | a handle to the Sequence object.

Return Values
handle | to the first Command in a Sequence (sequence)
MPIHandleVOID | if sequence is invalid if sequence is empty
MPIMessageHANDLE_INVALID | if sequence is an invalid handle.

See Also | mpiSequenceCommandNext | mpiSequenceCommandLast


mpiSequenceCommandInsert

Declaration
long mpiSequenceCommandInsert(MPISequence sequence,
                              MPICommand  command,
                              MPICommand  insert)
Required Header stdmpi.h
Description

SequenceCommandInsert inserts a Command (insert) in a Sequence (sequence) just after the specified Command (command).

Return Values
MPIMessageOK if SequenceCommandInsert successfully inserts the Command (insert) in a Sequence following the specified Command (command)
See Also


mpiSequenceCommandIndex

Declaration
long mpiSequenceCommandIndex(MPISequence  sequence,
                             MPICommand   command)
Required Header stdmpi.h
Description

SequenceCommandIndex returns the position of "command" on the list.

sequence | a handle to the Sequence object.
command | a handle to a Command object.

Return Values
index | of a Command (command) in a Sequence (sequence)
-1 | if sequence is invalid if the Command (command) was not found in the Sequence (sequence)
See Also


mpiSequenceCommandLast

Declaration
const MPICommand mpiSequenceCommandLast(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceCommandLast returns the last element in the list. This function can be used in conjuntion with mpiSequenceCommandPrevious() in order to iterate through the list backwards.

sequence | a handle to the Sequence object.

Return Values
handle | to the last Command in a Sequence (sequence)
MPIHandleVOID | if sequence is invalid if sequence is empty
MPIMessageHANDLE_INVALID | if sequence is an invalid handle.

See Also | mpiSequenceCommandFirst | mpiSequenceCommandPrevious | mpiSequenceCommandNext


mpiSequenceCommandListGet

Declaration
long mpiSequenceCommandListGet(MPISequence  sequence,
                               long         *commandCount,
                               MPICommand   *commandList)
Required Header stdmpi.h
Description

SequenceCommandListGet gets the Commands in a Sequence (sequence). SequenceCommandListGet writes the number of Commands [in a Sequence (sequence)] to the location (pointed to by commandCount), and also writes an array (of commandCount Command handles) to the location (pointed to by commandList).
Return Values
MPIMessageOK if SequenceCommandListGet successfully gets the list of Commands in a Sequence
See Also | mpiSequenceCommandListSet


mpiSequenceCommandListSet

Declaration
long mpiSequenceCommandListSet(MPISequence  sequence,
                               long         commandCount,
                               MPICommand   *commandList)
Required Header stdmpi.h
Description

SequenceCommandListSet creates a Sequence (sequence) of commandCount Commands using the Command handles specified by commandList. Any existing command Sequence is completely replaced.

The commandList parameter is the address of an array of commandCount Command handles, or is NULL (if commandCount is equal to zero).

You can also create a command Sequence incrementally (i.e., one command at a time), by using the Append and/or Insert methods. Use the List methods to examine and manipulate a command Sequence, regardless of how it was created.

Return Values
MPIMessageOK if SequenceCommandListGet successfully creates a Sequence of Commands using the Command handles specified by commandList
See Also | mpiSequenceCommandListGet


mpiSequenceCommandNext

Declaration
const MPICommand mpiSequenceCommandNext(MPISequence sequence,
                                        MPICommand  command)
Required Header stdmpi.h
Description

SequenceCommandNext returns the next element following "command" on the list. This function can be used in conjuntion with mpiSequenceCommandFirst() in order to iterate through the list.

sequence | a handle to the Sequence object.
command | a handle to a Command object.

Return Values
handle | to the Command following the Command (command) in a Sequence (sequence)
MPIHandleVOID | if sequence is invalid if command is the last command in a Sequence (sequence)
MPIMessageHANDLE_INVALID | Either sequence or command is an invalid handle.

See Also | mpiSequenceCommandFirst | mpiSequenceCommandPrevious


mpiSequenceCommandPrevious

Declaration
const MPICommand mpiSequenceCommandPrevious(MPISequence sequence,
                                            MPICommand  command)
Required Header stdmpi.h
Description

SequenceCommandPrevious returns the previous element prior to "command" on the list. This function can be used in conjuntion with mpiSequenceCommandLast() in order to iterate through the list backwards.

sequence | a handle to the Sequence object.
command | a handle to a Command object.

Return Values
handle | to the Command preceding the Command (command) in a Sequence (sequence)
MPIHandleVOID | if sequence is invalid if command is the first command in a Sequence (sequence)
MPIMessageHANDLE_INVALID | Either sequence or command is an invalid handle.

See Also | mpiSequenceCommandLast | mpiSequenceCommandNext


mpiSequenceCommandRemove

Declaration
long mpiSequenceCommandRemove(MPISequence sequence,
                              MPICommand  command)
Required Header stdmpi.h
Description

SequenceCommandRemove removes a Command (command) from a Sequence (sequence).
Return Values
MPIMessageOK if SequenceCommandRemove successfully removes the Command from a Sequence
See Also


mpiSequenceControl

Declaration
const MPIControl mpiSequenceControl(MPISequence sequence)
Required Header stdmpi.h
Description SequenceControl returns a handle to the Control object with which the Sequence object is associated.
sequence | a handle to the Sequence object.

Return Values
MPIControl | a handle to the Sequence object
MPIHandleVOID | if sequence is invalid

See Also | mpiSequenceCreate | mpiControlCreate


meiSequenceCompile

Declaration
long meiSequenceCompile(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceCompile “compiles” a sequence object by reading its list of Command objects and then creating an equivalent list of XMP commands.

Return Values
MPIMessageOK if SequenceCompile successfully reads a Sequence object’s list of Command objects and creates an equivalent list of XMP commands
See Also


mpiSequenceCreate

Declaration
const MPISequence mpiSequenceCreate(MPIControl control,
                                    long       number,
                                    long       pageSize)
Required Header stdmpi.h
Description

SequenceCreate creates a Sequence object associated with the program sequencer identified by number located on motion controller (control). SequenceCreate is the equivalent of a C++ constructor.

If | Then
number is -1 | SequenceCreate selects the next unused program sequencer. If this is the first use of the program sequencer, then SequenceCreate will attempt to allocate pageSize firmware command slots.
pageSize is -1 | SequenceCreate will allocate all remaining firmware command slots, which may prevent any more Sequence objects from being created.

Return Values
handle | to a Sequence object
MPIHandleVOID | if the object could not be created

See Also | mpiSequenceDelete | mpiSequenceValidate


mpiSequenceDelete

Declaration
long mpiSequenceDelete(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceDelete deletes a Sequence object and invalidates its handle (sequence). SequenceDelete is the equivalent of a C++ destructor.

All Command objects in a Sequence are deleted when the Sequence object is deleted.
Return Values
MPIMessageOK if SequenceDelete successfully a Sequence object and invalidates its handle
See Also | mpiSequenceCreate | mpiSequenceValidate


mpiSequenceEventNotifyGet

Declaration
long mpiSequenceEventNotifyGet(MPISequence   sequence,
                               MPIEventMask  *eventMask,
                               void          *external)
Required Header stdmpi.h
Description

SequenceEventNotifyGet writes an event mask [that specifies the event types (generated by the Sequence sequence, for which host notification has been requested] to the structure pointed to by eventMask, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The event mask information in external is in addition to the event mask information in eventMask, i.e, the event mask information in eventMask and in external is not the same information. Note that eventMask or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEIEventMask{} or is NULL.
Return Values
MPIMessageOK if SequenceEventNotifyGet successfully writes the event mask to the structure(s)
See Also | MEIEventMask | mpiSequenceEventNotifySet


mpiSequenceEventNotifySet

Declaration
long mpiSequenceEventNotifySet(MPISequence   sequence,
                               MPIEventMask  eventMask,
                               void          *external)
Required Header stdmpi.h
Description

SequenceEventNotifySet requests host notification of the event(s) specified by eventMask and generated by a Sequence (sequence), and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The event mask information in external is in addition to the event mask information in eventMask, i.e, the event mask information in eventMask and in external is not the same information. Note that eventMask or external can be NULL (but not both NULL).

The mask of event types generated by a Sequence object consists of MPIEventMaskEXTERNAL. When a Sequence issues a Command of type MPICommandTypeEVENT, an event of type MPIEventTypeEXTERNAL is generated. The only event generated by a Sequence is MPIEventTypeEXTERNAL, which is generated when a Sequence issues a Command of type MPICommandTypeEVENT.

To | Use "eventMask"
Disable host notification of all Sequence events | MPIEventTypeNONE
Enable host notification of all Sequence events | MPIEventMaskALL
XMP Only

external either points to a structure of type MEIEventMask{} or is NULL.
Return Values
MPIMessageOK if SequenceEventNotifySet successfully requests host notification of the events in the event mask(s)
See Also | MPIEventMaskEXTERNAL | MEIEventMask | mpiSequenceEventNotifyGet


mpiSequenceEventReset

Declaration
long mpiSequenceEventReset(MPISequence  sequence,
                           MPIEventMask eventMask)
Required Header stdmpi.h
Description

SequenceEventReset resets the event(s) that are specified in eventMask and generated by a Sequence (sequence). Your application should not call SequenceEventReset until one or more latchable events have occurred.

Return Values
MPIMessageOK if SequenceEventReset successfully resets the event(s) that are specified in eventMask and generated by a Sequence object
See Also


mpiSequenceFlashConfigGet

Declaration
long mpiSequenceFlashConfigGet(MPISequence       sequence,
                               void              *flash,
                               MPISequenceConfig *config,
                               void              *external)
Required Header stdmpi.h
Description

SequenceFlashConfigGet gets a Sequence’s (sequence) flash configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The Sequence’s flash configuration information in external is in addition to the Sequence’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL). The implementation-specific flash argument is used to access flash memory.
XMP Only

external either points to a structure of type MEISequenceConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.

Return Values
MPIMessageOK if SequenceFlashConfigGet successfully writes the Sequence’s flash configuration to the structure(s)
See Also | mpiSequenceFlashConfigSet


mpiSequenceFlashConfigSet

Declaration
long mpiSequenceFlashConfigSet(MPISequence       sequence,
                               void              *flash,
                               MPISequenceConfig *config,
                               void              *external)
Required Header stdmpi.h
Description

SequenceFlashConfigSet sets a Sequence’s (sequence) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Sequence’s flash configuration information in external is in addition to the Sequence’s flash configuration information in config, i.e., the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL). The implementation-specific flash argument is used to access flash memory.

XMP Only

external either points to a structure of type MEISequenceConfig{} or is NULL. flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
Return Values
MPIMessageOK if SequenceFlashConfigSet successfully sets the Sequence’s flash configuration using data from the structure(s)
See Also | MEISequenceConfig | mpiSequenceFlashConfigGet


mpiSequenceLoad

Declaration
long mpiSequenceLoad(MPISequence sequence,
                     MPICommand  command,
                     long        start)
Required Header stdmpi.h
Description

SequenceLoad loads the firmware command slots of a Sequence (sequence) as necessary, starting with the Command (command).

SequenceLoad is intended to be called initially by mpiSequenceStart(...) and called thereafter by mpiEventMgrService(...) (in response to reception of an internal page fault event notification from the firmware). Except when you are debugging a sequence via mpiSequenceStep(...), your application should never need to directly call SequenceLoad.

If | Then
command is MPIHandleVOID | SequenceLoad loads Commands starting with the first Command of the Sequence
start is not FALSE | SequenceLoad starts the sequence after the commands are loaded
Return Values
MPIMessageOK if SequenceLoad successfully loads the firmware command slots of a Sequence
See Also | mpiSequenceStart | mpiEventMgrService | mpiSequenceStep


mpiSequenceMemory

Declaration
long mpiSequenceMemory(MPISequence sequence,
                       void        **memory)
Required Header stdmpi.h
Description SequenceMemory writes an address [used to access a Sequence’s (sequence) memory] to the contents of memory. This address (or an address calculated from it) is passed as the src argument to mpiSequenceMemoryGet(...) and as the dst argument to mpiSequenceMemorySet(...).
Return Values
MPIMessageOK if SequenceMemory successfully writes the address (used to access Sequence memory) to the contents of memory
See Also | mpiSequenceMemoryGet | mpiSequenceMemorySet


mpiSequenceMemoryGet

Declaration
long mpiSequenceMemoryGet(MPISequence sequence,
                          void        *dst,
                          void        *src,
                          long        count)
Required Header stdmpi.h
Description SequenceMemoryGet copies count bytes of a Sequence’s (sequence) memory (starting at address src) to application memory (starting at address dst).
Return Values
MPIMessageOK if SequenceMemoryGet successfully copies count bytes of Sequence memory to application memory
See Also | mpiSequenceMemorySet | mpiSequenceMemory


mpiSequenceMemorySet

Declaration
long mpiSequenceMemorySet(MPISequence sequence,
                          void        *dst,
                          void        *src,
                          long        count)
Required Header stdmpi.h
Description

SequenceMemorySet copies count bytes of application memory (starting at address src) to a Sequence’s (sequence) memory (starting at address dst).

Return Values
MPIMessageOK if SequenceMemorySet successfully copies count bytes of application memory to a Sequence object’s memory
See Also | mpiSequenceMemory | mpiSequenceMemoryGet


mpiSequenceNumber

Declaration
long mpiSequenceNumber(MPISequence sequence,
                       long        *number)
Required Header stdmpi.h
Description

SequenceNumber writes the index of a Sequence (sequence, on the motion controller that the Sequence object is associated with) to the contents of number.

Return Values
MPIMessageOK if SequenceNumber successfully writes the Sequence’s index to the contents of number
See Also


mpiSequencePageSize

Declaration
long mpiSequencePageSize(MPISequence sequence,
                         long        *pageSize)
Required Header stdmpi.h
Description

SequencePageSize writes the number of command slots that are available to a Sequence (sequence, on its associated motion controller) to the contents of pageSize.
Return Values
MPIMessageOK if SequencePageSize successfully writes the number of command slots (available to the Sequence) to the contents of pageSize
See Also


mpiSequenceResume

Declaration
long mpiSequenceResume(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceResume resumes a Sequence (sequence) from the point where the Sequence has stopped (if execution has been stopped).
Return Values
MPIMessageOK if SequenceResume successfully resumes a Sequence from the point where the Sequence has stopped
See Also


mpiSequenceStep

Declaration
long mpiSequenceStep(MPISequence sequence,
                     long        count)
Required Header stdmpi.h
Description

SequenceStep executes count steps (Commands) of a stopped Sequence (sequence). After executing the Commands, the Sequence will be in the MPISequenceStateSTOPPED state.
Return Values
MPIMessageOK if SequenceStep successfully executes count steps (Commands) of a stopped Sequence
See Also


mpiSequenceStop

Declaration
long mpiSequenceStop(MPISequence sequence)
Required Header stdmpi.h
Description

SequenceStop stops a Sequence (sequence), if execution has been started. A stopped Sequence can be resumed from the point where it has stopped.
Return Values
MPIMessageOK if SequenceStop successfully stops a Sequence (while it is executing)
See Also | mpiSequenceStart


mpiSequenceStart

Declaration
long mpiSequenceStart(MPISequence sequence,
                      MPICommand  command)
Required Header stdmpi.h
Description

SequenceStart begins the execution of a Sequence (sequence), starting with the Command (command). If command is MPIHandleVOID, execution starts with the first command of the Sequence.
Return Values
MPIMessageOK if SequenceStart successfully begins the execution of a Command Sequence
See Also | mpiSequenceStop


mpiSequenceStatus

Declaration
long mpiSequenceStatus(MPISequence       sequence,
                       MPISequenceStatus *status,
                       void              *external)
Required Header stdmpi.h
Description

SequenceStatus returns the status of a Sequence (sequence), and writes it into the structure pointed to by status, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The status information in external is in addition to the status information in status, i.e, the status information in status and in external is not the same information. Note that status or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEISequenceStatus{} or is NULL.

Return Values
MPIMessageOK if SequenceStatus successfully returns the Sequence’s status and writes the status to the structure(s)
See Also | MPISequenceStatus


mpiSequenceValidate

Declaration
long mpiSequenceValidate(MPISequence sequence)
Required Header stdmpi.h
Description SequenceValidate validates the Sequence object and its handle (sequence).
Return Values
MPIMessageOK if Sequence is a handle to a valid object.
See Also | mpiSequenceCreate | mpiSequenceDelete


Sercos Objects

Introduction

A Sercos object manages an individual SERCOS master.

The SERCOS (Serial Real-Time Communication System) protocol was designed specifically for the motion control industry. The protocol uses a ring topology which allows communication to occur at specific assigned times within a predetermined cycle. Thus, SERCOS is deterministic allowing the Master (control unit) to synchronize command and feedback values to and from all of the Slaves (drives).

The MPI supports the use of SERCOS fiberoptic technology. The XMP-SERCOS-CPCI supports up to 3 SERCOS rings with support for up to 24 drives, in a 2-slot configuration in a CompactPCI form-factor. The MPI includes 4 SERCOS object types: SERCOS, NODE, IDN, and IDNLIST. Utility programs for initializing a ring and reading or writing IDNs are also provided with the software distribution.

Only a limited number of SERCOS drive manufacturers are supported in the MPI. For a list of supported drives, click here. Contact MEI for more information about supported SERCOS drives.

Introduction | Overview | Data Types | Communications
Procedures | Telegrams | Topologies
Methods
Create, Delete, Validate Methods
 | mpiSercosCreate | Create Sercos object
 | mpiSercosDelete | Delete Sercos object
 | mpiSercosValidate | Validate Sercos object

Configuration and Information Methods
 | mpiSercosConfigGet | Get Sercos object’s configuration
 | mpiSercosConfigSet | Set Sercos object’s configuration
 | mpiSercosError | Set contents of error with platform-specific info (about the error)
 | mpiSercosFlashConfigGet | Get flash config of Sercos
 | mpiSercosFlashConfigSet | Set flash config of Sercos
 | meiSercosServiceIdnFieldGet |
 | meiSercosServiceIdnFieldSet |
 | meiSercosServiceProcedure |
 | mpiSercosStatus / meiSercosStatus | Get the status of a Sercos object

Action Methods
 | mpiSercosInit | Initialize a Sercos object to a specified SERCOS phase
 | mpiSercosReset | Reset a Sercos object to SERCOS Phase 0

Memory Methods
 | mpiSercosMemory | Set Sercos memory address
 | mpiSercosMemoryGet | Copy bytes of Sercos memory to application memory
 | mpiSercosMemorySet | Copy bytes of application memory to Sercos memory

Relational Methods
 | mpiSercosControl | Get handle to Control object that a Sercos object is associated with
 | mpiSercosNumber | Get the index of a Sercos object from the Control object that the Sercos object is associated with
 | List Methods for Sercos Nodes
 | mpiSercosNode | Get handle to the indexth Node in a Sercos object’s list
 | mpiSercosNodeAppend | Append a Node object to a Sercos object’s list
 | mpiSercosNodeCount | Get the number of Node objects in a Sercos object’s list
 | mpiSercosNodeFirst | Get handle to the first Node in a Sercos object’s list
 | mpiSercosNodeIndex | Get the index of a Node object in a Sercos object’s list
 | mpiSercosNodeInsert | Insert a Node into a Sercos object’s list
 | mpiSercosNodeLast | Get handle to the last Node in a Sercos object’s list
 | mpiSercosNodeListGet | Get the list of Nodes associated with a Sercos object
 | mpiSercosNodeListSet | Create a list of Nodes associated with a Sercos object
 | mpiSercosNodeNext | Get handle to the next Node in a Sercos object’s list
 | mpiSercosNodePrevious | Get handle to the previous Node in a Sercos object’s list
 | mpiSercosNodeRemove | Remove a Node from a Sercos object’s list
Data Types
MPISercosBaud
MPISercosError
MPISercosErrorGroup
MPISercosErrorType
MPISercosLoopStatus
MPISercosMessage / MEISercosMessage
MPISercosProcedureAction
MEISercosServiceContainer
MPISercosStatus
Constants
MPISercosNODE_COUNT_MAX
Macros
mpiSercosNodeIdnDataSET
mpiSercosNodeIdnGET


SERCOS Communication Error Notification

If your motion controller uses SERCOS, you can take advantage of specialized status information. The MPIStatusMask in the MPIStatus structure makes it possible to read the MPIStatusFlag(s):

/* MPIStatus */
typedef enum {
    MPIStatusFlagINVALID,
    MPIStatusFlagCOMM_ERROR,
} MPIStatusFlag;

#define	mpiStatusMaskBIT(flag)    (0x1 << (flag))

typedef enum {
    MPIStatusMaskNONE         = 0x0,
    MPIStatusMaskCOMM_ERROR   = mpiStatusMaskBIT(MPIStatusFlagCOMM_ERROR),  /* 0x00000001 */
    MPIStatusMaskMOTOR        = MPIStatusMaskCOMM_ERROR,                    /* 0x00000001 */
    MPIStatusMaskALL          = mpiStatusMaskBIT(MPIStatusFlagLAST) - 1	    /* 0x00000001 */
} MPIStatusMask;

typedef struct MPIStatus {
    MPIState        state;
    MPIAction       action;
    MPIEventMask    eventMask;

    long     settled;
    long     atTarget;

    MPIStatusMask     statusMask;
} MPIStatus;

Presently, the only MPIStatusFlag supported is MPIStatusFlagCOMM_ERROR. This flag represents the communication status. For XMP-Series SERCOS controllers, this flag represents the status of the SERCOS communication. When the SERCOS communication ring fails, the MPIStatusFlagCOMM_ERROR is set. The flag can only be cleared by re-initializating the SERCOS ring with mpiSercosInit(...).

Return to Sercos Objects page


MPISercosBaud

MPISercosBaud

typedef enum {
    MPISercosBaudINVALID,

    MPISercosBaud2MBIT,
    MPISercosBaud4MBIT,
    MPISercosBaud10MBIT,

} MPISercosBaud;
Description

SercosBaud defines the different baud rates that the SERCOS ring can communicate at.

See Also


MPISercosError

MPISercosError

typedef enum {
    MPISercosErrorSHIFT,

    MPISercosErrorGENERAL,
    MPISercosErrorNONE,
    MPISercosErrorCHANNEL_NOT_OPEN,
    MPISercosErrorCHANNEL_ACCESS,

    MPISercosErrorIDN,
    MPISercosErrorNO_IDN,
    MPISercosErrorIDN_ACCESS,

    MPISercosErrorNAME,
    MPISercosErrorNO_NAME,
    MPISercosErrorNAME_TOO_SHORT,
    MPISercosErrorNAME_TOO_LONG,
    MPISercosErrorNAME_NO_CHANGE,
    MPISercosErrorNAME_WRITE_PROTECT,

    MPISercosErrorATTR,
    MPISercosErrorATTR_TOO_SHORT,
    MPISercosErrorATTR_TOO_LONG,
    MPISercosErrorATTR_NO_CHANGE,
    MPISercosErrorATTR_WRITE_PROTECT,

    MPISercosErrorUNIT,
    MPISercosErrorNO_UNIT,
    MPISercosErrorUNIT_TOO_SHORT,
    MPISercosErrorUNIT_TOO_LONG,
    MPISercosErrorUNIT_NO_CHANGE,
    MPISercosErrorUNIT_WRITE_PROTECT,

    MPISercosErrorMIN,
    MPISercosErrorNO_MIN,
    MPISercosErrorMIN_TOO_SHORT,
    MPISercosErrorMIN_TOO_LONG,
    MPISercosErrorMIN_NO_CHANGE,
    MPISercosErrorMIN_WRITE_PROTECT,

    MPISercosErrorMAX,
    MPISercosErrorNO_MAX,
    MPISercosErrorMAX_TOO_SHORT,
    MPISercosErrorMAX_TOO_LONG,
    MPISercosErrorMAX_NO_CHANGE,
    MPISercosErrorMAX_WRITE_PROTECT,

    MPISercosErrorOP,
    MPISercosErrorOP_TOO_SHORT,
    MPISercosErrorOP_TOO_LONG,
    MPISercosErrorOP_NO_CHANGE,
    MPISercosErrorOP_WRITE_PROTECT,
    MPISercosErrorOP_MIN,
    MPISercosErrorOP_MAX,
    MPISercosErrorOP_DATA,
    MPISercosErrorOP_PASSWORD,
} MPISercosError;
Description

The SercosError enumeration defines all the different errors that can occur in SERCOS.

See Also | For a more in-depth breakdown of the errors, please refer to a SERCOS Specification Manual.


MPISercosErrorGroup

MPISercosErrorGroup

typedef enum {
    MPISercosErrorGroupINVALID,

    MPISercosErrorGroupGENERAL,
    MPISercosErrorGroupIDN,
    MPISercosErrorGroupNAME,
    MPISercosErrorGroupATTR,
    MPISercosErrorGroupUNIT,
    MPISercosErrorGroupMIN,
    MPISercosErrorGroupMAX,
    MPISercosErrorGroupOP,

} MPISercosErrorGroup;
Description

When an error occurs, SercosErrorGroup defines what part of the IDN field has the error.
See Also


MPISercosErrorType

MPISercosErrorType

typedef enum {
    MPISercosErrorTypeNONE,
    MPISercosErrorTypeDOES_NOT_EXIST,
    MPISercosErrorTypeTOO_SHORT,
    MPISercosErrorTypeTOO_LONG,
    MPISercosErrorTypeNO_CHANGE,
    MPISercosErrorTypeWRITE_PROTECT,
    MPISercosErrorTypeTOO_SMALL,
    MPISercosErrorTypeTOO_BIG,
    MPISercosErrorTypeINVALID_DATA,
    MPISercosErrorTypeINVALID_ACCESS,
    MPISercosErrorTypePASSWORD_PROTECT,
} MPISercosErrorType;
Description

SercosErrorType enumeration contains basic SERCOS error types that are ORed into the MPISercosErrorGroup enumeration to construct unique MPISercosError codes.

MPISercosErrorTypeNONE | This error type indicates no error occurred.
MPISercosErrorTypeDOES_NOT_EXIST | This error type indicates that a service channel is not open, an idn does not exist or an idn element does not exist.
MPISercosErrorTypeTOO_SHORT | This error type indicates an idn element is too short.
MPISercosErrorTypeTOO_LONG | This error type indicates an idn element is too long.
MPISercosErrorTypeNO_CHANGE | This error type indicates an idn element cannot be changed.
MPISercosErrorTypeWRITE_PROTECT | This error type indicates an idn element is read only.
MPISercosErrorTypeTOO_SMALL | This error type indicates the idn operation data is too small.
MPISercosErrorTypeTOO_BIG | This error type indicates the idn operation data is too big.
MPISercosErrorTypeINVALID_DATA | This error type indicates the idn operation data is not valid.
MPISercosErrorTypeINVALID_ACCESS | This error type indicates a service channel is not accessible or an idn is not accessible.
MPISercosErrorTypePASSWORD_PROTECT | This error type indicates the idn operation data is password protected.

See Also | MPISercosError


MPISercosLoopStatus

MPISercosLoopStatus

typedef enum {
     MPISercosLoopStatusOPEN,
} MPISercosLoopStatus;
Description

SercosLoopStatus defines the status of a SERCOS loop.
See Also


MPISercosMessage and MEISercosMessage

MPISercosMessage / MEISercosMessage

MPISercosMessage

typedef enum {

    MPISercosMessageSERCOS_INVALID,
    MPISercosMessageHANDSHAKE_TIMEOUT,
    MPISercosMessageIDN_FIELD_INVALID,
    MPISercosMessageMST_RECEIVE_ERROR,
    MPISercosMessageNODE_NOT_FOUND,
    MPISercosMessagePROCEDURE_DATA_INVALID,
    MPISercosMessagePROCEDURE_ERROR,
    MPISercosMessagePROTOCOL_ERROR,
    MPISercosMessageRING_NOT_CLOSED,
    MPISercosMessageSAMPLE_RATE_INVALID,
    MPISercosMessageSERVICE_CHANNEL_BUSY,
    MPISercosMessageSERVICE_CHANNEL_ERROR,
    MPISercosMessagePROCEDURE_TIMEOUT,
    MPISercosMessageM_BUSY_TIMEOUT,
} MPISercosMessage;

Description
 | MPISercosMessageSERCOS_INVALID
 | Meaning | The specified SERCOS ring is not valid.
 | Possible Causes | A number passed to MPISercosCreate( ) is larger than the maximum allowable number of Sercos objects.
 | Recommendations | If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessageHANDSHAKE_TIMEOUT
 | Meaning | A timeout has occurred during a SERCOS service container operation.
 | Possible Causes | If there is some sort of communication error, the handshaking will probably not be synchronized, and a timeout will occur.
 | Recommendations | If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessageIDN_FIELD_INVALID
 | Meaning | A user is trying to read an IDN field that does not exist.
 | Possible Causes | This error occurs when the user is trying to read the Min or Max IDN field on an IDN whose data is Variable.
 | Recommendations | If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessageMST_RECEIVE_ERROR
 | Meaning | .The wrong data type is being used to access an IDN field.
 | Possible Causes | This error occurs when the user is trying to read the Min or Max IDN field on an IDN whose data is Variable.
 | Recommendations | .If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessageNODE_NOT_FOUND
 | Meaning | The specified Node number is invalid.
 | Possible Causes | In the phase 2 transition, if a Node in the Sercos ring has a node number that is greater than the MEIXmpSercosNodeCountMAX, this error will occur.
 | Recommendations | .If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessagePROCEDURE_DATA_INVALID
 | Meaning | The wrong data type is being used to access an IDN field.
 | Possible Causes | This error occurs when the user is trying to read the Min or Max IDN field on an IDN whose data is Variable.
 | Recommendations | .If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.
 | MPISercosMessageMST_RECEIVE_ERROR
 | Meaning | The wrong data type is being used to access an IDN field.
 | Possible Causes | This error occurs when the user is trying to read the Min or Max IDN field on an IDN whose data is Variable.
 | Recommendations | .If you are receiving this error message, then please contact an applications engineer at Motion Engineering, Inc.

MEISercosMessage

typedef enum {
    MEISercosMessage    BUFFER_SIZE_ERROR,
} MEISercosMessage;

Description
 | MEISercosMessageBUFFER_SIZE_ERROR
 | Meaning | There is no memory allocated for a given SERCOS object.
 | Possible Causes | When mpiSercosValidate() is called and the firmware does not have any space allocated for SERCOS.
 | Recommendations | Make sure the controller has been configured for SERCOS.
See Also


MPISercosNODE_COUNT_MAX

MPISercosNODE_COUNT_MAX

#define	 MPISercosNODE_COUNT_MAX    (32)
Description

SercosNODE_COUNT_MAX defines the maximum number of Nodes that can be on a SERCOS ring.
See Also


MPISercosProcedureAction

MPISercosProcedureAction

typedef enum {
    MPISercosProcedureActionINVALID,

    MPISercosProcedureActionCLEAR_AND_START,
    MPISercosProcedureActionSTART,
    MPISercosProcedureActionCANCEL,
    MPISercosProcedureActionSTATUS,
    MPISercosProcedureActionCLEAR_AND_EXECUTE,
    MPISercosProcedureActionEXECUTE,
    MPISercosProcedureActionNONE,

} MPISercosProcedureAction;
Description

SercosProcedureAction lists all of the different commands that can be applied to a SERCOS procedure.
See Also


MEISercosServiceContainer

MEISercosServiceContainer

typedef struct MEISercosServiceContainer {
    unsigned long	header[5];

    unsigned long	write[20];
    unsigned long	read[20];
    unsigned long	readOverhang;
} MEISercosServiceContainer;
Description

SercosServiceContainer is part of the Sercos message where noncyclic data is requested and sent. It resides in both the AT and MDT.

See Also | For a definition of the individual fields, consult a SERCOS specification manual.


MPISercosStatus

MPISercosStatus

typedef struct MPISercosStatus {
    MPISercosLoopStatus	 loopStatus;
    long                 phase;
    long                 nodeCount;
} MPISercosStatus;
Description

SercosStatus gives the status of the SERCOS ring.

loopStatus | the current state of the ring (ie open or closed)
phase | the phase in which the SERCOS ring is in [0-4]
nodeCount | the number of nodes on the SERCOS ring
See Also


mpiSercosConfigGet

Declaration
long mpiSercosConfigGet(MPISercos       sercos,
                        MPISercosConfig *config,
                        void            *external)
Required Header stdmpi.h
Description

SercosConfigGet gets a Sercos object’s (sercos) configuration and writes it into the structure pointed to by config, and also writes it into the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).

XMP Only

external either points to a structure of type MEISercosConfig{} or is NULL.

Return Values
MPIMessageOK if SercosConfigGet successfully writes the Sercos object’s configuration to the structure(s)
See Also | mpiSercosConfigSet


mpiSercosConfigSet

Declaration
long mpiSercosConfigSet(MPISercos       sercos,
                        MPISercosConfig *config,
                        void            *external)
Required Header stdmpi.h
Description

SercosConfigSet sets a Sercos object’s (sercos) configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The configuration information in external is in addition to the configuration information in config, i.e, the configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEISercosConfig{} or is NULL.

Return Values
MPIMessageOK if SercosConfigSet successfully sets the Sercos object’s configuration using data from the structure(s)
See Also | mpiSercosConfigGet


mpiSercosControl

Declaration
const MPIControl mpiSercosControl(MPISercos sercos)
Required Header stdmpi.h
Description

SercosControl returns a handle to the Control object with which the Sercos object is associated.

sercos | a handle to the Sercos object

Return Values
handle | to the Control object that a Sercos object (sercos) is associated with
MPIHandleVOID | if sercos is invalid

See Also | mpiSercosCreate | mpiControlCreate


mpiSercosCreate

Declaration
const MPISercos mpiSercosCreate(MPIControl control,
                                long       number)
Required Header stdmpi.h
Description

SercosCreate creates a Sercos object that is associated with the SERCON 410B chip, which in turn is identified by number on a motion controller (control). SercosCreate is the equivalent of a C++ constructor.

Return Values
handle | to a Sercos object (associated with number and control)
MPIHandleVOID | if the object could not be created

See Also | mpiSercosDelete | mpiSercosValidate


mpiSercosDelete

Declaration
long mpiSercosDelete(MPISercos sercos)
Required Header stdmpi.h
Description

SercosDelete deletes a Sercos object and invalidates its handle (sercos). SercosDelete is the equivalent of a C++ destructor.
Return Values
MPIMessageOK if SercosDelete successfully deletes the Sercos object and invalidates its handle
See Also | mpiSercosCreate | mpiSercosValidate


mpiSercosError

Declaration
long mpiSercosError(MPISercos      sercos,
                    MPISercosError *error)
Required Header stdmpi.h
Description

SercosError reads the error code from a Sercos object and writes it into the location pointed to by error.

sercos | a handle to a Sercos object
*error | a pointer to a MPISercosError
Return Values
MPIMessageOK if mpiSercosError successfully writes the current sercos error to error.
See Also


mpiSercosFlashConfigGet

Declaration
long mpiSercosFlashConfigGet(MPISercos       sercos,
                             void            *flash,
                             MPISercosConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

SercosFlashConfigGet gets a Sercos object’s (sercos) flash configuration and writes it in the structure pointed to by config, and also writes it in the implementation-specific structure pointed to by external (if external is not NULL).

The Sercos object’s flash configuration information in external is in addition to the Sercos object’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEISercosConfig{} or is NULL.
Return Values
MPIMessageOK if SercosFlashConfigGet successfully writes the Sercos object’s flash configuration to the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiSercosFlashConfigSet


mpiSercosFlashConfigSet

Declaration
long mpiSercosFlashConfigSet(MPISercos       sercos,
                             void            *flash,
                             MPISercosConfig *config,
                             void            *external)
Required Header stdmpi.h
Description

SercosFlashConfigSet sets a Sercos object’s (sercos) flash configuration using data from the structure pointed to by config, and also using data from the implementation-specific structure pointed to by external (if external is not NULL).

The Sercos object’s flash configuration information in external is in addition to the Sercos object’s flash configuration information in config, i.e, the flash configuration information in config and in external is not the same information. Note that config or external can be NULL (but not both NULL).
XMP Only

external either points to a structure of type MEISercosConfig{} or is NULL.

Return Values
MPIMessageOK if SercosFlashConfigSet successfully sets the Sercos object’s flash configuration using data from the structure(s)
flash is either an MEIFlash handle or MPIHandleVOID. If flash is MPIHandleVOID, an MEIFlash object will be created and deleted internally.
See Also | MEIFlash | mpiSercosFlashConfigGet


mpiSercosInit

Declaration
long mpiSercosInit(MPISercos sercos,
                   long      phase)
Required Header stdmpi.h
Description

SercosInit advances the initialization of a Sercos object (sercos) to a specific phase (phase).

If phase = -1, then the Sercos object is moved to Phase 4 (full initialization). If the current phase number (of the Sercos object) is greater than phase, initialization restarts at Phase 0 and advances to Phase phase.
Return Values
MPIMessageOK if SercosInit successfully initializes the state of a Sercos object (sercos) to the Phase phase
See Also


mpiSercosMemory

Declaration
long mpiSercosMemory(MPISercos sercos,
                     void      **memory)
Required Header stdmpi.h
Description

SercosMemory writes an address [that is used to access Sercos (sercos) memory] to the contents of memory. This address (or an address calculated from it) is passed as the src argument to mpiSercosMemoryGet(...) and as the dst argument to mpiSercosMemorySet(...).

Return Values
MPIMessageOK if SercosMemory successfully writes the Sercos memory address to the contents of memory
See Also | mpiSercosMemoryGet | mpiSercosMemorySet


mpiSercosMemoryGet

Declaration
long mpiSercosMemoryGet(MPISercos sercos,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description

SercosMemoryGet copies count bytes of Sercos (sercos) memory (starting at address src) to application memory (starting at address dst).

Return Values
MPIMessageOK if SercosMemoryGet successfully copies count bytes of Sercos memory to application memory
See Also | mpiSercosMemorySet | mpiSercosMemory


mpiSercosMemorySet

Declaration
long mpiSercosMemorySet(MPISercos sercos,
                        void      *dst,
                        void      *src,
                        long      count)
Required Header stdmpi.h
Description

SercosMemorySet copies count bytes of application memory (starting at address src) to Sercos (sercos) memory (starting at address dst).
Return Values
MPIMessageOK if SercosMemorySet successfully copies count bytes of application memory to Sercos memory
See Also | mpiSercosMemoryGet | mpiSercosMemory


mpiSercosNode

Declaration
const MPINode  mpiSercosNode(MPISercos sercos,
                             long      index)
Required Header stdmpi.h
Description

SercosNode returns the element at the position on the list indicated by index.

sercos | a handle to the Sercos object.
index | a position in the list.

Return Values
handle | to the indexth Node object of a Sercos object (sercos)
MPIHandleVOID | if sercos is invalid if index is less than 0 if index is greater than mpiSercosCount(sercos) if index is equal to mpiSercosCount(sercos)
MPIMessageARG_INVALID | if index is a negative number.
MEIListMessageELEMENT_NOT_FOUND | if index is greater than or equal to the number of elements in the list.
MPIMessageHANDLE_INVALID | if sercos is an invalid handle.
See Also


mpiSercosNodeAppend

Declaration
long mpiSercosNodeAppend(MPISercos sercos,
                         MPINode   node)
Required Header stdmpi.h
Description

SercosNodeAppend appends a Node object (node) to a Sercos object (sercos).

sercos | a handle to the Sercos object.
node | a handle to a Node object.

Return Values
MPIMessageOK | if SercosNodeAppend successfully appends the Node object to the Sercos object
MPIMessageHANDLE_INVALID | Either sercos or node is an invalid handle.
MPIMessageNO_MEMORY | Not enough memory was available.
See Also


mpiSercosNodeCount

Declaration
long mpiSercosNodeCount(MPISercos sercos)
Required Header stdmpi.h
Description

SercosNodeCount returns the number of elements on the list.

sercos | a handle to the Sercos object.

Return Values
number | of Node objects in a Sercos object (sercos)
-1 | if sercos is invalid
0 | if sercos is empty
See Also


mpiSercosNodeFirst

Declaration
const MPINode mpiSercosNodeFirst(MPISercos sercos)
Required Header stdmpi.h
Description

SercosNodeFirst returns the first element in the list. This function can be used in conjuntion with mpiSercosNodeNext() in order to iterate through the list.

sercos | a handle to the Sercos object.

Return Values
handle | to the first Node object of a Sercos object (sercos)
MPIHandleVOID | if sercos is invalid if sercos is empty
MPIMessageHANDLE_INVALID | if sercos is an invalid handle.

See Also | mpiSercosNodeNext | mpiSercosNodeLast


mpiSercosNodeIdnDataSET

Declaration

#define	  mpiSercosNodeIdnDataSET(sercos,node,idn)
      mpiSercosNodeIdnFieldSet((sercos), (node), (idn), MPIIdnFieldDATA)
Required Header stdmpi.h
Description

SercosNodeIdnDataSET writes the data fields from an idn object to an idn on a sercos node.
See Also


mpiSercosNodeIdnGET

Declaration

#define	  mpiSercosNodeIdnGET(sercos,node,idn)
      mpiSercosNodeIdnFieldGet((sercos), (node), (idn), MPIIdnFieldALL)
Required Header stdmpi.h
Description

SerocsNodeIdnGET reads all the fields from idn located on a sercos node and writes them into the idn object.
See Also


mpiSercosNodeInsert

Declaration
long mpiSercosNodeInsert(MPISercos sercos,
                         MPINode   node,
                         MPINode   insert)
Required Header stdmpi.h
Description

SercosNodeInsert inserts a Node object (insert) in a Sercos object (sercos), just after the specified Node object (node).

Return Values
MPIMessageOK if SercosNodeInsert successfully inserts the Node object (insert) just after the specified Node object (node), in the Sercos object (sercos)
See Also


mpiSercosNodeIndex

Declaration
long mpiSercosNodeIndex(MPISercos sercos,
                        MPINode node)
Required Header stdmpi.h
Description

SercosNodeIndex returns the position of node on the list.

sercos | a handle to the Sercos object.
node | a handle to a Node object.

Return Values
index | of a Node object (node) in a Sercos object (sercos)
-1 | if sercos is invalid if node was not found in sercos
See Also


mpiSercosNodeLast

Declaration
const MPINode mpiSercosNodeLast(MPISercos sercos)
Required Header stdmpi.h
Description

SercosNodeLast returns the last element in the list. This function can be used in conjuntion with mpiSercosNodePrevious() in order to iterate through the list backwards.

sercos | a handle to the Sercos object.

Return Values
handle | to the last Node object (node) of a Sercos object (sercos)
MPIHandleVOID | if sercos is invalid if sercos is empty
MPIMessageHANDLE_INVALID | if sercos is an invalid handle.

See Also | mpiSercosNodePrevious | mpiSercosNodeFirst


mpiSercosNodeListGet

Declaration
long mpiSercosNodeListGet(MPISercos sercos,
                          long      *nodeCount,
                          MPINode   *nodeList)
Required Header stdmpi.h
Description

SercosNodeListGet gets the Nodes in a Sercos object (sercos), and writes an array (of handles to those Nodes, size= nodeCount) to the location pointed to by nodeList, and also writes the number of Nodes (in the Sercos object) to the location pointed to by nodeCount.

Return Values
MPIMessageOK if SercosNodeListGet successfully writes the array of Node handles and the number of Nodes to the 2 locations (nodeList, nodeCount)
See Also | mpiSercosNodeListSet


mpiSercosNodeListSet

Declaration
long mpiSercosNodeListSet(MPISercos sercos,
                          long      nodeCount,
                          MPINode   *nodeList)
Required Header stdmpi.h
Description

Using the Node handles specified by nodeList, SercosNodeListSet creates a list of Nodes (length=nodeCount). Any existing Node list of the Sercos object (sercos) is completely replaced.

The nodeList argument is the address of an array of nodeCount Node handles, or is NULL (if nodeCount is equal to zero).

You can also create a Node list incrementally (one Node at a time), by using the mpiNodeListAppend(...) and/or mpiNodeListInsert(...) methods. You can use any mpiNodeList method to examine and manipulate a Node list sequence, regardless of how the the Node list was created.
Return Values
MPIMessageOK if IdnListSet successfully creates the IdnList using the handles in idnArray
See Also | mpiSercosNodeListGet


mpiSercosNodeNext

Declaration
const MPINode  mpiSercosNodeNext(MPISercos sercos,
                                 MPINode   node)
Required Header stdmpi.h
Description

SercosNodeNext returns the next element following "node" on the list. This function can be used in conjuntion with mpiSercosNodeFirst() in order to iterate through the list.

sercos | a handle to the Sercos object.
node | a handle to a Node object.

Return Values
handle | to the Node object that is just after the specified Node object (node), in a Sercos object (sercos)
MPIHandleVOID | if sercos is invalid if node is the last Node in the Sercos object (sercos)
MPIMessageHANDLE_INVALID | Either sercos or node is an invalid handle.

See Also | mpiSercosNodeFirst | mpiSercosNodePrevious


mpiSercosNodePrevious

Declaration
const MPINode  mpiSercosNodePrevious(MPISercos sercos,
                                     MPINode   node)
Required Header stdmpi.h
Description

SercosNodePrevious returns the previous element prior to "node" on the list. This function can be used in conjuntion with mpiSercosNodeLast() in order to iterate through the list backwards.

sercos | a handle to the Sercos object.
node | a handle to a Node object.

Return Values
handle | to the Node object that is just before the specified Node object (node), in a Sercos object (sercos)
MPIHandleVOID | if sercos is invalid if node is the first Node in the Sercos object (sercos)
MPIMessageHANDLE_INVALID | Either sercos or node is an invalid handle.

See Also | mpiSercosNodeLast | mpiSercosNodeNext


mpiSercosNodeRemove

Declaration
long mpiSercosNodeRemove(MPISercos sercos,
                         MPINode   node)
Required Header stdmpi.h
Description

SercosNodeRemove removes a Node object (node) from a Sercos object (sercos).

Return Values
MPIMessageOK if SercosNodeRemove successfully removes the Node object from the Sercos object
See Also


mpiSercosNumber

Declaration
long mpiSercosNumber(MPISercos sercos,
                     long      *number)
Required Header stdmpi.h
Description

SercosNumber writes the index of a Sercos object (sercos, on the motion controller that the Sercos object is associated with) to the location pointed to by number.

Return Values
MPIMessageOK if SercosNumber successfully writes the Sercos object’s index to the location
See Also


mpiSercosReset

Declaration
long mpiSercosReset(MPISercos sercos)
Required Header stdmpi.h
Description

SercosReset resets a Sercos object (sercos), thereby setting its initialization phase to 0.

Return Values
MPIMessageOK if SercosReset successfully resets the Sercos object
See Also


meiSercosServiceIdnFieldGet

Declaration

        long meiSercosServiceIdnFieldGet(MPISercos                 sercos,
                                         MEISercosServiceContainer *service,
                                         MPIIdn                    idn,
                                         MPIIdnField               field)
Required Header stdmei.h
Description

SercosServiceIdnFieldGet uses a service container to read the specified field from an idn, and write it into the idn object.

sercos | a handle to a Sercos object
*service | a pointer to a service container
idn | a handle to an Idn object
field | enumeration corresponding to each element in the structure MPIIdnElement
Return Values
MPIMessageOK if SercosServiceIdnFieldGet successfully reads the field from the service container.
See Also | mpiSercosServiceIdnFieldSet | MPIIdnElement


meiSercosServiceIdnFieldSet

Declaration

        long meiSercosServiceIdnFieldSet(MPISercos                 sercos,
                                         MEISercosServiceContainer *service,
                                         MPIIdn                    idn,
                                         MPIIdnField               field)
Required Header stdmei.h
Description

SercosServiceIdnFieldSet uses a service container to write the specified field from an idn object to an idn.

sercos | a handle to a Sercos object
*service | a pointer to a service container
idn | a handle to an Idn object
field | enumeration corresponding to each element in the structure MPIIdnElement
Return Values
MPIMessageOK if SercosServiceIdnFieldSet successfully writes the field to an idn via the service container.
See Also | mpiSercosServiceIdnFieldGet | MPIIdnElement


meiSercosServiceProcedure

Declaration

          long meiSercosServiceProcedure(MPISercos                 sercos,
                                         MEISercosServiceContainer *service,
                                         MPISercosProcedureAction  action,
                                         MPIIdn                    idn,
                                         unsigned long             *status)
Required Header stdmei.h
Description

SercosServiceProcedure uses a service container to send a procedure action to a sercos idn.

sercos | a handle to a Sercos object
*service | a pointer to a service container
action | a command used to invoke a procedure
idn | a handle to an Idn object
*status | a pointer to an unsigned long
Return Values
MPIMessageOK if SercosServiceProcedure successfully sends a procedure action via a service container.
See Also | MPISercosProcedureAction


mpiSercosStatus and meiSercosStatus

mpiSercosStatus / meiSercosStatus

mpiSercosStatus
Declaration
long mpiSercosStatus(MPISercos       sercos,
                     MPISercosStatus *status,
                     void            *external)
Required Header stdmpi.h
Description

SercosStatus writes the status of a Sercos object (sercos) to the structure pointed to by status.

Return Values
MPIMessageOK if SercosStatus successfully writes the status of a Sercos object to the structure

meiSercosStatus
Declaration
long meiSercosStatus(MPIControl         control,
                     MEIMotorTypeInfo   *motorInfo,
                     MPISercosStatus    *status)
Required Header stdmei.h
Description

SercosStatus reads the status from a control and writes it into the location pointed to by status. The status is read from the nodeNumber specified in the structure pointed to by motorInfo.

control | a handle to the Sercos object.
*motorInfo | a pointer to a MEIMotorTypeInfo structure
*status | a handle to a Node object.
Return Values
MPIMessageOK if SercosStatus successfully reads the status.
See Also


mpiSercosValidate

Declaration
long mpiSercosValidate(MPISercos sercos)
Required Header stdmpi.h
Description

SercosValidate validates the Sercos object and its handle (sercos).

Return Values
MPIMessageOK if Sercos is a handle to a valid object.
See Also | mpiSercosCreate | mpiSercosDelete


Service Objects

Introduction |
 | A Service object creates and handles threads that help event managers dispatch events. Typically, one will use a Service Object to create threads that will call mpiEventMgrService(…) whenever an XMP interrupt occurs. They are a convenient way to have a program automatically deal with event managers and events. Thread handling is something that is different on every operating system. Service objects may therefore have different behaviors on different operating systems. Programmers that are experienced in multi-threaded application programming will probably want to program their own threads that will call mpiEventMgrService(…).
Methods
Create, Delete, Validate Methods
 | mpiServiceCreate | Create a Service for EventMgr and the threads necessary for it to run.
 | mpiServiceDelete | Stop all threads belonging to the Service and deletes the Service.

Configuration and Information Methods
 | mpiServiceEnable | Enable or disables the Service.


ServiceCreate

Declaration
const Service serviceCreate(MPIEventMgr eventMgr,
                            long        priority,
                            long        sleep)
Required Header service.h
Description

ServiceCreate creates threads for each control associated with eventMgr, flushes eventMgr, and starts threads with priority that call mpiEventMgrService(eventMgr, … ) every sleep milliseconds.

priority is a platform specific variable.

If "priority" is | Then
-1 | The operating system will choose some default priority for the service’s threads.
>0 | ServiceCreate will attempt to assign the priority to all of the service’s threads.

If "sleep" is | Then
-1 | ServiceCreate will attempt to create interrupt driven threads.
0 | ServiceCreate will create threads that call mpiEventMgrService(eventMgr,...) as quickly as possible.
>0 | ServiceCreate will create threads that attempt to call mpiEventMgrService(eventMgr,...) every sleep milliseconds.

Return Values
handle | to a Service object
MPIHandleVOID | if the Service could not be created

See Also | mpiEventMgrService | ServiceDelete


ServiceDelete

Declaration
long serviceDelete(Service service)
Required Header service.h
Description

ServiceDelete alerts all threads that they should end, waits for all threads to end, and frees the memory allocated to service.
Return Values
MPIMessageOK if serviceDelete successfully deletes a Service object and invalidates its handle
See Also | ServiceCreate


ServiceEnable

Declaration
long serviceEnable(Service service,
                   long    enabled)
Required Header service.h
Description

ServiceEnable enables or disables all threads belonging to Service.

If "enabled" is | Then
FALSE | serviceEnable will disable service.
TRUE | serviceEnable will enable service.

Return Values
handle | to a Service object
MPIHandleVOID | if the Service could not be created
See Also


Trace Objects

Introduction

Use the Trace module to selectively produce trace output on a global and/or per-object basis for your application. You can specify the types of trace output when an application is linked, or dynamically (by using a debugger).

Note: You can also define your own trace function, using meiPlatformTraceFunction(...) For example, you could define your own function to send traces to a circular memory buffer.

The format of the trace output is determined by printf(...)-like trace macros located in MPI library source. The trace macros are of the form meiTrace#(mask, format, arg ...), where format and the args determine the trace output, and where # indicates the total number of arguments following the format argument (because macros cannot take variable numbers of arguments).

The placement and content of the meiTrace(...) macros in the MPI library source is the responsibility of whomever maintains the library. Because trace can be added as desired, it is often useful to leave trace statements in the library source code rather than remove them, as is similarly done with debug printf(...) statements. It is also useful to define per-object trace output types so that the volume of trace output is set to a manageable level.

The Trace module interface is declared in the XMP\include\trace.h header file. In order for your application to use Trace functions, you must build your application with the MEI_TRACE conditional-compile symbol defined.

To install trace, simply install the DLL for either the Debug or DebugSingle configuration. The Debug and DebugSingle configurations of the MPI library are built with the MEI_TRACE compile-time symbol defined.

Note: Debug and DebugSingle are the only MPI library configurations that will produce trace output.

By default, trace output is sent to standard error. However, to send trace output to a file, your application can call the meiTraceFile(char *fileName) function.

To obtain the current global trace mask, call meiTraceGet(...).
To modify the global trace mask, call meiTraceSet(...).

To obtain an object's trace mask, call meiObjectTraceGet(...) (defined in stdmei.h).
To modify an object's trace mask, call meiObjectTraceSet(...).

Trace Masks | Global Trace Outputs | Per-Object Trace Outputs

Methods
Configuration and Information Methods
 | meiTraceEol | Set the end-of-line character to be used by Trace
 | meiTraceFile | Send trace output to a file
 | meiTraceFunction | sets function used to display a trace buffer
 | meiTraceGet | Get global trace mask
 | meiTraceSet | Set global trace mask

Data Types
MEITraceFunction
MEITraceMask

Constants
MEITraceMaskGLOBAL


GlobalTrace Outputs

 Global Trace Outputs

There is a global 32-bit trace mask: the low 16 bits are the global trace output types, while the upper 16 bits are the per-object trace output types. Each object has a similar trace mask. The upper 16 bits of the global trace mask are not defined, but can be used to set the per-object output types for all objects. To enable all trace output types for all objects, set the global trace mask to all 1s (i.e., -1).

The MEITrace{...} enum (declared in trace.h) specifies the global types of trace output, i.e., the types of trace output that can be produced by any object or module. The MEITrace{...} enum defines constants that you use together as a bit mask. You specify the desired trace output as a combination (logical OR) of MEITrace{...} constants.

There are 16 possible types of global trace output, with 12 global trace outputs defined.

Output Type | Displays
MEITraceFUNCTION_ENTRY | Function name & calling parameters upon entry to function
MEITraceFUNCTION_RETURN | Function name, calling parameters & return value upon exit from function
MEITraceMEMORY_ALLOC | The Address & byte count when memory is dynamically allocated
MEITraceMEMORY_FREE | The Address & byte count when dynamically allocated memory is freed
MEITraceMEMORY_GET | Source address, destination address, byte count when reading XMP firmware memory
MEITraceMEMORY_SET | Source address, destination address, byte count when writing XMP firmware memory
MEITraceVALIDATE | Results of object validation
MEITraceLOCK_GIVE | When a resource lock is released
MEITraceLOCK_TAKE | When a resource lock is waited for & obtained
MEITraceEVENT | When an XMP event is received
MEITraceALL | All global trace outputs (lower 16 bits)
MEIModuleTraceALL | All per-object trace outputs (upper 16 bits)

Return to Trace Object's page


 Per-Object Trace Outputs

There are 16 possible types of per-object trace output. Each object can declare up to 16 of its own trace output types. MPI modules declare per-object trace output types in stdmei.h. MEI modules declare per-object trace output types in the module header file.

Output Type | Displays
MEIMotionTraceSTATUS | Status of the Motion Supervisor
MEINotifyTrcaeTHREAD | When a thread goes to sleep or wakes up
MEISequenceTraceLOAD | When a batch of new commands are sent to the XMP Program Sequencer
MEIConfigTracePROGRESS | Displays “.” as it executes (used by config utility)
MEIRecorderTraceRECORD_GET | When the Recorder gets records from the XMP
MEIRecorderTraceSTATUS | The number of data records available in the XMP
Note: The first 5 output types overlap in the mask.

Return to Trace Object's page


 Trace Masks

Every MPI object contains an MEITraceMask and every process contains a single global MEITraceMask. An MEITraceMask consists of bits, where each bit corresponds to a single trace category. A trace category is a specific type of debug information that you want to be displayed by the MPI library. A trace category can be either global (applying to all MPI objects) or object-specific (applying only to a specific MPI object).

Trace Category | Is
global | declared by the MEITrace{...} enum in trace.h.
object-specific (for MPI objects) | declared in stdmei.h.
object-specific (for MEI objects) | declared in the object header file (for MEI objects). Note that the trace mask bits for object-specific trace categories overlap.

An object will produce trace output for a trace category when the logical OR of the global trace mask and the object's trace mask has the bit set that corresponds to the trace category.

If the global trace mask has all of its bits set, then all objects will display trace output for all trace categories.

If an object's trace mask has all of its bits set, then that object will display trace output for all trace categories, but a different object of the same type might produce less or no trace output depending on the setting of its trace mask. The setting of the global and object trace masks is under the control of your application.

The trace mask is derived in 2 steps:

    1. The global trace mask is logically ORed with the object trace mask. This yields the current trace mask, representing the desired trace output types as specified by the application.
    2. The current trace mask (from step1) is logically ANDed with a library-defined trace mask (that describes the trace output types for which the trace macro should produce output). If the result of the AND is non-zero, trace output will be produced using the format and the args [from meiTrace#(mask, format, arg ...

Return to Trace Object's page


MEITraceFunction

MEITraceFunction

typedef long (*MEITraceFunction)(const char *buffer);

Description | Definition for a trace function interface. TraceFunction can be used to define a custom trace output routine. MEITraceFunction function must take a pointer to a buffer as a parameter and must return a long.

See Also | meiTraceFunction


MEITraceMask

MEITraceMask

typedef    unsigned long MEITraceMask;

Description | TraceMask is a bit mask used to enable/disable library trace statement output.

See Also | meiTraceGet | meiTraceSet | MEITraceMaskGLOBAL


MEITraceMaskGLOBAL

MEITraceMaskGLOBAL

extern MEITraceMask 	MEITraceMaskGLOBAL;
Description

TraceMaskGlobal is a non-object specific MPI Trace mask variable used for library wide Trace bits.

See Also | MEITraceMask


meiTraceEol

Declaration
char meiTraceEol(char eol)
Required Header stdmei.h
Description

TraceEol function simply calls meiPlatformTraceEol(...), which sets the end-of-line character that will be used by meiPlatformTrace(...). By default, meiPlatformTrace(...) will append a newline character ('\n') to the messages that it displays. The meiPlatformTraceEol(...) function allows your application to set the default end-of-line character.

Returns

 the previous end-of-line character used by meiPlatformTrace(...)
See Also | meiPlatformTrace | meiPlatformTraceEol


meiTraceFile

Declaration
long meiTraceFile(const char *fileName)
Required Header stdmei.h
Description TraceFile causes trace output to be sent to the file fileName. By default, trace output goes to standard output. Note that if fileName is Null, trace output still goes to standard output.
Return Values
MPIMessageOK if TraceFile successfully causes trace output to be sent to the file
See Also


meiTraceFunction

Declaration
MEITraceFunction meiTraceFunction(MEITraceFunction traceFunction)
Required Header stdmei.h
Description

TraceFunction sets the function used to display a trace buffer.

Front end to meiPlatformTraceFunction(). If traceFunction is NULL (default), then trace functions is fprintf(MEIPlatformTraceSTREAM) (default stdout).

Return Values
handle | to previous Trace function
NULL | otherwise
See Also


meiTraceGet

Declaration
MEITraceMask meiTraceGet(void)
Required Header stdmei.h
Description

TraceGet returns the current global trace mask for the application.

Returns

 the global trace mask
See Also | meiTraceSet


meiTraceSet

Declaration
MEITraceMask meiTraceSet(MEITraceMask mask)
Required Header stdmei.h
Description TraceSet sets the global trace mask to mask.
If "traceMask" is | Then
MEITraceALL | all global categories of trace will be enabled
MEITraceNONE | all categories of trace will be disabled

Returns

 the value of the previous global trace mask
See Also | meiTraceGet


General Definitions

MPI | Platform | MPI Installation Directory | Object | Handle | Method | Module

MPI

The Motion Programming Interface (MPI) defines a set of object-oriented, C-language functions and data types that you can use to develop motion control applications. The MPI is designed to be independent of the motion controller hardware used, as well as the platform (operating system & compiler) on which the motion control application is built. To support the MPI, a platform must be 32-bit (e.g. Windows NT). Most 32-bit platforms are capable of multi-threading and multi-tasking, and the MPI has built-in features that simplify the design and development of these types of applications.

For XMP only Instructions for the implementation of MPI in Motion Engineering’s XMP motion controller are flagged with the notice “For XMP only."

To add custom features, applications often make use of extensions to the MPI, which limits portability.

Platform

A platform is the combination of the host computer, operating system, and C compiler. A platform must be 32-bit, i.e., the operating system must be able to execute 32-bit programs.
For XMP only The MPI/XMP has been ported to the WindowsNT/Microsoft Visual C++ platform. This platform is referred to as XMP-WinNT. If you are interested in using the MPI/XMP with other operating systems and C compilers, please contact MEI.

MPI Installation Directory

The MPI installation directory is the location into which the MPI software has been installed. The installation procedure suggests a default location (C:\MEI), but you can choose to install it wherever you desire. It is highly recommended that you use the default location. The installation directory contains an MPI directory:

MPI Subdirectories
Directory \ MPI | Contains
\doc | Documentation – User and Reference Guides
\include | MPI header files

For XMP-WinNT only The default installation directory is C:\MEI, and it contains a release note named YYYYMMDD.pdf, where YYYY represents the year, MM the month, and DD the day of the release. The installation directory also contains an XMP directory, which has various subdirectories.

XMP Subdirectories
Directory: C:\MEI\XMP Contains

\app

 Sample applications

\bin

 XMP firmware

\bin\WinNT

 Windows NT utilities (from util)

\doc

 Documentation - XMP Harware and Software Reference

\include

 XMP header files

\lib

 XMP libraries

\util

 XMP utility source

Object

An object is an instance of a data structure. The data structure is typically not directly accessible by an application.
When an application calls a function (also called a method) to create an object, the function returns a handle to the object. The object handle is then passed as the first argument to all other functions (methods) that are associated with that object. These functions provide indirect access to the object’s data structure. When it is finished using an object, an application simply calls another function to delete it.
Example The MPI defines an Axis object. An Axis object is created by the mpiAxisCreate(...) function, which returns a handle of type MPIAxis. The mpiAxisStatus(...) function takes an Axis handle as its first argument and returns the status of the hardware axis with which the Axis object is associated. An Axis object is deleted by calling the mpiAxisDelete(...) function.

Handle

A handle is returned by the function that creates an object, and the handle uniquely identifies that object. A handle is simply a pointer to a pointer to an object. The MPI defines the type MPIHandle to be a generic handle. The symbol MPIHandleVOID is used to represent an invalid handle. The MPI functions that create and delete objects typically allocate and free memory from a heap; in this case a handle is generally a pointer to the allocated object data structure. However, an MPI implementation could define a handle to be a pointer into a static array of data structures, or an index into such an array. Regardless, an application MUST NOT do anything with a handle other than to pass it as an argument to other functions. In cases where a handle is a pointer, the pointer cannot be dereferenced, because the object data structure to which the handle points is not directly available to the application.

Example The MPI defines an Axis handle to be of type MPIAxis. An axis handle named axisHandle can be declared as follows: MPIAxis axisHandle;

Method

A function associated with an object is called a method. The first argument of a method is always the handle of the object with which it is associated. A function that is not associated with an object is called a function. Throughout the MPI documentation, the term function refers to methods and functions, whereas the term method only refers to methods.

Example The following functions are all considered to be methods: mpiAxisCreate(...), mpiAxisStatus(...), mpiAxisDelete(...). Except for mpiAxisCreate(...), these functions all take an MPIAxis handle as their first argument.
                      MPIAxis axis;
                      axis = mpiAxisCreate(…);
                      mpiAxisStatus(axis, …);
                      mpiAxisDelete(axis);

Module

A module is a source file (module.c) whose interface is declared in a header file (module.h). A module contains code symbols (methods, functions, macros) and data symbols (data, data types and constants) that together implement an object. However, a module may also contain functions that have a logical connection without being associated with an object.

MPI Module | Header
Adc | adc.h
Axis | axis.h
Capture | capture.h
Command | command.h
Control | control.h
Event | event.h
EventMgr | eventmgr.h
Filter | filter.h
Idn | idn.h
IdnList | idnlist.h
Message | message.h
Motion | motion.h
Motor | motor.h
MpiDef | mpidef.h
Node | node.h
Notify | notify.h
Object | object.h
Recorder | recorder.h
Sequence | sequence.h
Sercos | sercos.h
StdMpi | stdmpi.h

XMP Module | Header
Client | client.h
Element | element.h
Firmware | firmware.h
Flash | flash.h
List | list.h
Map | map.h
MeiDef | meidef.h
Packet | packet.h
Platform | platform.h
Remove | remove.h
RipTide | riptide.h
Server | server.h
Trace | trace.h
XMP | xmp.h

Utility Module | Header
msgCHECK | msg.h
Service | service.h
Log | log.h
LogFunc | logFunc.h

Example The axis module consists of a source file called axis.c and a header file called axis.h. The axis.c source file contains the definitions of all Axis code and data symbols, in particular the Axis object data structure. The axis.h header file contains the declarations for the code and data symbols in axis.c.
Introduction | Motion Concepts | General Definitions | Naming Conventions | Object Descriptions


Introduction to the MPI Library

The MPI is a C language object-oriented interface that makes it easy for you to develop motion control applications that run on many different types of platforms. Programs written using the MPI range from simple single-task, single-controller applications to complex multi-tasking applications using multiple motion controllers. The MPI hides platform-specific and firmware implementation details while providing a rich set of functions to control motion at any desired level. As a system designer, you have complete flexibility to choose the level of control best suited for your application. The MPI library executes on the host computer, while the firmware executes on the XMP controller.

The XMP’s firmware components are managed by host software using the MPI (Motion Programming Interface). The MPI provides direct memory access to all XMP firmware components, delivering much more performance than competing systems that use command-based controllers or ASCII interfaces. Designed for multitasking environments, the MPI can access one or more motion controllers at maximum bus bandwidth, while efficiently handling controller interrupts.

Debugging under the MPI environment is simple if you use the configurable trace and debug features. The trace feature enables you to follow the progress of an executing program by observing the stream of messages produced whenever a library function is entered (displaying calling parameters) and whenever a library function is exited (displaying the return value).

You also have the ability to validate all library function parameters, and to stop execution whenever an error occurs, displaying the source file name and line number where the error occurred. You can configure the MPI for optimal trace and debug support during the design and test phase, and then reconfigure the MPI for optimal performance (without the debugging support).

Introduction | Motion Concepts | General Definitions | Naming Conventions | Object Descriptions


Motion Concepts

Introduction | Maps & Links | Motor Links | Filter Links
Axis Links | see Object Relationships

Introduction

The XMP software architecture is composed of separate modular objects that can be associated in a variety of ways to create custom systems. For example, a gantry or robot using more than one motor for a physical axis may be configured to allow the application to treat the axis as a single entity, simplifying the geometry. This flexibility does not come without a price, however, since configuration of complex systems involves a fairly large number of parameters. To overcome the need to configure simple "standard" systems, the XMP is pre-configured with a factory default configuration which can be used for most simple systems.

To understand how to create a custom XMP configuration, you must understand the component objects involved. Custom configurations are created using four types of objects: Motors, Filters, Axes, and Motion Supervisors (called Motion objects). To simplify implementation of the XMP architecture, we assumed that the association of Motors, Filters, and Axis would be more or less static (created during initialization), while association of Axes with Motion Supervisors would be more dynamic (created or modified during runtime).

Maps & Links

The relationships between the controller objects are determined by Maps and Links associated with the objects. The Maps are used by the MPI to define the object relationships and usually have the form of bitmaps. The following MPI functions are used to read and write these Maps.

mpiMotorAxisMapGet(...) | .
mpiMotorFilterMapGet(...) | mpiMotorFilterMapSet(...)
mpiFilterAxisMapGet(...) | mpiFilterAxisMapSet(...)
mpiFilterMotorMapGet(...) | mpiFilterMotorMapSet(...)
mpiAxisMotorMapGet(...) | .
mpiAxisFilterMapGet(...) | mpiAxisFilterMapSet(...)

Note that there are no functions to write any Motor-Axis or Axis-Motor maps. This is because these relationships are defined by the maps of the associated filters.

The links are used by the controller's objects to determine the sources for data generated by other objects. These links generally have the form of pointers that reference the source of the data or indexes that identify the sourcing object.

Motor Links

There can be up to 2 filter outputs used in calculating the output level of the Motor command. The following expression is evaluated each sample to determine this output:

Filter Links

The Filter object uses the difference between command and actual positions to calculate a control output (control algorithm). Both the command and actual positions used in these calculations can be defined as a linear combination of positions from 2 different sources.

MEIFilterConfig{}.Axis[] determine the sources and weight factors for these position inputs. On each sample, the following equations are used to determine the position error and command position used by the Filter:

The command velocity and acceleration used in feedforward calculations is also determined from MEIFilterConfig{}.AxisInput[], using the following equations:

Axis Links

The actual position of an axis can be calculated as a linear combination of position values from two separate sources. On each sample, the following equation is used to compute the Axis' actual position:

Introduction | Motion Concepts | General Definitions | Naming Conventions | Object Descriptions


Naming Conventions

Uniqueness | Symbol Declaration & Definition | Symbol Naming | Data Symbols | Code Symbols

Uniqueness

We have tried to make the names of all MPI code and data symbols unique, so that the names don’t conflict with symbols already defined in the supported operating systems, and in C language and third-party libraries. The MPI naming convention enables you to look at a symbol and know whether the symbol refers to code or data. The MPI uses “MPI” as the initial token of data symbols, while code symbols use an initial token of “mpi”.
Example The axis handle data type is called MPIAxis. The method that creates an axis object is called mpiAxisCreate(...).

MPI/XMP: MEI-specific additions and extensions to the MPI are named similarly with an initial token of “MEI” indicating a data symbol and “mei” indicating a code symbol.

Example The MEIAxisConfig{} data structure contains XMP-specific axis configuration parameters that extend the MPI-defined axis configuration parameters. The meiFilterCreate(...) function creates a Filter object, returning a handle of type MEIFilter. The Filter object is an addition to the MPI.

Symbol Declaration & Definition

MPI symbols are declared in header files and defined in source files. To determine the file in which an MPI symbol is declared and defined, look at the second token of the symbol name: the second token indicates the module where the symbol is declared and defined. Also, to maximize the portability of the code, the MPI uses a DOS-like 8.3 file naming convention. Therefore, the second token of any symbol name will not exceed 8 characters, nor will the names of modules and objects.

For example, consider a symbol named MPIObjectXyz. The symbol is a data symbol (MPI) declared in object.h and defined in object.c. Similarly, a symbol named mpiObjectAbc is a code symbol (mpi) declared in object.h and defined in object.c.
Example The MPIAxis data type and the mpiAxisCreate(...) method are declared in the header file axis.h. The MEIServer data type and meiServerDelete(...) method are declared in header file server.h. The code and data symbols for the Axis object are defined in axis.c; for the Server object, they are defined in server.c.

Symbol Naming

The previous sections use the concept of a token when discussing symbol names, where a token is a word or abbreviation contained in a symbol name. The name of an MPI symbol consists of a left-to-right sequence of tokens (with no spaces in between). An uppercase letter indicates the beginning of a token, except the first token of a symbol, which may be either upper (MPI) or lower case (mpi). The MPI uses underscores in symbol names only when it is necessary to separate tokens that are all uppercase letters.

The first token of a symbol (MPI or mpi) guarantees uniqueness and indicates whether the symbol is a data symbol (MPI) or a code symbol (mpi) . The second token indicates the module that declares and defines the symbol. The remaining tokens of the symbol name vary, depending on whether the symbol is code or data.

Data Symbols

Tokens in data symbols are arranged from left-to-right in a hierarchical fashion, with the leftmost token being general and the rightmost token being specific. If the data symbol names are listed alphabetically, this scheme results in an listing that groups related data symbols together.

If the rightmost token of a data symbol is all uppercase, then that data symbol is a constant. If the rightmost token of a data symbol is not all uppercase, then that data symbol is either data or a data type. Because the MPI contains virtually no global data, there is little need to distinguish between data and data type.

Consider the MPIMotorHomeIndex enumeration:

typedef enum {
    MPIMotorHomeIndexINVALID = -1,

    MPIMotorHomeIndexHOME_HI_INDEX,
    MPIMotorHomeIndexINDEX_ONLY,
    MPIMotorHomeIndexHOME_LO_INDEX,
    MPIMotorHomeIndexHOME_ONLY,

    MPIMotorHomeIndexLAST,
    MPIMotorHomeIndexFIRST = MPIMotorHomeIndexINVALID + 1
} MPIMotorHomeIndex;
The third and fourth tokens (Home, Index) are the same for all symbols. The enum name (MPIMotorHomeIndex) is incorporated in the name of all of the enum members, whose last token is all uppercase (FIRST, HOME_HI_INDEX, etc.) to indicate that they are constants (instead of a data type). It is standard coding practice to use enums rather than #defines to declare constants, which allows for greater control of the name space and better type-checking. The use of FIRST and LAST members in an enum is also standard coding practice, so that functions can bounds-check enum values.

Code Symbols

Tokens in code symbols indicate the data type and order of the arguments to the function. The last token in a code symbol is often the action that the function performs, or the data type that the function returns. If the code symbol names are listed alphabetically, this scheme results in a listing that groups related code symbols together.

If the rightmost token of a code symbol is all uppercase, then that code symbol is a macro.

If the rightmost token of a code symbol is not all uppercase, then that code symbol is either a function or a method.

Consider mpiAxisConfigGet(...) and mpiAxisConfigSet(...), which are 2 methods used to configure an Axis. Because these functions are methods, the first argument to them is an Axis handle. The second argument is a pointer to a structure of type MPIAxisConfig{}. The last token of the method name indicates the action to take; Get fills the supplied structure with Axis configuration and Set configures the Axis from the supplied structure.

The mpiAxisControl(...) method returns the MPIControl handle with which the Axis was created, while meiElementNEXT(...) is a macro that returns the MEIElement following the specified Element.
Introduction | Motion Concepts | General Definitions | Naming Conventions | Object Descriptions


Object Descriptions

Control Objects | Axis Objects | Motion Objects | Motor Objects | Filter Objects
Event Objects | Notify Objects | EventMgr Objects | Recorder Objects
Sequence Objects | Command Objects | Adc Objects | Coordinate Systems

Control Objects

Think of a Control object as a “Controller” object, which is typically a single circuit board residing in a PC or an embedded system. A Control object manages that motion controller board.

Every application creates a single Control object per board (XMP controller).

A Control object can read and write device memory using I/O port, memory-mapped or device driver methods. All communication with motion controller firmware is handled by a Control object.

For the case where the application and the motion controller device exist on two physically separate platforms connected by a LAN or serial line, the application creates a client Control object which communicates via remote procedure calls with a server.

If your application requires high performance, then only use the Control object to communicate directly with the firmware, bypassing all other MPI constructs. Unlike the methods of all other objects in the MPI, Control object methods are not thread-safe.
Objects taht are created with a single Control
Object | Relationship to a Controller
Adc | many-to-one, must reside on that controller
Axis | many-to-one
Filter | one-to-one or many-to-one
Motion | many-to-one or many-to-many
Motor | many-to-one
Recorder | one-to-one
Sequence | many-to-one

Axis Object

An Axis object is associated with a single physical axis on a motion controller, and corresponds to a geometric axis used for calculation of a path of motion. An Axis may be controlled by one or more Motion objects.

The concept of an Axis is a “geometric” idea, but the main purpose of an Axis object is to generate the desired path (trajectory calculations, i.e., to generate command positions) on every sample, using the path-planning data provided by a Motion Supervisor. An Axis object is mostly a computational block.

The Filter and Motor objects ensure that the command path (calculated by Axis) is followed, and that the signals get to the right motors.
Axis Objects Are Mapped to Filters and Motors

Motion Objects

Think of a Motion object as really a “Motion Supervisor” object.

The Motion (Supervisor) object corresponds to a coordinate system or collection of axes. The primary function of the Motion Supervisor is to provide data in a synchronized manner to the Axis objects for use in path creation.

A second important function of the Motion Supervisor is to monitor the status of all of the Axes under its control (and all of the Motors, and Filters associated with these Axes), so that motion can be stopped or resumed in a controlled manner, especially in the event of errors. The Motion Supervisor is the primary interface for a your MPI application with respect to motion. A Motion object maintains an ordered list of Axis objects, which specify the coordinate system for all motions to be performed with that Motion object. When a motion is started, the type of motion is specified (trapezoidal, S-curve, parabolic, etc.) along with type-specific motion parameters. A Motion can be started directly (by calling a Motion method), or started when the Motion is associated with a Command that is called by a Sequence (that is executing). An Axis object may be controlled by more than one Motion object, but only one of those Motion objects may be active at a time.

Motor Objects

The Motor object corresponds to a physical motor used to create motion. The primary function of the Motor object is simply to provide an interface to the physical hardware associated with the physical motor. The Motor object could practically be called the “I/O” object (only the User I/O is handled outside of the Motor object). Essentially, the Motor object is the controller’s interface to the outside world.

The data of the Motor object contains the state of encoders, limit switches, home sensors, amplifier control and status signals (amplifier enable, fault, step and direction), and general purpose digital and analog I/O. Secondary functions of the motor object include commutation control, limit checking, and position capture and compare control.

To perform sinusoidal commutation, the Motor takes the outputs from the Filter object. The Motor object also implements scale interpolation.

Filter Objects

The Filter object is concerned with the controller’s control loop, i.e., what should the controlled output be (usually an input to a Dac) based on the position error? The Filter is primarily a computational block, taking command positions and actual positions and computing errors.

The Filter object calculates the output (usually the D/A output level) that controlls a physical motor or motors, using data (command positions) calculated by the Axis object. PID, PIV and Biquad filter calculations are all parts of the Filter object.

Event Objects

An Event object contains information about an asynchronous event that has occurred. You typically obtain an Event object from the EventMgr object.

Notify Objects

A Notify object is used by a thread to wait for event notification.You can configure a Notify object to wait and look for specific events and for specific event sources.

Event Manager (EventMgr) Objects

An EventMgr:

  • obtains asynchronous events from the Control object(s) that the EventMgr is associated with
  • generates Event objects for enabled event sources
  • awakens any threads that are waiting for events

Recorder Objects

You typically use the Recorder object to periodically record motion data. Note that you can only have one Recorder object per Control object (controller).

Sequence Objects

A motion application can issue individual motion commands, or can create a series of motion commands (that are executed in sequence by the controller). Essentially, you can use the Sequence object to download commands that are executed by the XMP controller, and not executed by the host.

Using the MPI, you can create a sequence of commands (a Sequence object), using high-level motion (e.g., trapezoidal motion profile on axes 2 & 4), using low level work (e.g., write 0x00043433 into memory address 0x2000).

A typical Sequence might be
    1. Start a motion
    2. Wait 60 msec
    3. Turn on a specific I/O bit
    4. Wait for motion to finish
    5. Wait for another I/O bit
    6. Start a new motion
A Sequence object is always executed starting with the first command. After completing the first command, subsequent commands can initiate a new motion, set values in firmware memory, execute a delay for a specified period, branch to a different command in the sequence, wait for a condition to be met, and so on.

Command Objects

A Command object specifies a single action that is executed by a Sequence, such as motion, conditional branch, computation, time delay, wait for condition, etc. Any Command object that specifies motion must have a Motion object associated with it.

Adc Objects

Adc objects manage the A/D converters on a controller (Control). Typically the A/Ds can be programmed to perform conversions on different channels. On every timer interrupt, the A/D performs a single conversion, which takes 12 microseconds to complete.

A 16-Axis XMP controller has 8 A/D channels available for your application’s use. Each Adc can be correlated to a Motor object.
Note: For the XMP, no more than 2 Adc objects can be associated with a single Motor.

Coordinate Systems

To create a coordinate system for a motion application, you simply associate a list of Axis objects with a Motion object. The list of Axis objects and the order of those Axis objects on the list essentially define the coordinate system.
Introduction | Motion Concepts | General Definitions | Naming Conventions | Object Descriptions

Return to Software's Main Menu


Configuration Methods

Introduction | mpiObjectConfig{}
                Structure | mpiObjectConfigGet(...) / mpiObjectConfigSet(...)
                mpiObjectFlashConfigGet(...) / mpiObjectFlashConfigSet(...)

Introduction

An object’s configuration is static information that may be read and written, and an object retains its configuration until an application changes it. To configure an MPI object, you use a Config structure that is specific to each object.

To configure an MPI object, get the current Config from the motion controller by calling the ConfigGet method. Modify the Config structure as desired, and then send it back to the motion controller by calling the ConfigSet method.

If a motion controller has flash memory, you can configure that flash memory using the same Config structure. The MPI implementation handles all of the details for flash memory support; all your application needs is a handle to a flash memory object. If a motion controller does not have flash memory, the flash configuration methods will return MPIMessageUNSUPPORTED.

MPIObjectConfig{} Structure

An object’s configuration structure contains all of the configurable items for that object. To configure an object, your application must declare a variable of type MPIObjectConfig{}. Note that some Config structures are very large, so if you declare a Config structure on a small stack, your application might encounter problems. A pointer to a Config structure is passed to the Config methods.

The MPI Config structures should be able to support generic object configurations for a variety of motion controllers. However, the MPI also provides you with a way to perform configuration unique to a particular motion controller. In addition to the MPIObjectConfig{} structure, MPI Config methods can also use an external configuration structure that is defined by the implementation.
For XMP only The external configuration structures are of type MEIObjectConfig{}.
Example The MEIAxisConfig{} structure contains XMP-specific configuration parameters that extend the configuration available in MPIAxisConfig{}.

Configuration Methods
Root | Method | .
ConfigGet | mpiObjectConfigGet(...) | Fill configuration structures with current motion controller configuration
ConfigSet | mpiObjectConfigSet(...) | Change current motion controller configuration
FlashConfigGet FlashConfigSet | mpiObjectFlashConfigGet(...) mpiObjectFlashConfigSet(...) | Fill configuration structures with current motion controller Flash configuration Change current motion controller Flash configuration

mpiObjectConfigGet(...) / mpiObjectConfigSet(...)

The mpiObjectConfig( ) structure is meant to illustrate how objects are configured. Please swap the object you are interested in for the the object to configure. For example, mpiObjectConfigSet( ) shows the naming convention that mpiAxisConfigGet( ) follows.Both ConfigGet and ConfigSet take three arguments:
    • the first argument is the object handle (MPIObject)
    • the second argument is a pointer to an MPIObjectConfig{} structure (MPIObjectConfig *)
    • the third argument is a pointer to an external implementation-defined configuration structure (void *).The third argument may also be NULL
For XMP only The external argument is a pointer to an XMP-specific configuration structure of type MEIObjectConfig{}.

Use the Get method to fill the configuration structures with the current motion controller configuration for the object.
Use the Set method to change the current motion controller configuration for the object. (The Set method uses the configuration structures to do that.)

mpiObjectFlashConfigGet(...) / mpiObjectFlashConfigSet(...)

The FlashConfigGet and FlashConfigSet methods take four arguments:

    • The first argument is the object handle (MPIObject)
    • The second argument is an implementation-specific handle to Flash memory (void *).
    • The second argument can also be NULL.
    • The third argument is a pointer to an MPIObjectConfig{} structure (MPIObjectConfig *)
    • The fourth argument is a pointer to an external implementation-defined configuration structure (void *). The fourth argument can also be NULL.
For XMP only The flash handle is of type MEIFlash (second argument); the external argument (fourth argument) is a pointer to a configuration structure of type MEIObjectConfig{}.

Use the Get method to fill the configuration structures with the current motion controller Flash configuration for the object.
Use the Set method to change the current motion controller Flash configuration for the object. (The Set method uses the configuration structures to do that.)

The flash configuration is in effect after system start-up and also after resetting the motion controller (by calling the mpiControlReset(...) method).
Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Event Notification Methods

Introduction | mpiObjectEventNotifyGet(...)
                | mpiObjectEventNotifySet(...)
mpiObjectEventNotifyReset(...) | Notification
                Process

Introduction

The MPI EventMgr is responsible for the collection and distribution of host notifications of firmware events. An application often needs to be notified of events that take place on the motion controller. Events include normal motion completion, motion limits being reached, hardware failure, etc. The EventNotify methods enable your application to request host notification of certain types of events, while ignoring other types of events. Some events are latched, in which case your application must reset the event before the event can be triggered again.

Method | Description
mpiObjectEventNotifyGet(...) | Get event mask used for host notification
mpiObjectEventNotifySet(...) | Set event mask to request host notification of events
mpiObjectEventNotifyReset(...) | Reset event notification

mpiObjectEventNotifyGet(...)

Use EventNotifyGet to return an MPIEventMask, which has a bit set for each type of event that host notification has been requested for, by the object.

mpiObjectEventNotifySet(...)

Use EventNotifySet to request host notification for each type of event specified in the MPIEventMask argument.

mpiObjectEventNotifyReset(...)

Use EventNotifyReset to reset each type of event specified in the MPIEventMask argument.

Notification Process

Events [that are requested by mpiObjectEventNotifySet(...)] move up through the firmware to the EventMgr.
To collect events, the EventMgr either polls the firmware (using mpiEventMgrService(...)) or is interrupted by the firmware. The EventMgr passes each event to its list of Notify objects, who further qualify events based on the event type and the source of the event, and generate signals and otherwise notify the host application of event occurrences.
Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Identity Methods

Identity methods are used to identify an object, by providing the value of each of the arguments passed to the Create method to create that object. An identity method exists for each Create method argument, and typically is named by that argument.

Identity methods generally have a second output argument that is a pointer to the Create method argument to be returned; the return value of the method will indicate success or failure (as usual). However, identity methods that return an object handle do so directly rather than using an output argument.

Example

The mpiAxisCreate(...) method takes 2 arguments; an MPIControl handle and an axis number. Therefore, the Axis module declares 2 identity methods: mpiAxisControl(...) and mpiAxisNumber(...).

The mpiAxisControl(...) method returns the MPIControl handle with which the axis object was created. The mpiAxisNumber(...) method returns a value that indicates success or failure; if the value indicates success, the second argument points to a location that will be set to the axis number.

Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |

Return to Software: Method's Main Menu


List Methods

Introduction | List | Element | Array Methods
List Expansion Methods | List Contraction Methods | List Traversal Methods

Introduction

Several MPI objects maintain a list whose elements are other MPI objects.

Example A Motion object maintains a list of Axis objects.
An EventMgr object maintains 2 lists: a list of Control objects and a list of Notify objects.

The MPI declares standard list manipulation methods for all such objects. The MPI does not specify how lists are to be implemented.

List

A list is an ordered sequence of elements. Generally, the elements of a list are objects of the same type, but this is not required. A list that contains no elements is empty. A list may be traversed either forwards or backwards from any element that is a member of the list. List manipulation methods are declared for the object that maintains the list.

Element

An element is a member of a list. An element is generally an object. An element is added to or removed from a list using list manipulation methods (declared by the object that maintains the list).
Grouping | List Action | Method | .
Array Methods | ListGet ListSet | . | .
List Expansion | Append Insert | . | .
List Contraction | Remove | . | .
List Traversal | Count First Index Last Next Previous | mpiListElement(...) mpiListElementCount(...) mpiListElementFirst(...) mpiListElementIndex(...) mpiListElementLast(...) mpiListElementNext(...) mpiListElementPrevious(...) | Return handle of indexth element Return number of elements in list Return handle to first element in list Return index number of element in list Return handle to last element in list Return handle to next element in list Return handle to previous element in list

Array Methods

You use Array methods to manipulate lists. Array methods use an element count and an application-resident array of elements. These methods provide a convenient way of dealing with a list as a whole. Note that if you do use array methods for list manipulation, you can also use other list manipulation methods as well.

mpiListElementListGet(MPIList list, long *count, MPIElement *Element)
The ListGet method returns the list (maintained by List) as an array of object handles of type MPIElement. Upon successful return of the ListGet method, the contents of the location pointed to by count will be set to the number of elements in the list, or set to zero (if the list is empty). Your application must also define the object handle array pointed to by Element, and the array must be large enough to hold the current number of list elements.

mpiListElementListSet(MPIList list, long count, MPIElement *Element)
The ListSet method sets the list (maintained by List) from an array of object handles of type MPIElement. Upon successful return of the ListSet method, the list will contain count elements. Your application must also define the object handle array pointed to by Element, and the array must contain at least count list elements. After using the ListSet method, any existing list will be completely replaced by the new list. To make an existing list empty, call the ListSet method with a count of 0 and Element set to NULL.

List Expansion Methods

A list can be expanded by inserting an element at any point, either as the first element of the list, after a specific list element, or as the last element of the list. Lists generally check and verify that an element to be inserted is not already a list element. Other list-specific checks may be made before insertion as well.

mpiListElementAppend(MPIList list, MEIElement Element)
The Append method appends an object (whose handle is Element) to the list maintained by List, making it the last element of the list.

mpiListElementInsert(MPIList list, MEIElement before, MEIElement insert)
The Insert method inserts an object (whose handle is insert) into the list maintained by List, placing it after the list element whose handle is before. If before is MPIHandleVOID, insert becomes the first element of the list.

List Contraction Methods

A list can be contracted (shortened) by removing a list element. Lists check and verify that the element to be removed is actually a list element.

mpiListElementRemove(MPIList list, MEIElement Element)
The Remove method removes an object (whose handle is Element) from the list maintained by List.

List Traversal Methods

To traverse a list means to be able to move through all of the elements on a list. It can also involve determining the number of list elements, searching for a particular list element, finding the index of a list element, and more.
MPIElement mpiListElement(MPIList list, long index)

Return Values

 .
handle of the indexth list element of the list maintained by List
MPIHandleVOID if index is less than zero
if index is greater-than-or-equal-to the number of list elements

mpiListElementCount(MPIList list)

Return Values

 .
number of list elements on the list maintained by List
-1
 if list is invalid

MPIElement mpiListElementFirst(MPIList list)

Return Values

 .
handle to the first list element of the list maintained by List
MPIHandleVOID
 if list is empty or is not valid
if list is not valid

mpiListElementIndex(MPIList list, MPIElement Element)

Return Values

 .
index of Element in the list maintained by List
-1
 if list is empty or not valid
if Element is not a list element of the list maintained by List

MPIElement mpiListElementLast(MPIList list)

Return Values

 .
handle to the last list element of the list maintained by List
MPIHandleVOID
 if list is empty
if list is not valid

MPIElement mpiListElementNext(MPIList list, MPIElement Element)

Return Values

 .
handle to the list element immediately after Element in the list maintained by List
MPIHandleVOID
 if list is not valid
if Element is not a list element
if Element is the last list element of the list maintained by List

MPIElement mpiListElementPrevious(MPIList list, MPIElement Element)

Return Values

 .
handle to the list element immediately before Element in the list maintained by list
MPIHandleVOID
 if list is not valid
if Element is not a list element
if Element is the first list element of the list maintained by List
Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Memory Methods

Introduction | Accessing Memory Methods | Control Object Memory Methods
mpiObjectMemory(...) | mpiObjectMemoryGet(...) / Set(...)

Introduction

You use Memory methods to access a motion controller’s RAM. The MPI imposes no structure on motion controller RAM, so the use of memory methods requires implementation-specific knowledge of the motion controller’s memory map.
For MEI/XMP only The memory map is defined in the xmp.h header file. All accessible memory is defined b#eeeeFFy the MEIXmpData{} and MEIXmpBufferData{}structures.
Each object has its own memory methods; only the memory directly associated with the specific object can be accessed using that object’s Memory methods.
Example An Axis object created with axis number 0 may only access memory associated with Axis 0.

Accessing Memory Methods

Memory access via these methods is thread-safe; only one thread at a time can read or write the portion of memory associated with the object. The Get/Set methods will bounds-check the memory address to be accessed, and return an error if the address is not associated with the object.

Control Object Memory Methods

The Control object memory methods are an exception. Using the ControlMemory methods, an application may access all memory on the motion controller at any time, without constraint. The ControlMemory methods are not thread-safe. Memory methods for the other objects are generally implemented by locking the section of memory associated with the object, and then calling a ControlMemory method.

It is possible to write a motion application using only a Control object. After creating and initializing the Control object, the address of motion controller memory can be obtained, and you can use the ControlMemoryGet/Set methods to access that memory.

Depending on the type of Control object created, an application can directly access the motion controller memory without using the ControlMemoryGet/Set methods. Such an application would bypass the rest of the MPI library and must implement its own thread safety, as well as deal with how the motion controller firmware operates.
Method .
mpiObjectMemory(...)
mpiObjectMemoryGet(...)
mpiObjectMemorySet(...) 		Return host address of object in memory Read motion controller memory
Write motion controller memory

mpiObjectMemory(...)

The mpiObjectMemory(...) method returns a host address that maps to the section of motion controller memory associated with the object. mpiObjectMemory(...) uses 2 arguments: the object handle, and an output argument of type void **. If a call to mpiObjectMemory(...) succeeds, the location pointed to by the output argument is set to the host address.

mpiObjectMemoryGet(...) / mpiObjectMemorySet(...)

These methods read (get) and write (set) motion controller memory. They take 4 arguments:
    • the object handle
    • a destination address of type void *
    • a source address of type void *
    • and a length in bytes
The Get method’s destination address points to host memory, while the source address points to motion controller memory (based on the address returned by the Memory method for the object). The Set method is the opposite. The Set method’s destination address points to motion controller memory and the source address points to host memory.
Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Object Methods

Introduction | Common Methods for MPI Objects
mpiObjectCreate(...) | mpiObjectDelete(...) | mpiObjectValidate(...)

Introduction

Object-oriented languages such as C++ and Java provide capabilities such as inheritance and polymorphism. The MPI is written in the C language, and so these more exotic object-oriented features are not available. However, the basic concepts of object-oriented design are in the MPI: modularity, data hiding and no global or static data.

It’s similar to C++
If you are already familiar with C++, you will quickly realize that the MPI methods that create and delete objects are patterned after C++ constructors and destructors. An MPI method takes an object as its first argument, much as a C++ method has a “this” pointer. Object data is private and available only by calling object methods. MPI source code is organized into modules, with one object per module. Library state is distributed across application-created objects; there is virtually no state information maintained by the library.

All object methods and all functions return a value indicating whether the call to them succeeded or not. In general, the return value is of type long, with a value of 0 indicating success. The return value can be treated as an MPIMessage, so that you can call the mpiMessage(...) function to obtain a text string that describes the return value. The text string that indicates a successful return value of MPIMessageOK (0) is empty (“”).

All MPI objects must implement certain required methods. Note that most MPI objects implement standard configuration and memory methods; many MPI objects implement standard status and list manipulation methods and a few objects implement standard event notification methods. For multi-threaded environments, all objects must implement standard resource allocation timeout methods.

In general, there are few methods that are unique to an object, and those unique methods tend to be those that perform object-specific actions. The following sections describe the standard methods that are implemented by many objects. For specific details about objects and their methods/functions, refer to the breakdown of Objects.

Where used in the rest of this section, the word Object may be replaced with the name of an MPI object in order to obtain the name of the methods for that object.
Example

For the term mpiObjectCreate(...), replace Object with Axis to obtain the name of the method that you would use to create Axis objects, mpiAxisCreate(...).

For the term MPIObject, replace Object with Axis to obtain the data type of the Axis handle (MPIAxis) returned by the Axis method mpiAxisCreate(...), and also used by other Axis methods, such as mpiAxisValidate(...).

Common Methods for MPI Objects

All MPI objects have four types of common methods:

    • methods which create an object
    • methods which delete an object
    • methods which validate an object
    • methods which identify an object

mpiObjectCreate(...)

Use the Create method to create an object and return a handle that uniquely identifies that object. The MPI does not support declaring an object directly, so you must always use the Create method. The Create method is the only method that does not take an object handle as its first argument. The Create method arguments depend on the type of object being created.

If an object cannot be created, the value of the handle returned is MPIHandleVOID, which typically indicates only that no memory is available to hold the object. If memory is available to create the object, but the Create method encounters an error, then the Create method returns a handle, but the object referenced by the handle is not valid. A call to the mpiObjectValidate(...) method returns a value that indicates whether an object is valid, and if it is not valid, why. In general, if you call a method using an object handle that is invalid, the method will fail and return a value indicating the cause of failure.

The MPI supports multiple motion controllers. Typically, an MPI application first creates a Control object that corresponds to the desired motion controller. If the application will use more than one motion controller, it must create a Control object for each motion controller. The arguments to mpiControlCreate(...) associate a Control object with a specific motion controller.

A motion controller provides various types of resources, such as axis, digital-to-analog converter, data recorder, etc. Many of a motion controller’s resource types have multiple instances. For example, motion controllers provide multiple axes and DACs.

Most MPI objects are associated with a specific instance of a resource on a specific motion controller. An Axis object, for example, is associated with a single axis on a motion controller. When creating an MPI object that corresponds to a specific motion controller resource, the Create method takes an MPIControl handle as its first argument and a number as the second argument. The number argument identifies the specific motion controller resource to be used.

Example

The number argument of mpiAxisCreate(...) identifies an axis on the motion controller specified by the MPIControl handle argument.

For XMP only Number arguments, for those MPI objects that take them, start with 0 (not 1). For example, on an 8-axis XMP motion controller, valid axis numbers are 0 - 7.
Some MPI objects maintain a list whose elements are other MPI objects. The Create method for a list object generally takes a third argument that is a handle to an element object. The element object then becomes the first element of the list maintained by the list object. Specifying an element object is optional; if the handle (third argument) has value MPIHandleVOID, the list object will be created with an empty list.
Example The Motion object maintains an ordered list of Axis objects. This ordered list of Axis objects defines a motion coordinate system. The third argument to mpiMotionCreate(...) is an Axis handle (MPIAxis). If the Axis handle is valid, then the Axis object (that the handle points to) will be made the first axis in the motion coordinate system.
All MPI objects provide a method to return the value of each of its Create method arguments. These methods serve to identify the object. For more detail, see Identity Methods on page 1-47.

mpiObjectDelete(...)

Use the Delete method to delete an object created by the Create method. After an object has been deleted, the handle to that object can no longer be used.

If a method attempts to use a handle to a deleted object, it returns MPIMessageObject_FREED, but not always. If the memory originally allocated for the deleted object is subsequently allocated for a different purpose, then the method will not return MPIMessageObject_FREED.

Your application must ensure that handles to deleted objects are no longer used. After an object is deleted, your application should ensure that the handle to that object is set to MPIHandleVOID. After that, any calls to methods using this handle will return MPIMessageHANDLE_INVALID.

When your application exits, it should call Delete methods for all objects that have been created by your application. We recommend that your application delete objects in the reverse order in which they were created. Regardless, the Control object should be the last object deleted. The MPI does not provide the ability to automatically delete all of the objects that have been created.

Alternatively, to delete objects, your application may use the C library function atexit(...), which guarantees that the objects will be deleted even if the application terminates abnormally.

mpiObjectValidate(...)

Use the Validate method to “validate” an object created by the Create method. Your application should always call the Validate method immediately after calling the Create method. Afterwards, the Validate method can additionally be called at any time in an application.

If the object is valid, the Validate method will return MPIMessageOK. If the handle passed to the Validate method has value MPIHandleVOID, the Validate method returns MPIMessageHANDLE_INVALID. If a method attempts to use a handle to a deleted object, the method returns MPIMessageObject_FREED. (Also see the previous discussion in mpiObjectDelete(...)).

Other possible return values are declared in the message header file(MPI\include\message.h) and in the object’s header file (MPI\include\object.h).
Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Status Methods

Introduction | MPIStatus{...} Structure | MPIObjectStatus{...} Structure

Introduction

Status is read-only information that changes dynamically. Many objects define a Status structure and a method that uses that structure to return status to the application.

MPIStatus{...} Structure

The MPIStatus{...} structure contains information about the state of an axis or an entire motion. The Axis object and the Motion object return status using the MPIStatus{...} structure. Because the MPIStatus{...} structure is shared among objects, it is defined in the mpidef.h header file instead of being defined in an object header file.

For objects that involve more than 1 axis, the status returned by the motion object indicates the “sum” of the status conditions of the axes in its coordinate system. In general, the status structure gives an indication of whether an axis is moving or idle. The axis structure also indicates whether the axis is idle because of an error.

For MEI/XMP only The filter object (whose handle is of type MEIFilter) also returns status in MPIStatus{...}.

MPIObjectStatus{...} Structure

Objects that are not Axis and Motion objects return status using an object-specific Status structure defined in the object’s header file.

mpiObjectStatus(...)
For Axis and Motion objects, mpiObjectStatus(...) returns the object’s status using the object’s handle and a pointer to an MPIStatus{...} structure. For objects that are not Axis or Motion objects, mpiObjectStatus(...) returns the object’s status using the object’s handle and a pointer to an MPIObjectStatus{...} structure.

Object Methods | Configuration Methods | Memory Methods | Status Methods
| Event Notification Methods | List Methods | Identity Methods |


Sercos- Communications

Synchronization | Ring Timing | Initialization

Synchronization

The Master is responsible for sending a synchronization telegram (MST) at the beginning of each communication cycle. All Slaves (drives) will receive the MST and reset their clocks. In this way, all Slaves will run in phase lock with the Master’s clock. Because all Slaves are in phase lock with the Master’s clock, commands can be made active in all of the Slaves at the same instant. This means that the Master can coordinate motion between all axes without propagation effects distorting the motion profile. Feedback from the Slaves is handled in a similar manner, and is latched in all Slaves at the same instant.

Ring Timing

Data is sent and received by the Master and Slaves through communication telegrams. The communication telegrams are organized over the SERCOS cycle in the manner shown in the next figure.

The SERCOS ring timing is based on the data to be placed in the telegrams (AT, MDT), and on 6 drive parameters that are determined by the type and features of a drive (or drives), and 6 parameters that are written from the Master, with some of these parameters derived or calculated from the drive’s timing parameters. The times at which the MDT and AT are sent (relative to the sending of the MST) are determined by the Master and sent to the Slaves during initialization.

During Phase 2, the Master reads parameters from the drives that determine what and when the drives are able to transmit and receive. Using this information and the desired telegram contents, baud rate and cycle time, the Master determines the timing and telegram parameters for each drive. The Master then writes these parameters to the drives.
For a print-friendly version of the above diagram, click here.

Initialization

Before true synchronous data transmission can occur, the system must first be initialized. This is done through a series of communication phases (or just phases) in which data is first transmitted asynchronously. The data transmitted during these early phases is used to configure the Master and Slaves for synchronous data transmissions in later phases. The SERCOS protocol defines five phases.

Phase | Name | Action
0 | Ring Verification | Master verifies ring closure
1 | Device Verification | Master verifies devices on ring
2 | Telegram Set-Up | Master reads timing data from slaves and sets up telegram timing
3 | Device Parameterization | Master continues to configure devices
4 | Cyclic Operations | Master commands devices cyclically

On power-up, each drive or I/O module begins an initialization sequence. At this time, each drive and I/O module operates as a repeater, by simply passing received telegrams to the next device on the SERCOS ring.

The Master is only allowed to set the communication phase to the next logical communication Phase (Phase 0 -> Phase 1 -> Phase 2 -> Phase 3 -> Phase 4) or directly back to Phase 0. If at any time the Master attempts to switch a Slave into a Phase that is not the next logical Phase, then the Slave will immediately return to Phase 0. If at any time the Slave receives two invalid MSTs or MDTs consecutively, the Slave will also switch to Phase 0.
Phase 0:

During Phase 0 no data is exchanged between the Master and the Slaves. All Slaves must be in “repeater” mode. This means that each Slave will retransmit any signal that it receives. In order to verify that the communications ring is intact and capable of sending telegrams, the Master begins sending Master Synchronization Telegrams (MST) through the SERCOS ring.

The Slaves (drives) simply pass the MST to the next drive in the daisy-chained ring, and eventually because of the ring topology, the MST returns to the Master (i.e., Master will receive its own MST). Phase 0 is completed when the Master receives 10 consecutive MSTs. After the tenth consecutive MST, the Master changes the phase information in the MST to 1, which commands all Slaves to switch into Phase 1 operations.
Phase 1:

During Phase 1, the Master sends out an MDT with the address of a specific Slave in the system. If present within the system, the Slave with the specified address responds by sending an AT back to the Master. The AT that is sent is rudimentary and is intended solely as a confirmation that the addressed Slave is in the system. The Master then repeats this query for all target Slaves. (Note that not all Slaves in the system will be target Slaves. Target Slaves are chosen by the application before initialization begins.)

When the Master receives an AT from each target Slave (in response to a query), the Master changes the phase information in the MST to 2, which commands all Slaves to switch into Phase 2 operations.
Phase 2:

During Phase 2, the Master sets up the configurable data portion and calculates the duration and time slots within the SERCOS cycle for all telegrams to be used in Phases 3 and 4. The Master also determines the slave operation mode for all Slaves. In order to do this, the Master requires certain data from the Slaves. The Master obtains this data by sending an MDT addressed to a specific Slave, that uses the MDT’s Service Channel to query the Slave for the required data

The Slave responds by sending an AT containing the appropriate data, in the AT’s Service Channel. Once the Master has determined all parameters, it sends them to each Slave via the MDT’s Service Channel. In Phase 2, the Service Channel is active in both MDTs and ATs.

Once all data is transmitted to the Slaves, the Master will initiate the Communication Phase 3 Transition Check S-0-127 procedure for each Slave.

The Communication Phase 3 Transition Check checks the validity of all the data, and if all the data is valid, then the procedure executes successfully. If any data is not valid, the procedure fails and the IDN number of the invalid data is placed in IDN-List of Invalid Operation Data for CP2 S-0-21.

After all Slaves have completed the procedure successfully, the Master changes the phase information in the MST to 3, which commands all Slaves to switch into communication Phase 3.
Phase 3:

In Phase 3, the real-time synchronous and asynchronous communication starts, and the Master uses the Service Channel to configure and parameterize (write parameters to) the Slaves. The parameters set in Phase 3 are application-oriented (e.g., conversion factors). During Phase 3, all communication telegram parameters sent in Phase 2 become active. Note that although Configurable Data (in ATs and MDTs) is present in the communication telegrams, some of that Configurable Data may not be valid until Phase 4.

The Master will still send the MST at the beginning of the SERCOS cycle, but will now also send an MDT with a global address at a specific time (all Slaves will receive a global telegram). Each Slave will transmit its AT during its specified time slot. The communication telegrams now contain the Control/Status Word, a Service Channel, and the Configurable Data.

When the Master has finished sending parameters to the Slaves, it will initiate the Communication Phase 4 Transition Check S-0-128 procedure for each Slave.

The Communication Phase 4 Transition Check checks the validity of all the data, and if all the data is valid, then the procedure executes successfully. If any data is not valid, the procedure fails and the IDN number of the invalid data is placed in IDN-List of Invalid Operation Data for CP3 S-0-22.

If the Communication Phase 4 Transition Check executes successfully and the Phase information in the MST is equal to 4, the Master switches the drives to Phase 4.
Phase 4:
In Phase 4, a final verification of error-free drive operation is completed. This completes the drive initialization. The SERCOS communication loop is now operational. During Phase 4, all Control/Status words, Service Channels, and Configurable Data (in ATs and MDTs) are valid for the target Slaves. The Slaves (drives) are ready to follow commands when enabled. Diagnostics (errors, warnings, status) are enabled.
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Data Types

Summary | Data Block Structure | Data Block Structure of IDNs

              • Element 1: IDNumbers
              • Element 2: Name of Operation Data
              • Element 3: Attributes of Operation Data
              • Element 4: Operation Data Unit
              • Element 5: Minimum Input Value of Operation Data
              • Element 6: Maximum Input Value of Operation Data
              • Element 7: Operation Data

Summary

And datas in a slave that can be accessed by the host is represented by a data block. Data blocks are assigned identification numbers (IDNs or “ID numbers”). The data block consists of information about the data; for example, IDNumber, name, attributes, units, min and max values, and the operation data itself.

Data Block Structure

The SERCOS protocol is designed to handle many different types of data, characterized by two fundamental types: fixed length data and variable length data.

Fixed length data is either 2 bytes or 4 bytes wide and can be used to represent signed or unsigned integers, hexadecimal values, binary codes, IDNumbers (identification numbers) of other Data Blocks, and procedure commands.

The length of variable length data depends on what type of data is present, and is defined by the first two words (32 bits), which specify the actual and maximum length of the data. Variable length data can be used to represent character strings, lists of IDNumbers of Data Blocks, lists of signed or unsigned integers (both 2 or 4 bytes wide), lists of hexadecimal values, etc.

All data (fixed and variable length) can be sent or received via the Service Channel. However, only fixed length data is allowed to be configured into a communication telegram (MDT, AT). When a communication telegram is configured to send or receive fixed length data, it is only Element 7 data that will be either sent or received.

Data Block Structure of IDNs

Data is accessed through data blocks referred to as IDNs. An IDN consists of seven elements:
Element 1 | IDNumber
Element 2 | Name
Element 3 | Attribute
Element 4 | Unit
Element 5 | Minimum Input
Element 6 | Maximum Input
Element 7 | Operation Date
All data exchanged between Master and Slaves has an IDNumber (IDN number) assigned to it. Every IDN has an associated data block which consists of seven elements. The Master can only write Element 7 data; the Master cannot write Elements 1 - 6. Elements 1 - 6 are defined by the drive itself.
Element | Description | Data Type
1 | IDNumber (Identification number) | binary Expressed as either S-X-XXXX or P-X-XXXX. S denotes IDNs that are defined by the SERCOS Specification. P denotes IDNs that are defined by the manufacturer of the device.
2 | Name | variable length string Contains the name of the IDN.
3 | Attribute | 32 bit binary Contains information about conversion factors and data representation (signed or unsigned integer, fixed or variable length data, etc.)
4 | Unit | variable length string Contains a representation of the units for the data.
5 | Minimum input value | 1 or 2 words
6 | Maximum input value | 1 or 2 words
7 | Operation Data | 1 or 2 words, or string

Element 1: IDNumbers

Each Data Block has a number assigned to it for identification purposes, called the IDNumber. The IDNumber is represented as either S-X-XXXX or P-X-XXXX. S denotes a Data Block that is defined by the SERCOS Specification. P denotes a Data Block that is defined by the manufacturer. The first ‘X’ identifies the “data set” that the Data Block belongs to. According to the SERCOS Specification, it is possible to switch between data sets.

Bits | Name | Values
15 | Type of IDN | 0 S - Standard data 1 P - Product-specific data as the “S” or “P” part of the IDN notation S-y-zzzz or P-y-zzzz.
14-12 | Parameter Set | 0 - 7, as the “y” part of the IDN notation S-y-zzzz or P-y-zzzz.
11-0 | Data Block Number | 0 - 4095, as the “zzzz” part of the IDN notation S-y-zzzz or P-y-zzzz.

Element 2: Name of Operation Data

The name of operation data is 64 bytes maximum, with 2 length specifications of 2 bytes each, and a character string of 60 characters maximum. Bytes 1 and 2 contain the number of characters in the text. Bytes 3 and 4 contain the maximum number of characters in the text. Since this element is READ-Only, bytes 3 and 4 will contain the same values as bytes 1 and 2.

Element 3: Attributes of Operation Data

Every data block has an attribute (4 bytes) which contains all of the information required to display operation data, using universal routines. If data needs to be scaled (to be displayed), then specific scaling parameters are supplied in the attribute.

Bits | Name | Values
31 | Reserved |
30 | Phase 4 write-protection bit. | 1 = write-protected
29 | Phase 3 write-protection bit. | 1 = write-protected
28 | Phase 2 write-protection bit. | 1 = write-protected
27-24 | Number of places after the decimal point Indicates the position of the decimal point in the data to be displayed. Basically, it’s the exponent “x” in 10-x. | 000 No places after decimal point 001 1 place after decimal point 010 2 places after decimal point * 111 15 places after decimal point
23 | Reserved |
22-20 | Data Type & Display Format Used to convert the operation data, and min/max input values to the correct display format. | Data Type 000 binary number 001 unsigned integer 010 integer 011 unsigned integer 100 extended char set 101 unsigned integer 010 Reserved 111 Reserved | Display Format binary unsigned decimal signed decimal hexadecimal text IDN number
19 | Function of Operation Data Indicates whether this data calls a procedure in a drive | 0 Operation data or parameter 1 Procedure command
18-16 | Data Length The data length is required so that the Master is able to complete Service Channel data transfers correctly. | 000 Reserved 001 Operation data is 2 bytes long 010 Operation data is 4 bytes long 011 Reserved 100 Variable length with 1-byte data strings 101 Variable length with 2-byte data strings 110 Variable length with 4-byte data strings 111 Reserved
15-0 | Conversion Factor | An unsigned integer used to convert numeric data to display format. Is set to 1 when it is not needed for data display (e.g., binary display or a character string).

Element 4: Operation Data Unit

The operation data unit is 16 bytes maximum, with 2 length specifications of 2 bytes each, and a character string of 12 characters maximum. Bytes 1 and 2 contain the number of characters in the text. Bytes 3 and 4 contain the maximum number of characters in the text. Since this element is READ-Only, bytes 3 and 4 will contain the same values as bytes 1 and 2.

Element 5: Minimum Input Value of Operation Data

The minimum input value is the smallest numerical value for operation data that the drive can process. When the Master writes a value to the drive that is less than the minimum value, the drive ignores it and continues to use the previous operation data.

When the operation data is of variable length or a binary number is used, there is no minimum input value of operation data.

Element 6: Maximum Input Value of Operation Data

The maximum input value is the largest numerical value for operation data that the drive can process. When the Master writes a value to the drive that is more than the maximum value, the drive ignores it and continues to use the previous operation data.

When the operation data is of variable length or a binary number is used, there is no maximum input value of operation data.

Element 7: Operation Data

In terms of length, there are 3 types of operation data:

    • fixed length with 2 bytes
    • fixed length with 4 bytes
    • variable length up to 65,532 bytes in 1 byte (char), 2 byte, or 4 byte values

Bytes 1 and 2 contain the number of bytes in the text. Bytes 3 and 4 contain the max number of bytes available in the text. Data in the text may be 1 byte, 2 bytes, or 4 bytes wide.
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Overview

Summary | Operation Modes | Closed-Loop Tuning | Data Transmission

Summary

SERCOS (SErial Real-time COmmunication System) is the international standard for optical communication between motion control units and drive modules. It was developed by the International Electrotechnical Commission (IEC) specifically for motion control and is defined by the IEC 1491 standard. SERCOS supports data rates up to 16 Mbits/sec over a fiber optic ring. Data can be transmitted deterministically in real time based on the loop update rate (cyclic), or at lower bandwidths for less critical operations (non-cyclic). A SERCOS-compatible communication ring must have a single controller (master) and 1 - 254 drive or I/O modules (slaves).

Also, data communication can be performed in either a synchronous or asynchronous manner. The protocol allows the user to configure the communication telegrams to send whatever data is appropriate synchronously. Data that has not been configured to reside in the communication telegrams can be sent or retrieved asynchronously by use of a Service Channel contained within the communication telegrams. Generally, synchronous data is data that is critical to real-time operation (e.g., command and feedback data, status).

SERCOS is a unidirectional serial communications protocol for connecting multiple drives (Slaves) to a motion controller (Master) over a fiber optic ring, in an industrial environment. The control and status information is organized into telegrams, and travels in a serial data stream around the SERCOS ring. All messages are synchronized according to the SERCOS cycle time, the timing of which is configured during initialization by the Master. Each Slave on the ring repeats the telegrams sent to it, sending them to the next device on the ring, and inserting its own telegram into the designated time slot in the serial data stream.

Starting at the output port of the Master, the devices are connected in the ring in a daisy-chain fashion, connecting from the output port of one device to the input port of the next device, and so on, until the ring is closed back at the input port of the Master. Up to 254 drives can be connected on a SERCOS ring, although the systems requirements for update rates and data will usually limit the number of devices to many fewer than that. SERCOS networks can operate at 2, 4, 8 or 16 Mbit/sec. Maximum distances from input port to output port can be 60 meters (plastic fiber) to 250 meters (glass fiber).

Operation Modes

The SERCOS communication interface supports three main operation modes (Torque, Velocity and Position). The operation mode defines the real-time digital messages sent between the controller and the drive(s).

Mode | To Drive | To Controller
Torque | 16 bit Command Torque | 32 bit Actual Position
Velocity | 32 bit Command Velocity | 32 bit Actual Position
Position | 32 bit Command Position | 32 bit Actual Position

In addition to the main operation modes SERCOS supports several variations. Since the communication interface is determined by the firmware/software in the controller and the firmware/software in the drive, the real-time data is configurable.

Currently the SERCOS/XMP Series firmware/software supports several operation modes. Some operation modes are drive specific while others are drive independent. Motion Engineering is constantly testing and certifying compatibility between our controller and SERCOS-compatible drives.

Most drives support the three main operation modes (Torque, Velocity and Position). Please consult your drive specific documentation regarding supported operation modes and variations.

In all modes, the controller calculates a 32-bit command position every sample. The command position is based on the current command jerk, command acceleration and command velocity.

In Torque mode, the controller sends a 16-bit command torque to the drive. The drive sends a 32-bit actual position back to the controller. Every sample, the controller calculates a new command torque based on the position error and the control algorithm. The controller closes the position and velocity loop and the drive closes the torque loop.

In Velocity mode, the controller sends a 32-bit command velocity to the drive. The drive sends a 32-bit actual position back to the controller. Every sample, the controller calculates a new command velocity based on the position error and the control algorithm. The controller closes the position loop, and the drive closes the velocity and torque loop.

In Position mode, the controller sends a command position to the drive. The drive sends a 32-bit actual position back to the controller. Every sample, the controller calculates a new command position. The drive closes the position, velocity and torque loop.

Closed-Loop Tuning

A general difference between SERCOS digital drives and conventional analog drives is that digital drives have on-board intelligence and can close position or velocity loops within the drive. In all operation modes, “tuning” requires setting parameters in the drive and the controller. Thus, an understanding of both the controller and drive control algorithm is necessary for successful drive tuning.

The controller tuning parameters can be set using Motion Console (for Windows-based systems). For more information on the controller’s tuning procedures, please consult the Tuning section in the XMP Motion Controller Hardware Installation manual.

The drive’s tuning parameters must be set via IDNs, and the values are determined from information supplied by the drive manufacturer. Please consult the drive-specific documentation for more information on the drive’s tuning parameters. While Motion Engineering has considerable experience with the listed drives and can generally offer tuning guidelines for drive parameters, difficult tuning situations may require support from the drive vendor or manufacturer.

In Velocity mode, the controller’s CONTROL ALGORITHM output controls the motor’s velocity. Therefore, the drive’s velocity loop must be tuned and the controller’s position loop must be tuned. The tuning procedure is identical to a standard analog output XMP Series controller connected to a velocity-controlled amplifier. Note that the controller’s Velocity Feed Forward term is very useful in velocity-controlled systems.

In Position mode, the controller’s control algorithm is not used. The drive is responsible for the closed loop control. Therefore, the drive’s velocity and position loop must be tuned. The controller’s tuning parameters have no effect on the system’s response.

Data Transmission

SERCOS supports two types of data transmission, cyclic and non-cyclic.

Cyclic data is the critical real-time synchronized data sent between the Master and the Slaves (drives, I/O modules). In every SERCOS cycle, the Master sends and receives fixed-length messages to the drives and I/O modules. These messages contain the motion control command signal and the feedback response for each drive or the digital I/O commands and responses for each I/O module. The cyclic data is guaranteed to reach each drive and I/O module and return to the Master at a fixed time interval, the SERCOS cycle.

Non-cyclic data is the noncritical asynchronous data. The cyclic fixed-length messages have space (called the Service Channel) reserved for non-cyclic data. In each SERCOS cycle, the Master may transmit two bytes of non-cyclic data through the Service Channel to each Slave. Note that it may require several SERCOS cycles for the Master to complete the transmission of the non-cyclic data to the Slaves. Typically, transmitting non-cyclic data is much slower than cyclic data.

SERCOS cycles are built using telegrams, which in turn contain data records for all of the Slave drives. Cyclic data is transferred in the cyclic data part of the data records. Non-cyclic data is transferred in the Service Channel of data records. Refer to the next figure.
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Procedures

Summary

Many Slaves (drives) come with preprogrammed procedures that the Slave is able to execute without assistance from the Master. Each of these procedures is assigned a Data Block. The Master controls a procedure by reading and writing to Element 7 of the procedure’s Data Block. The Master can initiate, interrupt, or cancel a procedure at any time by setting or clearing bits in Element 7 of the procedure’s Data Block.

Bits 0 and 1 are responsible for respectively setting and enabling the procedure command. Once set and enabled, the Slave will begin execution of the procedure. To indicate that the procedure is executing, the Slave sets bit 2 of the procedure status word. When the procedure has finished executing, the Slave clears bit 2 of the procedure status word and sets the Procedure Command Change Bit in the Drive Status Word S-0-134. If an error has occurred when executing the procedure, the Slave will set bit 3 of the procedure status word and will also set the Procedure Command Change Bit in the Drive Status Word S-0-135. In either case (successful execution or failure), the Master must cancel the procedure by clearing bits 0 and 1 of the procedure.

In SERCOS, in order for a Master to execute a procedure,

      1. The Master writes 0x3 to Element 7 of the desired IDN procedure, which sets and enables the procedure.
      2. The Master reads the procedure status word and checks bits 2 & 3 to see if the procedure has finished executing or if there is an error.
      3. After reading that the procedure has executed, the Master writes 0x0 to Element 7 of the particular procedure, which cancels the procedure.
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Communications; Ring Timing diagram

 Sercos Communications: Ring Timing Diagram


Sercos- Introduction

About SERCOS | Supported Drives

About the MEI SERCOS Controller

The SERCOS/XMP Series controllers from MEI are an extension of the XMP Series motion controllers. XMP Series motion controllers support analog motion control outputs, encoder inputs, and discrete digital I/O. SERCOS/XMP Series motion controllers replace these signals with the SERCOS digital fiber optic network interface. The SERCOS interface only requires two fiber optic connections (one output and one input) to connect to a fiber loop containing up to 8 axes of motion.

Both SERCOS and standard XMP Series controllers share the same basic hardware architecture, onboard firmware, host software and many other features. So, for controller installation procedures, Motion Console application and C programming information, use the XMP’s standard documentation.

However, because the SERCOS IDNs are actually implemented in the drive (and not in the controller), there are many SERCOS functions not documented in the XMP documentation, because they are in the drive’s documentation (because these functions are associated with the drive and not the controller). Motion Engineering adheres to the specifications set forth by the IEC concerning SERCOS. For more information regarding SERCOS or the SERCOS specification, please contact SERCOS N.A at www.sercos.com.

Supported Drives / Modules

MEI currently supports drive and I/O modules from a variety of manufacturers. If you desire support for a drive or I/O vendor not listed, please contact MEI.

Manufacturer | Device
Indramat | Servo Drives
Modicon | Servo Drives
Lutze | Digital I/O Modules
Pacific Scientific | Servo Drives
Kollmorgen | Servo Drives
Sanyo Denki | Servo Drives
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Telegrams

Summary | BOF Delimiter | ADR Target Addresses | Message Field
FCS (Frame CHeck Sequence) | EOF (End of Frame) Delimiter | Data Record
Master Synchronization Telegram | Master Data Telegram | Amplifier Telegram

Summary

The controller (Master) communicates with the drives and I/O modules (Slaves) using telegrams. A telegram is a structure that contains data, error checking and handshaking information. SERCOS supports three types of telegrams: Master Synchronization Telegram (MST), Master Data Telegram (MDT), and Amplifier Telegram (AT).

Each type of telegram contains 5 types of fields: BOF (beginning of frame), ADR (address), message field, FCS (frame check sequence), EOF (end of frame).

BOF Delimiter

All telegrams have a BOF (beginning of frame) byte denoting the beginning of the telegram. The BOF is always 0111 1110.

ADR Target Addresses

All telegrams have an ADR (address) byte, which denotes the address of a drive (Slave). In a telegram from the Master, the address specifies which drive the information is for. In a telegram from a Slave (drive), the address specifies the sourcing drive. The target addresses for the drives are valid if greater than 0 and less than 255. Typically, a drive’s address is set using a selector located physically on the drive.

Address 0 is the “no station” address, and is sometimes used to remove a drive from the ring logically, during troubleshooting. During non-cyclic operations (Phases 0 - 2), the Master can only communicate with one drive per cycle. During cyclic operations (Phases 3, 4), the Master can communicate with all drives.

From | To | Telegram | Non-Cyclic (Phases 0,1,2) | Cyclic (Phases3,4)
Master | Slave | MST | 255 | 255
Master | Slave | MDT | 1 < ADR < 255 | 255
Slave | Master | AT | 1 < ADR < 254 | 1 < ADR < 254

Message Field

Each Telegram (MST, AT, and MDT) contains a message field. The Message Field for the MST consists of one 8-bit word. The lower three bits of the MST contain Phase information. The Message Field for the AT consists of one Data Record. The Message Field for the MDT consists of one Data Record if the MDT’s target address is a specific drive. If the MDT’s Target address is all drives (255), then the Message Field for the MDT consists of one Data Record per drive in the system.

FCS (Frame Check Sequence)

All telegrams have a two-byte FCS number used to check data integrity. The frame check sequence (16 bits) is implemented according to ISO/IEC 3309, 4.5.2.

EOF (End of Frame) Delimiter

All telegrams have an EOF byte denoting the end of the telegram. The EOF is always 0111 1110.

Data Record

Data Records are used by both the Amplifier Telegram (AT), and the Master Data Telegram (MDT) to send data. Generally, a Data Record consists of a 16-bit Control/Status word, a 16-bit Service Channel, and a Data Block of 16-bit words.

Amplifier Telegrams contain only one Data Record, because each Slave sends its own Amplifier Telegram.

During Phase 2, the Master sends a Master Data Telegram that is addressed to a specific Slave. Since only one Slave is to receive the MDT, the Phase 2 MDT has only one Data Record. During Phases 3 and 4, the Master sends a Master Data Telegram that is received by all Slaves on the ring. Since all Slaves receive the Master Data Telegram, the Phase 3-4 MDT has one Data Record for each Slave.

During Phase 2, the Data Block in both the AT and the MDT has a length of 0. This means that all data exchange between Master and Slave must take place using the Service Channel. Because the Service Channel is only 16-bits wide, data exchange can take multiple cycles. Service Channel exchange of data is referred to as non-cyclic.

During Phase 2, the Master is responsible for determining the data fields for the Data Blocks in the Phase 3-4 AT and MDT. The size and number of data fields will determine the size of the Data Block. Once defined in Phase 2, the fields and therefore the size of the Data Block is fixed. The data fields in the MDT usually contain command data. The data fields in the AT usually contain feedback data. Because the Data Blocks are configured in Phase 2, there is no overhead using the Data Blocks to send data in Phases 3 and 4. Data exchange using the Data Blocks is referred to as cyclic.

Master Synchronization Telegram

The Master Controller uses master synchronization telegrams (MST) to coordinate its transmission cycle timing with the Slaves. The Master initiates a SERCOS cycle by transmitting an MST to all of the drives and I/O modules on the ring.The MST message field contains one 8-bit word, of which the three lowest bits determine the communication phase of the system. The MST is sent at the beginning of the SERCOS cycle in all communication phases.

Field | Bytes | Description
BOF ADR | 1 1 | Beginning of Frame. The BOF marks the start of a telegram. The target address. In the MST, ADR = 255 (the broadcast address) during Phases 3 and 4.
Current Phase | 1 | The lower 3 bits designate the SERCOS phase (0 - 4)
FCS EOF | 2 1 | Frame check sequence. The FCS field contains circular redundancy check (CRC) information. End of Frame. The EOF marks the end of the telegram.

Master Data Telegram

During Phase 2, the Master must communicate with the Slaves in order to configure them for operations in Phases 3 and 4. In order to send or request data, the Master will send a Master Data Telegram (MDT) to a specific Slave (the Slave is addressed explicitly). Since only one Slave is to receive the MDT, the MDT Message Field contains only one Data Record, where the length of the Data Block (inside the Data Record) is 0, i.e., the data block is empty. During Phase 2, the Master sends data to each Slave via the Service Channel.

During Phase 2, the Master informs the Slave of the byte offset into the MDT at which the Data Record resides for that Slave. The length (in bytes) of the Data Block within each Data Record depends on the data fields configured by the Master during Phase 2. The data fields within the Data Block usually contain command information.

During Phases 3 and 4, once per SERCOS cycle the Master sends a Master Data Telegram (MDT) that has a global (broadcast) address. Because the global address is used, all Slaves receive the MDT. Since all Slaves will receive the MDT, the MDT Message Field contains one Data Record for each Slave in the system. During Phases 3 and 4, data is sent to a Slave by using the Data Blocks (cyclic) or the Service Channel (non-cyclic).

Field | Size (bytes) | Description
BOF | 1 | Beginning of Frame, which is always 0111 1110. The BOF marks the start of a telegram.
ADR | 1 | Target address. In the MDT, ADR = 255 (the broadcast address).
*Control Word | 2 | Control word for drive n. Contains operational data.
*Service Info | 2 | Contains the non-cyclic data for drive n.
*IDN Commands | Variable ** | Contains the cyclic data for drive n.
FCS | 2 | Frame check sequence. Contains circular redundancy check (CRC) info.
EOF | 1 | End of Frame, which is always 0111 1110. The EOF marks the end of the telegram.
* These fields comprise the data record. There is one data record per drive in the MDT.
** The length if the IDN Commands field is determined during Phase 2

Bit | Name & Value | More Detail
15 | 0 Drive OFF 1 Drive ON | Bit 15-13=111, the drive should follow command values. When 1->0, the drive removes torque from the motor, and allows the motor to spin down.
14 | 0 Drive Disable 1 Drive Enable | When 1->0, torque is immediately disabled, independent of bits 15 and 13.
13 | 0 Drive Halt 1 Drive Restart |
12, 11 | Reserved |
10 | Control Unit Synchronization Bit |
9, 8 | Operation Mode 00 primary op mode 01 secondary op mode 1 10 secondary op mode 2 11 secondary op mode 3 | Defined byS-0-32 Defined by S-0-33 Defined by S-0-34 Defined by S-0-35
7 | Real-time Control Bit 2 | S-0-302
6 | Real-time Control Bit 1 | S-0-300
5, 4, 3 | Data Block Element 000 Service channel not active, 001 IDN (number) of the op data 010 Name of operation data 011 Attribute of op data 100 Units of op data 101 Min input value 110 Max input value 111 Operation data | -Close service channel or break a transmission in progress -The service channel is closed for the previous IDN and opened for a new IDN.
2 | 0 Transmission in progress 1 Last transmission |
1 | 0 Read service info 1 Write service info |
0 | Master Service Transport Handshake | A toggle bit

Amplifier Telegram

During Phase 2, the Slave sends an Amplifier Telegram (AT) only when it receives a Master Data Telegram (MDT) that contains that Slave’s address. The AT contains one Data Record where the length of the Data Block is 0, i.e., the data block is empty. During Phase 2, the Master sends data to each Slave via the Service Channel.

During Phases 3 and 4, each Slave sends an Amplifier Telegram (AT) every SERCOS cycle, at the time designated by the Master during Phase 2. The AT Message Field contains one Data Record, where the length of the Data Block (inside that Data Record) is determined by the data fields configured by the Master during Phase 2. The data fields within the Data Block usually contain feedback and status information.

During Phases 3 and 4, data is sent to the Master by using the Data Blocks (cyclic) or the Service Channel (non-cyclic).

Field | Size (bytes) | Description
BOF | 1 | Beginning of Frame. The BOF marks the start of a telegram.
ADR | 1 | sends address.
Status | 2 | Control word for drive n. Contains operational data.
Service Info | 2 | Contains the non-cyclic data for drive n.
Operation Data | Variable * | Contains the cyclic data for drive n.
FCS | 2 | Frame check sequence. Contains circular redundancy check (CRC) info.
EOF | 1 | End of Frame, which is always 0111 1110. The EOF marks the end of the telegram.
* The length of the Operation Data field is determined during Phase 2.

Bit | Name & Value | More Detail
15, 14 | Ready to operate 00 drive not ready for power-up 01 drive ready for power-up 10 drive power ready 11 drive ready to operate |
13 | Drive Shutdown Error, Class 3 Diags |
12 | Change Bit for Class 2 Diags |
11 | Change Bit for Class 3 Diags |
9,8 | Actual Operation Mode 00 primary op mode 01 secondary op mode 1 10 secondary op mode 2 11 secondary op mode 3 | Defined by S-0-32 Defined by S-0-33 Defined by S-0-34 Defined by S-0-35
7 | Real-time Status Bit 2 | See S-0-306
6 | Real-time Status Bit 1 | See S-0-304
5 | Change Bit Commands 0 No Change in Command Status 1 Changing Command Status |
4, 3 | Reserved |
2 | Error 0 No Error 1 Error in Service Channel | Error message is in drive’s Service Channel.
1 | Busy 0 Step Finished 1 Step in Progress |
0 | Master Service Transport Handshake | A Toggle bit
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies


Sercos- Application Topologies
Introduction | Overview | Data Types | Communications | Procedures | Telegrams | Topologies

Return to Software's Main Menu


Axis Tolerances and Related Events

MEIXmpStatusIN_FINE_POSITION | MEIXmpStatusIN_COARSE_POSITION
 MEIXmpStatusAT_TARGET | MEIXmpStatusAT_VELOCITY
MEIXmpStatusDONE

MEIXmpStatusIN_FINE_POSITION

During Normal Conditions (no Stop, E-stop, or Abort)
Between mpiMotionStart(...) and AT_TARGET, IN_FINE_POSITION is FALSE.

After AT_TARGET, the evaluation of the settling criteria begins. When the settling criteria has been satisfied, IN_FINE_POSITION is TRUE.

The settling criteria are:

    1. The absolute value of the position error is less than or equal to the fine position tolerance.
    2. The absolute value of the velocity is less than or equal to the velocity tolerance.
    3. Both of the above criteria has been satisfied for the settling time. Whenever either criteria 1 or 2 is not satisfied, IN_FINE_POSITION is cleared and the settling timer is reset.

During STOP
If settleOnStop is FALSE, IN_FINE_POSITION is FALSE.

If settleOnStop is TRUE and Feedrate != 0, IN_FINE_POSITION is FALSE.

If settleOnStop is TRUE and Feedrate = = 0, evaluation of the settling criteria begins.

After the settling criteria has been satisfied, IN_FINE_POSITION is TRUE.

During E-STOP
If settleOnEstop is FALSE, IN_FINE_POSITION is FALSE.

If settleOnEstop is TRUE and Feedrate != 0, IN_FINE_POSITION is FALSE.

If settleOnEstop is TRUE and Feedrate = = 0, evaluation of the settling criteria begins.

After the settling criteria has been satisfied, IN_FINE_POSITION is TRUE.

If both E-STOP and STOPoccur simultaneously
If both settleOnStop and settleOnEstop are FALSE, IN_FINE_POSITION is FALSE.

If either settleOnStop or settleOnEstop are TRUE and Feedrate != 0, IN_FINE_POSITION is FALSE.

If either settleOnStop or settleOnEstop are TRUE and Feedrate = = 0, evaluation of the settling criteria begins.

After the settling criteria has been satisfied IN_FINE_POSITION is TRUE.

Note

If STOP and E-STOP occur simultaneously, the XMP applies priority to the E-STOP. Both status bits will be true, but the motion will decelerate at the E-STOP rate.

During ABORT
IN_FINE_POSITION is FALSE.

If both E-STOP and ABORT occur simultaneously
During an E-Stop_Abort condition, IN_FINE_POSITION is FALSE (even if settleOnEstop is TRUE).

After mpiMotionAction(..., MPIActionRESET)
If IN_FINE_POSITION status is TRUE before RESET, the status will be unaffected (no event generated).

If IN_FINE_POSITION status is FALSE, the effect of RESET depends on the cause: If IN_FINE_POSITION is FALSE because:

  • the position error exceeds the tolerance, IN_FINE_POSITION will remain FALSE (no event generated).
  • the position error is within the tolerance but STOP is TRUE and settleOnStop is FALSE, IN_FINE_POSITION will become TRUE at settlingTime after the RESET call (event will be generated).
  • the position error is within the tolerance but E_STOP is TRUE and settleOnEstop is FALSE, IN_FINE_POSITION will become TRUE at settlingTime after the RESET (event will be generated).
  • the position error has been within the tolerance for settlingTime but ABORT is TRUE, IN_FINE_POSITION will become TRUE immediately after the RESET (event will be generated).

MEIXmpStatusIN_COARSE_POSITION

During Normal Conditions (no Stop, E-stop, or Abort)
The IN_COARSE_POSITION status bit can be set only during motion (defined from the return of mpiMotionStart(...) until MEIXmpStatusDONE is set for the following motion types:

  • S-Curve (final velocity = 0)
  • Trap
  • PT (after final point has been specified)
  • PVT (after final point has been specified)

For these motion types IN_COARSE_POSITION is TRUE whenever the absolute distance to the target (measured from the actual position to the final position) is less than or equal to the coarse position tolerance. If the target position is changed by mpiMotionModify(...) calls, IN_COARSE_POSITION may be set and cleared more than once (causing multiple events) during a single move.

IN_COARSE_POSITION is always FALSE for velocity moves (or moves using the FINAL_VEL attribute where the final velocity is non-zero).

During STOP, E-STOP, or ABORT
IN_COARSE_POSITION is FALSE.

After mpiMotionAction(..., MPIActionRESET)
IN_COARSE_POSITION is FALSE.

MEIXmpStatusAT_TARGET

There can be up to 2 filter outputs used in calculating the output level of the Motor command. The following expression is evaluated each sample to determine this output:

During Normal Conditions (no Stop, E-stop, or Abort)
The AT_TARGET status bit can be set only during motion (defined from the return of mpiMotionStart(...) until MEIXmpStatusDONE is set for the following motion types:

  • S-Curve (final velocity = 0)
  • Trap
  • PT (after final point has been specified)
  • PVT (after final point has been specified)

For these motion types AT_TARGET is TRUE whenever the command position is equal to to the target (final) position. If the target position is changed by mpiMotionModify(...) calls, AT_TARGET may be set and cleared more than once (causing multiple events) during a single move.

AT_TARGET is always FALSE for velocity moves (or moves using the FINAL_VEL attribute where the final velocity is non-zero).

During STOP, E-STOP, or ABORT
AT_TARGET is always FALSE.

After mpiMotionAction(..., MPIActionRESET)
AT_TARGET is always FALSE.

MEIXmpStatusAT_VELOCITY

During Normal Conditions (no Stop, E-stop, or Abort)
The AT_VELOCITY status bit can only be set during the constant velocity portions for the following move types:

  • Velocity
  • S-Curve (final velocity = 0)

The velocity settling criteria are continuously evaluated during the constant velocity portion of the motion. Once the criteria has been satisfied, the AT_VELOCITY bit is set to TRUE. AT_VELOCITY is FALSE during any non-constant velocity portions of the motion.

The velocity settling criteria are:

    1. The absolute value of the velocity error is less than or equal to the velocity tolerance.
    2. Criteria 1 has been satisfied for the settling time. Whenever Criteria 1 is not satisfied, AT_VELOCITY is set to FALSE and the settling timer is reset.

After Reset, Stop, E-stop, or Abort
After a Reset, Stop, E-Stop, or Abort, AT_VELOCITY is always FALSE.

MEIXmpStatusDONE

This status bit is set to TRUE whenever IN_FINE_POSITION is TRUE. It can be cleared only by mpiMotionStart(...).

After mpiMotionAction(..., MPIActionRESET)
DONE is always TRUE.
Return to Software's Main Menu


Compiling Program Sequencer Commands

An MPICommand will “compile” into one or more MEIXmpCommand{}s, each of which takes up a slot in the MEIXmpCommandBuffer{}. In general, an MPICommand will compile into a single MEIXmpCommand{}, but an MPICommand of type MPICommandTypeMOTION [with a motionCommand of MPICommandMotionSTART (i.e. mpiMotionStart(...))] will require several MEIXmpCommand{}s.

How many sequencer commands an MPI sequence command compiles to depends on the number of axes and number of positions in the move. The next table shows how many xmp sequencer commands it takes to do the equivalent of an mpiMotionStart(...).
Number of Sequencer Commands to be equivalent to mpiMotionStart(...)
Number of sequencer commands required | To do this:
axisCount + | One MEIXmpCommand{} per axis to write the axis number to MEIXmpLinkBuffer{}.MSLink[].Axis[].AxisNumber
1+ | 1 + One MEIXmpCommand{} to write axisCount to MEIXmpLinkBuffer{}.MSLink[].Axes
1+ | One MEIXmpCommand{} to write the MEIXmpMotionType{} to MS[].Mode.
(((axisCount*pointCount) + 3) / 4) + | One MEIXmpCommand{} for every four MEIXmpPoint{}s written to PointBuffer.Point[]
axisCount + | One MEIXmpCommand{} per axis to load the MEIXmpPoint(s)
1 | One MEIXmpCommand{} to start the motion


XMP Configuration

For a print-friendly version of the diagram below, click here.


XMP Configuration (page layout view)

XMP Configuration


Default XMP-Series Controller Configuration

Overview | Introduction | Software Components | Version Control
Automated Software Configuration | FAQs

Overview

The XMP-Series controller’s Flash memory is now pre-loaded at the factory with base firmware. This firmware contains a minimal amount of code to boot the DSP and allows the MPI to identify the XMP-Series controller. To operate the controller you will need to download the binary code included in this MPI software distribution. Please see the sections below for a complete description about software binary management and instructions to download firmware to your controller.

Introduction

System designers need to give careful consideration to the software configuration management procedures for their machines. To ensure machine consistency and quality, a process for software installation, configuration, version control, and verification must be implemented. Addressing this issue early in the development cycle will significantly reduce confusion and mistakes. Failure to implement some basic procedures can cause unknown machine configurations, costly field repairs/upgrades, mysterious intermittent problems, broken equipment, and possible injury.

The MPI and XMP-Series controllers contain several features to make configuration management easy. Please take the time to understand and implement these features before you begin development.

Software Components

The MEI software distribution contains several software components, which need to be loaded onto your machine and controller. The MPI DLL, header files, import libraries, device driver, utility programs, controller binaries, sample code, etc. These are all loaded onto your hard drive by the InstallShield distribution. Additionally, the controller contains on-board flash memory to store DSP code, FPGA code, and configuration information. You will also need to load the appropriate DSP (.bin) and FPGA (.fpg) code into your controller’s flash memory. The code is loaded into the DSP and FPGA(s) during power-on or when the controller is reset.

Version Control

Each software component has its own version number. These components have been tested together at the factory for interoperability.

The software version numbers have the following format:

Motion Console | NN.NN.nn | Major, Medium, minor
Motion Scope | NN.NN.nn | Major, Medium, minor
MPI DLL | YYYYMMDD.b...r | Year, Month, Day, branch,...rev
XMP Firmware | NNNnn | Major, minor
FPGA Code | RRR | Revision

The software has automated compatibility checking. If there is a compatibility problem between software components, an error code will be returned.

If an application (Motion Console and Motion Scope are applications too) and MPI DLL are NOT compatible, the error message "Control: application not compatible with MPI DLL" will be returned. To correct this problem, you can recompile your application with the appropriate MPI import library OR install the proper MPI DLL.

If the MPI DLL and firmware versions are NOT compatible, the error message, Control: firmware version mismatch will be returned. The user or application must download the appropriate firmware to correct the problem. The DLL and firmware versions can be determined with the version.exe utility, Motion Console, or application code.

If the controller flash memory has NOT been configured, the error message Control: no firmware found (factory default) will be returned. To correct this problem, the user or application must download the appropriate XMP firmware and FPGA images. Firmware and FPGA images can be downloaded from Motion Console, flash.exe, or application code.

For example, if Motion Console detects that the controller is in the factory default configuration (no firmware) or if the MPI DLL is not compatible with the firmware, it will prompt the user to download firmware:

Click Yes. Motion Console will then prompt you for the firmware file:

Click Browse and select the appropriate firmware file (.bin). The firmware is stored in the mei\xmp\bin directory (by default):

Select the proper file and click Open.

Automated Software Configuration

During the development stage of your machine, several different versions of MPI DLLs and/or XMP firmware might be used. You may want to upgrade to new releases in order to take advantage of new features. MEI may provide custom features or bug patches for previous releases.

During the production stage of your machine, you will want to guarantee software configuration consistency. MEI recommends using the InstallShield release package, a third party installer program, or batch scripts to install your application code and MEI’s software onto your machine.

You will also want to guarantee that the controller’s flash memory configuration is consistent. To load the flash, you could automatically download firmware (.bin) and FPGA (.fpg) code during software installation OR during your application initialization. For example, the flash.exe program could be executed from an installer or batch script during software installation. Included in the XMP\Apps directory, is a sample program called initFlsh.c that demonstrates how to read the controller’s firmware/FPGA versions, check if they match the desired configuration, and download the correct versions (if needed).

Also, you can create your own custom firmware file by saving configurations to flash, and uploading the firmware file to your hard drive. The firmware contains a userVersion field, so you can keep track of your custom configured files. Using this technique, the firmware can be configured with Motion Console, uploaded to a file (myfirm.bin) and downloaded to future machines using Motion Console, flash.exe or your application.

FAQs

Why do I need to download firmware to my controller?
Only the machine developer knows which firmware version and configuration works with their application. By downloading firmware directly, you have complete control over your development and release versions.

Why can’t MEI download firmware to my controller at the factory?
MEI can download your firmware, but it is expensive and causes several problems:

1. You would need a custom part number for each controller with a different firmware image. Even if you use the same controller hardware in several machines, each version would need to be ordered, purchased, tracked, and stocked separately.

2. Changing a firmware image (version or configuration) would require a new part number. This causes transition problems between “old” and “new” parts.

3. Repairs and replacements are much more complicated.

4. Field upgrades are not possible. Controllers must be returned to the factory to receive new firmware and a new part number.

What if I need to upgrade software in the field?
If you configure the flash memory as part of your application or installation, then it is very easy to upgrade software and/or firmware in the field. If you do not, then you’ll need to manually update the flash memory.

Can I modify the FPGA (.fpg) files?
No. These files are binary and do not contain any configuration data.


About Homing

Capturing position is central to the concept of homing (even for Sercos XMPs). The HOME event is triggered by the Capture Status instead of the Home Input (Motor[].IO.DedicatedIN.IO). Also note that each motor has its own default Capture Register (see the separate tip about capture numbering).

Currently the only configurable capture parameter (mpiCaptureConfigSet(...)) is captureConfig.trigger. CaptureConfig.trigger indicates which inputs are used for capturing (trigger.mask) and what polarity these inputs must be (trigger.pattern) to trigger a capture (HOME) event.

For non-Sercos XMPs, you can use 7 inputs to capture position: Home, Index, Positive and Negative Overtravel, and the three Transceiver inputs. These 7 inputs can be combined in a wide variety of ways, but the most useful are the Home and Index combination. Some designers also like to use Overtravel and Index combinations, and there is no problem doing this for non-Sercos drives.

For Sercos drives the selection is more limited. Only Index truly captures position, but all combinations of Home and Index can be used to cause a HOME event.

After a Capture object has been configured, capturing is controlled by mpiCaptureArm(...). To put the capture latch in the armed state, call mpiCaptureArm(...) with a TRUE arm parameter.

Actual position capturing will then occur if the capture criteria (defined by trigger.mask and trigger.pattern) is true (for at least 100 nsec) following a period where the criteria is false (for at least 100 nsec). To disable capturing, call mpiCaptureArm(...) with a FALSE arm parameter.

Note that capture will not occur (for non-Sercos motors) if the capture criteria is already TRUE when mpiCaptureArm(...) is called. Capture will only occur if the criteria goes FALSE, and then returns to TRUE.


Host-Based and Controller-Based Motion

Host-Based Motion | Controller-Based Motion | Sequence

Host-Based Motion

Basic Motion

NOTE: The terms “Control object” and “Controller” designate the same thing: a Control object.

To perform a simple motion using the XMP controller requires as few as eight basic steps:

    1. Create a Control object
    2. Initialize the Control object
    3. Create an Axis Object
    4. Create a Motion Object
    5. Append an Axis to a Motion object’s list (of axes)
    6. Start the Motion Check the Status of the Motion
    7. Delete the Objects

In more detail,

    1. Create a Control Object: Use mpiControlCreate(...) to create a Control object. You should only create one and only one Control object per board per process. The Control object controls all of the operating system resources for the actual board. You must create a Control object before creating any other objects.
    2. Initialize the Control Object: Use mpiControlInit(...) to initialize a Control object. mpiControlInit(...) establishes contact with the device driver, and maps the XMP’s memory space to the application’s memory space. An application can call mpiControlInit(...) more than once, but it isn’t necessary.
    3. Create an Axis Object: Use mpiAxisCreate(...) to create an Axis object, by passing a Control object handle and Axis number to it.
    4. Create a Motion Object: Use mpiMotionCreate(...) to create a Motion object, by passing a Control object handle and a Motion Supervisor (number) to it. Each motion object maintains a list of axes, which defines a coordinate system (specified by the number and order of the axes).
    5. Add an Axis to a Motion object’s list (of axes): Use mpiMotionAxisAppend(...) to associate an Axis with a Motion. The association is done by appending the Axis to a Motion object’s list of axes. Note that the Axis must be located on the same controller (board) as the Motion object.
    6. Start the Motion: Use mpiMotionStart(...) to start a Motion.
    7. Check the Status of the Motion: Use mpiMotionStatus(...) to determine if the current motion has completed yet.
    8. Delete the Objects: Use mpiObjectDelete(...) methods to delete the objects. We recommend deleting objects in the reverse order of creation. For this example, you would perform the object deletions in the order: Motion first, then Axis, then Control. Note that for any application, the Control object must be deleted last.

Controller-Based Motion

Motion Command
The XMP controller’s firmware uses a state machine for controller-based motion. The motion state machine has three states (Moving, Idle, Error). Transitions between states occur after a command (Start, Resume, Modify, Stop, E-Stop, Abort, Reset) or after an event (Done, Amp_Fault, Limits).
MPIEvents are generated by the XMP controller. MPIEvents (axis events) cause MPIActions to be generated. The MPIActions in the table are the default values and can be changed. Valid MPIActions for events are None, Stop, EStop, Abort.
MPIEventType | MPIAction (Default) | Event Trigger
AMP_FAULT | ABORT | Polarity (I/O bit Hi/Lo)
HOME | STOP | Polarity (I/O bit Hi/Lo)
LIMIT_HW_POS | ESTOP | Polarity (I/O bit Hi/Lo)
LIMIT_HW_NEG | ESTOP | Polarity (I/O bit Hi/Lo)
LIMIT_SW_POS | ESTOP | Position
LIMIT_SW_NEG | ESTOP | Position
LIMIT_ERROR | ABORT | Error [= absolute value (command position - actual position)]

MPIActions can come from the host or the firmware. For safety, there are 4 guaranteed restrictions on who can generate certain MPIActions:

    • The firmware can never issue Start. (Never 1 in table)
    • The firmware can never issue Resume. (Never 1 in table)
    • The firmware can never issue Reset. (Never 1 in table)
    • The host can never issue Done. (Never 2 in table)

    1 = Start/Resume/Reset can never be issued from the firmware; Start/Resume/Reset can only be issued from the host.
    2 = Done can never be issued from the host; Done can only be issued from the firmware.
MPIAction | Originating from Host | Originating from XMP Firmware
Start
Resume
Reset
Stop 		mpiMotionStart(...) mpiMotionResume(...) mpiMotionReset(...)
mpiMotionStop(...) 		Never 1
Never 1
Never 1
Event
E_Stop
Abort 		mpiMotionEStop(...) mpiMotionAbort(...) Event
Event
Done | Never 2 | If Settled and In_Position

1 = Start/Resume/Reset can never be issued from the firmware; Start/Resume/Reset can only be issued from the host.
2 = Done can never be issued from the host; Done can only be issued from the firmware.

Sequence

A Sequence consists of a linked list of Commands. Execution of a Sequence can be started, stopped, or its status queried. Execution of a Sequence begins with the first Command in the sequence and proceeds sequentially, unless otherwise commanded (e.g., a branch command). Execution of a Sequence ends when the last Command in the sequence is executed, or when the execution is stopped by the host.

An XMP can be controlled directly by the host or controlled by commands that the host downloads (for independent execution by the XMP firmware). Downloaded commands are managed by a firmware object known as a Program Sequencer (PS).
For the XMP, there are currently 16 Program Sequencers and a single command buffer that holds 256 commands. Each Sequence is created with a maximum command count, but the total command count for all Program Sequencers cannot exceed 256 commands.
The XMP commands can be thought of as a machine language for a virtual RISC processor (Reduced Instruction Set Computer) implemented by the XMP firmware. Similarly, a Program Sequencer can be thought of as an operating system thread, with the PS command buffer considered as a page of virtual memory for the thread. Each PS maintains the location within its command buffer of the next command to be executed, i.e., a program counter. The XMP firmware time-slices the PS “threads” by executing a command in every active PS, on every firmware cycle. When the next command to be executed is not located in the PS command buffer, a host interrupt is generated (i.e., a page fault occurs). The host is then expected to fill the PS command buffer with the next batch of commands. This method allows command sequences to be of any length.

The Motion Programming Interface (MPI) provides a layer of abstraction on top of the XMP Program Sequencer. The MPI Sequence object maintains a list of MPI Command objects. Commands exist to perform motion, compute/load/store data, branch-on/wait-for conditions (arithmetic, logical, I/O bits, events), delay, generate user-defined events, etc. There are a variety of command types, each with type-specific command parameters. The high-level language defined by these commands makes use of MPI objects, and allows for simple expressions with operands (that can be specified by value or by reference). A command can have a text label so that the command itself can be the target of a branch command.

When you create a Sequence, you specify the desired XMP PS command buffer size. Specifying a PS command buffer size of -1 will cause all remaining command buffer space to be allocated. After creating a Sequence, you typically create and append Command objects to the Sequence, and a Sequence can have any number of Command objects appended to it. When the Sequence is started, the Commands are “compiled” into XMP commands and loaded into the PS command buffer for execution.

When the XMP firmware does not find the next command to be executed in the command buffer, the firmware generates a host interrupt. This interrupt is handled by the MPI EventMgr, which then calls the Sequence to load the next batch of commands down to the Program Sequencer; your application does not have to do anything.


How Motion Completion Events are Generated

There are three types of generated events related to motion completion: DONE, AT_VELOCITY, and IN_POSITION_COARSE. Motion completion for a position move is indicated by a DONE event, while motion completion for a velocity move is indicated by an AT_VELOCITY event.

AT_VELOCITY is not generated for position moves. For both position moves and velocity moves, the MPI uses a settling time window to determine when to generate a motion completed event (to indicate that motion has finished on an axis).

For position moves, the MPI uses the settling time window to determine when an axis has reached the final target location and is stable.

For velocity moves, the MPI uses the settling time window to determine when an axis has reached the final velocity. This works because during ringing, the velocity is highest when the position error is lowest. (Velocity and position error are inversely-related.)
Position and Velocity criteria for generating motion completion events
For a | A "motion completed" event is generated when | Criteria
Position move | ABS(position error) < inPosition.tolerance.positionFine | position
Position move | ABS(velocity error) < inPosition.tolerance.velocity | velocity
Velocity move | ABS(velocity error) < inPosition.tolerance.velocity | velocity

where: |
 | position error = (command position - actual position)
 | velocity error = (command velocity - actual velocity)

For Position Moves
A DONE event is generated after a position move only after both the position and velocity criteria have been met for the period specified by the settling time. To determine if motion has completed, position moves use both position and velocity criteria.

The default (factory) value for inPosition.tolerance.velocity is 20,000,000 counts/sec. We included the ability to additionally use the velocity criteria for position moves because some users prefer to decide that an axis is “settled” only after the position error and actual velocity are both low enough.

For Velocity Moves
An AT_VELOCITY event is generated for a velocity move only after the velocity criteria has been met for the period specified by the settling time. To determine if motion has completed, velocity moves use only the velocity criteria (they don’t use the position criteria).

Note that the motion completed event generated this time is an AT_VELOCITY event rather than a DONE event. For velocity moves, DONE events will only occur after mpiMotionAction(..., MPIActionSTOP) calls.

You can also use the velocity criteria to determine when ringing has stopped after an open loop commutation move. To do this, the position criteria is effectively disabled by setting the position tolerance to a very large value (e.g., 1.0E10). After that, the DONE event following a move is determined entirely by the velocity tolerance and settling time, and, therefore, the event will be generated only after the ringing has stopped.

Be aware that setting inPosition.tolerance.velocity to 0 does not disable the velocity criteria. For interpolated scales, setting inPosition.tolerance.velocity to 0 makes it very difficult to meet the criteria of 0 counts of motion for settlingTime seconds.

Settling Time Parameters

Four Settling Time Parameters

For position moves, the generation of DONE events depends on three parameters:

MPIAxisConfig.inPosition.settlingTime
MPIAxisConfig.inPosition.positionFine
MPIAxisConfig.inPosition.velocity

DONE events are only generated when command = target or after STOP, ESTOP or ABORT events.

For velocity moves, the generation of AT_VELOCITY events depends on two parameters:

MPIAxisConfig.inPosition.settlingTime
MPIAxisConfig.inPosition.velocity

The settlingTime value specifies the amount of time (seconds) that a motion must be within the positionFine band, in order for the motion to be considered complete (finished).

The positionFine parameter is a tolerance (encoder counts), where we know a motion is complete if the motion settles within this tolerance.

The velocity parameter specifies a band around the target velocity for velocity moves.

A fourth parameter (MPIAxisConfig.inPosition.positionCoarse) specifies a band around the final position. Optionally, an interrupt can be triggered when the motion is in the positionFine band, but not necessarily complete (finished). In this case, the interrupt becomes an early warning of motion that is about to finish (i.e., mostly finished).


XMP Multitasking

Introduction

The MPI provides multitasking capabilities in the host, while the XMP can execute commands and receive data without host intervention.


Object Relationships

Objects Relationships

Introduction | Object List | Bitmap | Array of Object Numbers
Using Lists, Bitmaps, & Arrays | Application-MPI-Controller Interface | SERCOS Interface

Introduction

To create a motion application, you create objects, link them in relationships (associate them), and provide the desired parameters for motion.

There are three ways that you can associate one object with another object:

    • Using an object List
    • Using bitmap
    • Using an array of object numbers

Objects using bitmaps or an array of numbers must all be present physically on the same controller, while objects on an object list can come from different controllers (such as objects on the EventMgr control list).
Three Ways to Associate Objects with Objects
Object | . | When to Use
List | an ordered list | Use a List when the order of the objects to be associated is important, OR when some of the objects reside on different controllers.
Bitmap | an un-ordered list | Use a bitmap when the order of the objects is not important, AND the objects must all reside on the same controller (same Control object).
Array of object numbers | an ordered list | Use an array of object numbers when the order of the objects is important, AND the objects must all reside on the same controller (same Control object).

Object List

Use an object list to associate objects when ordering is required, such as the Axis list maintained by a Motion object. For example, when using a Motion object, a list of Axes 0, 1, 2 is not the same as a list of Axes 0, 2, 1. Such a distinction is not available when using an object map. Refer to the List methods for Motion, Notify, Sequence and EventMgr objects.

This object: | Can have object lists of:
Motion | Axes
Notify | Events
EventMgr | Controls Notify objects
Sequence | Commands

Bitmap

An object map is a bitmap, where each numbered bit represents the presence or absence of the correspondingly numbered object. You can order the objects in the bitmap from numeric low-to-high or high-to-low, but there is no other meaningful capability for ordering objects with an object map.

Another consideration with object maps is that all objects specified in the map and the object (that those objects are being associated with) must be resident on the same controller (Control object).

Note: Although the MPI allows an Axis to be associated with a Motion without regard to the controller (Control), the XMP implementation of the MPI does not allow this.

Object maps tend to be used to associate low-level objects that:

    • must all reside on the same controller (Control)
    • and the order in which the objects are ordered does not matter

Note that the objects specified in the bitmap may be associated with another object, without those objects having to be created and deleted. A goal of the MPI has been to minimize the need to create and delete objects, especially objects that are just used for configuration. For example, an MPI application that uses the default configuration doesn’t have to create Filter or Motor objects, yet the application can still configure an Axis, by calling mpiAxisFilterMapSet(...), where the Filters are specified by the bitmap.

Object Maps for Objects
This object: | Has associated object maps of:
Filter | Axes Motors
Axis | Filters Motors
Motor | Filters Axes Adcs

Array of Object Numbers

The MPI provides a third means of associating objects, by using object numbers. Object numbers should be used when ordering is required, and all the resources arelocated on the same controller.

Using List, Bitmaps, & Arrays

Application-MPI-Controller Interface

SERCOS Interface

The standard XMP controller uses an analog interface. The analog interface requires many wires to make the connections between amplifiers and I/O. The XMP/Sercos controller uses a fiber optic interface coupled with a deterministic serial communications protocol to take the place of the wires needed with the analog XMP.

SERCOS allows the XMP controller to transmit more than just an analog reference signal to an amplifier. SERCOS allows the XMP controller to transmit position, velocity, torque, I/O, tuning parameters, and other configuration parameters to an amplifier. Because the data is transmitted to an amplifier in digital form, the amplifier will contain an on-board processor. Besides parsing the command data and sending feedback, the on board processor gives the drive many capabilities. SERCOS drives have the ability to close a position, velocity, and/or torque loop, execute internal homing procedures, as well as latch position based on digital inputs.

Despite the fact that the XMP/SERCOS controller has a different physical interface than the standard XMP controller, the same MPI is used for both controllers. The complexity of the XMP/SERCOS controller’s interface has been hidden by the MPI and by the firmware running on the XMP. This means that the same development tools can be used for both controllers. The XMP/SERCOS controller requires that an initialization procedure be executed before commands can be sent to amplifiers. Once the initialization procedure has successfully executed, the XMP/SERCOS controller acts the same as the standard analog XMP controller.


Using the Origin Variable

In servo control applications, the Command and Actual Positions for an Axis are generally used for position error calculations. On each sample, the XMP controller reads the new Actual Positions from the feedback devices and calculates the new Command Positions.

To determine the relationship between Command and Actual Positions for an Axis and physical positions on the machine, you can use the Origin variable (which can be set by the host).

If it is important to set the Command or Actual Position to an exact value, you should use the mpiAxisOriginSet(...) function. Calling mpiAxisOriginSet(...) will modify both Command and Actual Positions by the same amount.

The Origin variable can be set in two different ways depending on the desired result. For example, assume the Command and Actual Positions are 10,000 and 10,024 counts respectively and that the axis is not moving.

Setting the Origin variable to 10,000 will result in Command Position = 0 and Actual Position = 24. Setting the Origin variable to 10,024 will result in Command Position = -24 and Actual Position = 0.

This second method is the most frequently used method for setting the new Origin after homing. Refer to the next table.
Position and Velocity criteria for generating motion completion events
If Command Position = | If Actual Position | And you set Origin Variable | Then Command Position = | And Actual Position =
10,000 | 10,024 | 10,000 | 0 | 24
10,000 | 10,024 | 10,024 | -24 | 0

Cautions about motion in general:

  1. During motion, you should never call the mpiAxisOriginSet(...) and mpiAxis[Actual|Command|Position]Set(...) functions. If you do call one of these functions, the XMP controller will immediately act on the new positions, causing the move to complete at a different point than the point specified in mpiMotionStart(...).
  2. Setting a new Command Position using mpiAxisCommandPositionSet(...) should be done with caution, because the XMP controller will immediately try to servo to the new position. If the new and old command positions differ by a large amount the axis may fault (limit error) or jump to the new position at very high speed.
  3. The effect of mpiAxisOriginSet(...) and mpiAxis[Actual|Command]PositionSet(...) calls will not be seen by the host until the next controller sample following the call.

    For example, if you call mpiAxisCommandPositionGet(...) immediately after calling mpiAxisOriginSet(...) or mpiAxisCommandPositionSet(...), mpiAxisCommandPositionGet(...) will probably return the old position values.


About the PID PIDOutputOffset Parameter

The PIDoutput Offset parameter is a constant value added to the PID calculation before sending the DAC value to the DAC.
Reason
More
1
 To compensate for the input offset errors in a “conventional” amplifier

For situations when the amplifier performs the commutation.

Individual DAC offsets can also be used to zero out-of-spec amplifier offsets.
2
 If a static DC torque (force) on the system is needed Typically used with a gravity-loaded (vertical) axis that has a simple current amplifier controlling the motor
3
 For testing the DAC

If the axis is aborted or all PID gains are zeroed, you can use the PIDOutputOffset parameter to set the DAC voltage directly. (3277 = 1Volt, 6553 = 2Volts, etc.)

You can only use the PIDOutputOffset parameter if the controller is not configured for motor commutation. If the controller is configured for commutation, use the Commutation DAC Offset to test the DAC.
4
 For using the DAC as a general purpose analog output

In some cases, the easiest way for the host to generate an analog signal is to set all PID gains to zero and use the PIDOutputOffset parameter to set the desired voltage level.

Alternatively, you can use the Commutation DAC Offset for the same purpose, which has the advantage that the voltage levels can be individually set for the two DACs.


Perform a Point-to-Point Coordinated Move

To generate a point-to-point coordinated move, you can use mpiMotionStart(...) with either a “trapezoidal” or “S-Curve” type motion. By scaling the Velocities, Accels, and Decels by the ratio of the distances, you can get a point-to-point coordinated move. The coordinated moves will all start and end at the same time.

It doesn't matter what the Jerk Percent parameter value is, because the calculated move time is the same for both trapezoidal and S-Curve moves. For example, specifying a vector Vel, Accel, Decel, and a distance X, Y, Z:


Symbol Definitions

Project / Makefile Settings: Symbol Definitions

MPI_DECL1/MPI_DECL2 | MEI_ASSERT | MEI_PLATFORM

Introduction |
 | This section describes compile-time symbol definitions used by the MPI library.
MPI_DECL1/MPI_DECL2

These symbols are used in library header files to handle compiler-specific language extensions when declaring external functions and data; in particular, those extensions used when making Win32 dynamic link libraries (DLLs). MPI_DECL1 precedes the return type of a function declaration; MPI_DECL2 follows the return type and precedes the function name:

    MPI_DECL1 long MPI_DECL2 mpiModuleFunction();
When building an application or the MPI library for Win32 platforms (Windows 95/NT), the following symbol definitions should be used:
MPI_DECL1=__declspec(dllexport)
    MPI_DECL2=__stdcall

MEI_ASSERT

When defined, MEI_ASSERT will cause calls to the macro meiASSERT(expression) to be compiled into the library. Otherwise, these calls will be discarded by the preprocessor.

The meiASSERT(...) macro is used by the library and is available to applications. It is a valuable debugging tool that can be used to catch programming errors at their source and prevent them from spreading. If the argument to the macro is TRUE (i.e. non-zero), execution proceeds normally. Otherwise, an error message is displayed; the message contains the name of the file and the line number of the meiASSERT(...) call. The application exits after displaying the message.

The MEI_ASSERT symbol should generally be defined except for when library size must be as small as possible and application execution speed must be as fast as possible.

MEI_PLATFORM

The MEI_PLATFORM symbols are used to indicate the platform for which the library and applications are built. Each platform has its own unique symbol.

Currently supported platforms:

MEI_PLATFORM_WIN95 | Microsoft Windows 95
MEI_PLATFORM_WINNT | Microsoft Windows NT
MEI_PLATFORM_WINRTSS | VenturComm WinNT RealTime SubSystem
Currently supported platforms; however, platform- and version-specific (contact MEI for details):
MEI_PLATFORM_LYNXOS | Real-Time Systems LynxOS
MEI_PLATFORM_QNX | Quantum Software Systems
QNX MEI_PLATFORM_VXWORKS | WindRiver Systems VxWorks
Potentially supported platforms:
MEI_PLATFORM_DOS | Microsoft DOS
MEI_PLATFORM_IRMX | Intel iRMX
MEI_PLATFORM_OS9 | Microware OS-9
MEI_PLATFORM_PSOS | Integrated Systems pSOS
MEI_PLATFORM_VRTX | Microtec Research
VRTX MEI_PLATFORM_WIN31 | Microsoft Windows 3.1
Note: Existence of an MEI_PLATFORM symbol for a potentially supported platform does not imply intent to support that platform.


Running Multiple Applications with the XMP

There are two situations that often cause problems when you are executing multiple applications at the same time:
  1. If one application resets the XMP controller while other applications are busy using the XMP, this is analogous to pulling the rug out beneath the feet of the other applications. The other applications are not aware that all states have been lost (controller reset), and thus these other applications get lost themselves.

    If you run two XMP applications at the same time (Motion Console and VM3, or Motion Console and your application), and if one application resets the board while the second application is busy accessing memory (like VM3), then the interface between the host and DSP can break down. To resolve this type of problem, you should close both applications, restart one application, and then reset the XMP.
  2. If you modify the default configuration of objects on the XMP, and then run another application which wants a different configuration of the same objects (program sequencers, motion supervisors, axes, etc), and you don't manage this, you can get into trouble.You have to coordinate how simultaneously exectuing applications manage the XMP resources.
  3. Simultaneously, using DLLs, applications, and Motion Console from different MEI releases can and will cause problems.


S-Curve Jerk Algorithm and Attributes

Algorithm | Attributes

Algorithm

A new move type, MPIMotionTypeS_CURVE_JERK, has been added to support a jerk-specified profile. This replaces the old jerkPercent algorithm. Two added features that the new S-Curve Jerk algorithm provide are the ability to call a motion modify at any time during a path move and the freedom to change jerk, acceleration, and maximum velocity independently. None of these values will be exceeded in the resulting motion. The new S-Curve Jerk algorithm will be ideal for making final adjustments to a move as it draws closer to its final target and for making smoother transitions from one motion to the next.

Old firmware: Notice that the acceleration is assumed
to be zero and that there is a sudden change in the velocity as a result.

New firmware: Notice that the acceleration changes less
abruptly and that the velocity profile is much smoother.

Safe parameters for jerk values should range from a minimum of amax* amax / vmax (amax is just reached when accelerating from 0 to vmax) and a maximum of amax / sample period (amax is reached in one sample period). In the new firmware, changes to the jerk will also change the time needed to complete a motion. For example, a large value of jerk will have a shorter time, but increase the “jerkiness” of the motion (see fig 1). Conversely, a small value of jerk will have a longer time, but a much smoother motion (see fig 2).

Two new parameters, accelerationJerk and decelerationJerk have been added to the MPITrajectory{…} structure. When they are non-zero, the acceleration profile uses the specified jerk and acceleration to ramp an axis(es) to constant velocity and then decelerate to a stop. If accelerationJerk or decelerationJerk is zero, an illegal parameter error is returned.

For the move type, MPIMotionTypeS_CURVE, the MPI calculates an appropriate jerk value based on the specified velocity, acceleration, and jerkPercent. The jerk value is computed according to the following formula:

If jerkPercent is zero, the jerk value is computed so that the maximum acceleration is reached in one sample period. With the previous S-Curve algorithm, the time for a move would not change as jerkPercent value was varied. This is also true for this S-Curve algorithm, as long as the move reaches maximum velocity. In short moves, where maximum velocity is not reached, setting jerkPercent to be small will result in a quicker move than if you were to set jerkPercent to be large.

WARNING! The same jerkPercent values may cause different profiles than the previous S-Curve algorithm.

Attributes

The new S_Curve algorithm behaves similarly to the previous algorithm, except for its attributes.

MPIMotionAttrMaskDELAY can now be used with any start motion, but never with motion modify.

MPIMotionAttrMaskAPPEND can be used with any motion, as long as it is not preceded by a motion that had a final velocity.

MEIMotionAttrMaskNO_REVERSAL returns a MPIMotionMessagePROFILE_ERROR if the given specifications would result in a move with a reversal init, thereby preventing the move from being executed.

MPIMotionTypeTRAPEZOIDAL, MPIMotionTypeS_CURVE, and MPIMotionTypeS_CURVE_JERK

MPIMotionAttrMaskRELATIVE, when used with MPIMotionTypeTRAPEZOIDAL, MPIMotionTypeS_CURVE and MPIMotionTypeS_CURVE_JERK means that the final position is relative to the beginning position of the motion.

MEIMotionAttrMaskFINAL_VEL can be used with MPIMotionTypeTRAPEZOIDAL, MPIMotionTypeS_CURVE and MPIMotionTypeS_CURVE_JERK, but should be used with caution as it may not be possible for the controller to compute a trajectory to meet these criteria, which would cause a MPIMotionMessagePROFILE_ERROR to be returned, and the move to be ignored.

Multi-Axis Motion

Neither MPIMotionAttrMaskSYNC_START nor MPIMotionAttrMaskSYNC_END
If neither MPIMotionAttrMaskSYNC_START nor MPIMotionAttrMaskSYNC_END are specified, a single MPITrajectory{...} may be specified for the resultant motion of multiple axes on one motion supervisor. The motion of each axis will be synchronized with the others on the motion supervisor. The maximum velocity, acceleration, deceleration, and jerk values of the first MPITrajectory structure will be used for the global vector parameters. It will ignore any other values supplied. This cannot be used with MEIMotionAttrMaskFINAL_VEL.

MPIMotionAttrMaskSYNC_START or MPIMotionAttrMaskSYNC_END but not both
If MPIMotionAttrMaskSYNC_START or MPIMotionAttrMaskSYNC_END (but not both) is specified, each axis will move as fast as possible and either start together, or stop together. If motion is point-to-point and more than one axis on the motion supervisor has a final velocity, MPIMotionAttrMaskSYNC_START or MPIMotionAttrMaskSYNC_END must be used. MPIMotionAttrMaskSYNC_END cannot be used with motion modify.

Both MPIMotionAttrMaskSYNC_START and MPIMotionAttrMaskSYNC_END
With MPIMotionAttrMaskSYNC_START and MPIMotionAttrMaskSYNC_END, the motion for each axis will be scaled so that the motion of all axes will end at approximately the same time. The time for this motion is based on the time for the longest motion, so that the limits are not exceeded. The axes will be scaled to start and stop together, but the scaling may not be exact. Both MPIMotionAttrMaskSYNC_START and MPIMotionAttrMaskSYNC_END cannot be used together with MEIMotionAttrMaskFINAL_VEL.

MPIMotionTypeVELOCITY

MPIMotionTypeVELOCITY moves allow a final velocity to be specified without a final point.

MPIMotionAttrMaskSYNC_START and/or MPIMotionAttrMaskSYNC_END
Neither is supported for this motion type. MPIMotionAttrMaskSYNC_END cannot be used with motion modify.

MEIMotionAttrMaskFINAL_VEL
MEIMotionAttrMaskFINAL_VEL is not supported for this motion type.

MPIMotionAttrMaskRELATIVE
MPIMotionAttrMaskRELATIVE, when used with MPIMotionTypeVELOCITY or MPIMotionTypeVELOCITY_JERK, means that the final velocity is relative to the velocity at the start of the motion.


S-Curve Motion Profiles: Command Acceleration vs. Peak Acceleration

The XMP’s DSP uses a formula to convert the “commanded acceleration” for an S-Curve move to a “peak acceleration.” The DSP calculates the trapezoidal profile first, then adjusts the accel/decel portions of the move based on the “Jerk Percent” parameter, while keeping the move time at a constant value. For example, a 0% jerk would look like a trapezoidal velocity profile (no jerk portion), and a 100% jerk would have no constant accel/decel (all jerks). See the table below.

Changes in Jerk Percent parameter change the
acceleration-deceleration curve characteristics

The conversion formula is:

where,

max_accel is the maximum acceleration (or decel) for a point to point profile accel is the specified acceleration (or decel) from the application code jerk_percent is the specified jerk percentage (0 to 100.0) from the application code.


XMP Servo Algorithms

PID-Based | PIV-Based

PID-Based

PIV-Based

PIV: Block Diagram

For a print-friendly version of the above diagram, click here.

PIV: Position Compensation

For a print-friendly version of the above diagram, click here.

PIV: Velocity Compensation

For a print-friendly version of the above diagram, click here.


How STOP Events work

Resuming Motion after STOP Events

When a motion supervisor sees a STOP event (generated by anything in the domains of motion supervisor’s axes), the Feedrate is changed from NormalFeedrate to PauseFeedrate (MS[n].PauseFeedrate in the firmware). To set the PauseFeedrate , use the method mpiControlMemorySet(...).

How quickly the NormalFeedrate changes to PauseFeedrate is determined by the value of StartStopRate (which is set by motionConfig.decelTime.stop). Normally, PauseFeedrate is 0.0, which causes the motion to stop.

When the motion is re-started (using mpiMotionAction(...,MPIActionRESUME) for STOP events), the Feedrate is changed back to the NormalFeedrate at the StartStopRate rate.
How Motion is Restarted after STOP Events
If Motion was stopped by | Then Motion resumes after
STOP Event | mpiMotionAction(...MPIActionRESUME) is called
PAUSE Event | mpiMotionAction(...MPIActionRESUME) is called
 | the limit (bit) is cleared

Note that STOP events are latched by the firmware, while PAUSE events aren’t. This means that if you configure a user limit to trigger a STOP event when an input (like Xcvr) is set (= 1), the Motion will go from NormalFeedrate to PauseFeedrate when that bit is set, and the Motion will stay at the PauseFeedrate until mpiMotionAction(...,MPIActionRESUME) is called.

If a limit is configured for a PAUSE event, the Motion will resume automatically after the bit is cleared (mpiMotionAction(...,MPIActionRESUME) is not needed).


 PIV: Block Diagram


 PIV: Position Compensation


 PIV: Velocity Compensation


Safety Warnings

WARNING! READ ME!
CAUTION! RAPID MOTION!

Motion Console can effect rapid movements in machinery under its control. Entered parameter values take effect immediately, and may cause sudden, unexpected movement of machinery. Before entering or changing Motion Console parameters, verify that all personnel, hands, fingers, body parts, and property are clear of the movement area; otherwise, injury or death may result!

ATTENTION! MOUVEMENTS RAPIDES!

Motion Console est capable de produire des mouvements rapides des machines sous son contrôle. Les valeurs de paramètres introduites agissent immédiatement, et peuvent produire des motions soudaines et inattendues. Avant d’introduire ou de changer les paramètres, vérifiez que toutes personnes, mains, doigts, parties de corps, soient hors de la région de mouvement afin de ne pas causer de blessures ou de mort.

CAUTION! ELECTRICAL HAZARDS!

Before connecting servo amplifiers to motion control components, verify that all power is off and equipment is unplugged from its power source.

ATTENTION! DANGER ELECTRIQUE!

Avant de mettre en contact les amplificateurs servo avec les éléments composant le contrôle de mouvement, vérifiez que l’électricité soit éteinte et que l’équipement soit débranché de sa source électrique.

CAUTION! CONFIGURE PANIC STOP NOW!

Motion Console provides a software-based Panic Stop feature which may be activated in one of two ways:

  • keyboard key
  • Panic Stop button

The Panic Stop behaves according to the user-specified Panic Action parameter located on Motion Console’s Motion Supervisor Summary / General Configuration tab page. Depending upon how Panic Action is configured, a panic stop may initiate a slow or rapid motion stop, an error state, or no error at all. For details on configuring your Panic Stop, see Chapter 2 of this manual. You must custom-configure your Panic Stop according to the level of control and safety demanded by your motion system! Configure your Panic Stop now, before proceeding!

IMPORTANT! In addition to the software-based Panic Stop feature offered in Motion Console, users are strongly urged to construct a hardware-based emergency stop system. This should be done before commencing motion control testing and configuration. (Most such hardware-based safety systems work by interupting power to motion components.) For assistance with constructing a hardware-based emergency stop, readers are directed to their local governmental occupational safety guidelines.


Introduction to Utilities

CONTENTS:
Introduction
Required Materials
Safety Precautions
Hardware Requirements and Installation
CHAPTER 1
Requirements

Introduction

To fully understand Motion Console, Motion Scope and the VM3 utility, you will need to experiment with hardware. Ideally, a test stand has been obtained for this purpose so that you may experiment with the XMP to the fullest extent possible. This reduces risks to personnel and property. (If you are new to XMP, your first motion experiments should not be with a 20-ton wrecking crane!) This section will assist you in getting your hardware connected. You should then proceed to the "Motion Console" section (Chapter 2) to begin using your XMP motion controller.


Required Materials
Safety Precautions
Hardware Requirements and Installation
CHAPTER 1
Requirements
Required Materials
  • XMP Motion Controller Hardware Installation Manual (P/N M001-0066)

    •
  • XMP controller card(s)

    •
  • VHDCI cable ("VHDCI" = Very High Density Connector Interface) One cable for every two motors (servo or stepper). Each controller card accepts 1-4 cables, depending upon its configuration.

    Note

    If you are configuring for a SERCOS system, you do not need a VHDCI cable.

  • Screw terminal connector (STC-136) for connecting one or two VHDCI cables to your motion hardware.

    Note

             If you are configuring for a SERCOS system, you do not need a terminal connector.

  • Host computer

    •
  • Servo amplifier(s) or stepper motors

  • Hand tools (sufficient to open host computer and install controller card, secure cables, etc.)


Safety Precautions
Hardware Requirements and Installation
CHAPTER 1
Requirements
Safety Precautions
Mechanical Hazards

The following mechanical precautions should always be observed, especially when operating large, powerful components:

Crush-Collision Danger to Personnel-- Even small mechanical components can exert sufficient force to crush or injure you! Before powering your motion control system, verify that personnel, including their hands, fingers and feet are clear of the safety zone. If you have not already done so, define a safety zone, then employ barriers and/or clearly marked boundary lines so that personnel are excluded from the zone. Before powering motion control components, verify that all personnel remain outside the safety zone.

Crush-Collision Hazard to Equipment-- The same precautions applied to personnel should be observed for equipment. Components can be damaged or destroyed due to collision with other components or fixed hardware.

Component Hazards-- Motion control may be applied to components which themselves present hazards. These include welders, saws, lasers, presses, cutters, etc. Be aware that the introduction of movement to a component extends the reach and range of that component's hazards. In addition, any object can be made dangerous if suddenly jarred loose or pitched due to sudden, wild movements. When testing new applications, it is recommended that you begin at very low speeds, then slowly increase to the design speed.

Electrical Hazards

Electrocution Hazard-- Some motion control systems utilize high voltages and currents which present hazards to personnel. During installation and servicing of components:

  • Power off all electrical components and accessories connected to your motion control system.
  • Unplug electrical devices from their source of power. Safe-lock all power plugs to prevent them from being plugged in during servicing.
  • Allow sufficient time for components using capacitors to discharge fully before making connections.
  • Do not repower any components until installation is complete and personnel are clear of component spaces.

ESD-- Due to the use of sensitive microelectronics, all XMP boards are subject to damage due to electrostatic discharge (ESD). When handling XMP components, users are advised to observe basic ESD precautions, including the use of grounding straps and grounding mats. Removed XMP components should always be stored in protective ESD bags and/or cases.


Hardware Requirements and Installation
CHAPTER 1
Requirements

Hardware Requirements and Installation

Hardware: Controllers

Controller hardware requirements and detailed installation instructions are detailed in the XMP Motion Controller Hardware Installation Manual (P/N M001-0066), .

Hardware: SIM4 Modules

Installation instructions and hardware requirements for scale interpolation modules (or "SIM4 modules") are detailed in Application Note 206, "SIM4 Option: Installation and Calibration," available from Motion Engineering.

Hardware: Sinusoidal Commutation

Installation instructions and hardware requirements for utilizing sinusoidal commutation are detailed in Application Note 203, "Sinusoidal Commutation," available from Motion Engineering.

Software

Operating System-- Operates on WindowsNT 4.0, or Windows 95/98, or 2000. Detailed software installation instructions are included with the current release note of your software version.


Object Oriented Motion Control

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console

Object-oriented Motion Control

The XMP motion control system is distinguished by its unparalleled flexibility in design. This is largely the result of two features: 1) a firmware-configured DSP processor which can be customized for efficient tasking; and, 2) a dual-library software architecture containing both general (MPI) and specialized (MEI) software objects. These objects encompass complex motion control functions, enabling the programmer to quickly build programs without writing hundreds or thousands of lines of code. Objects lend extraordinary portability to the software environment, allowing complex functions to be executed by calling them as single objects.

Motion Console embodies this object-oriented approach to motion control through its unique graphical user interface. It has been designed as a utility to assist programmers. It does not write custom applications. Rather, it provides an environment for the testing and monitoring of motion control components. This will prove extremely helpful to you when writing new applications, because it allows you to check your code against a proven interface. (For example, if your application fails to move a component, you can try Motion Console to see whether the problem lies within the hardware or software.)

This chapter will guide you through the basic use of Motion Console, and includes a description of objects and attributes. If you would like to try configuring a simple motion control system with Motion Console, please see the Quick-Start Guide, which accompanies MEI's Firmware Developer's Kit. Another helpful section is the, "Configuring New Systems with Motion Console," in this chapter.


Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console

Motion Console Objects

Motion Console divides motion control into several distinct software objects. Some of these objects have direct hardware equivalents, such as Motor objects. Other objects are more abstract and complicated, such as Filter objects. Motion Console provides direct configuration and monitoring of XMP motion control objects, including:

Motion Controller-- A single XMP controller, capable of controlling motion supervisors, and served by a host computer. A Controller folder lists the controllers served by the host computer, of which there may be more than one. However, each Controller demands its own separate motion controller hardware (i.e., one main controller board, with or without an attached expansion board).

Motion Supervisor-- Topmost level of motion control associated with a Controller. Each Motion Supervisor, in turn, has 0 (zero) or more Axes mapped to it.

Axis-- A motion vector associated with either linear (e.g., linear slide), or rotary (e.g., turntable) motion, and associated with a Motion Supervisor. Each Axis has 0 (zero) or more Filters mapped to it.

Filter-- Attributes applied to closed-loop motor control, such as gains and motion algorithms. Each Filter has 0 (zero) or more Motors mapped to it.

Motor-- A motor, which may be either rotary (such as a rotary motor shaft), or linear (such as a linear motor, pneumatic cylinder, hydraulic actuator, etc.).

SERCOS-- Read-only configuration attributes for monitoring SERCOS rings.

Node-- SERCOS nodes. Each Node is associated with a particular SERCOS object.

IDN-- SERCOS identification number. Each IDN object is associated with a particular Node object.

Mapping

"Mapping" means associating one object with another. For example, one axis may have one motor mapped to it (such as a motor-driven leadscrew on a slide), or one axis may have two motors mapped to it (such as a gantry crane).

Frequently, motion designers think of each axis in terms of a single motor; however, the XMP environment allows you to expand this model. For example, the X-Y table on a three-axis machine is simply controlled by two motors, each of which represents a single, independent axis. However, it may be advantageous to add a second motor to each axis, in order to obtain independent, rapid-coarse motion and slow-fine motion. In this model, each axis has two motors associated with it: one coarse, one fine. The choice of when to use what motor is performed by a Filter object, written into the custom application code. If the fine motor is commanded to move to a point outside its range, the filter object can be configured to use the coarse motor to reposition the axis. Once the coarse motor has positioned the axis at its starting point, the filter will switch to the fine motor. This level of flexibility is made possible by object mapping.

Motors 1 and 2 (M1 and M2) are mapped to Axis 1 (A1) on the X-axis. Motors 3 and 4 (M3 and M4) are mapped to Axis 2 (A2) on the Y-axis.

This allows one component to be associated with another by simply dragging one object to another on the computer screen with a mouse.

IMPORTANT! Object mappings, along with all other Motion Console settings, are NOT saved until the Save to Flash Memory [image] function is used on the Object Explorer or object summary window. If you do not save your settings to flash memory, your settings will be lost when the system is powered down, or when the controller is reset.

Before using Motion Console to map objects, it will help to review how the user interface is designed.


CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console

Motion Console User Interface

Main Motion Console Frame

The outermost Motion Console window frame presents a toolbar at the top with several buttons. Each button function is summarized below.

Toolbar Functions

View Error List-- MPI library function errors are displayed in the Library Function Errors window. When there are no errors to display, the View Error List button is disabled. Otherwise, it is enabled and clicking on it opens the Library Function Errors window.

To empty the list, click on the Reset button. To close the list, click on either the Close button, or the close ("X") icon in the upper-right corner of the window. Some MPI error messages are described in the Software Reference.

New-- Clicking on the New Profile button will create a new initialization file (.INI), or profile. The default setting will initially display only the Object Explorer box with no controllers. See the Profile Files section for more information.

Open-- Clicking the Open Existing Profile button will open a specified .INI file. See the Profile Files section for more information.

Save As-- Clicking the Save Profile As button will save the current profile into the specified .INI file. See the Profile Files section for more information.

View Object Explorer-- Clicking on the View Object Explorer button displays the Object Explorer window. See "Object Explorer" section below in this chapter for more information.

Open and Configure Controller Summary-- Clicking on this button opens and configures the Controller Summary window. See "Controller Objects" section below in this chapter for more information.

Open and Configure Motion Supervisor Summary-- Clicking on this button opens and configures the Motion Supervisor Summary window. See "Motion Supervisor Objects" section below in this chapter for more information.

Open and Configure Axis Summary-- Clicking on this button opens and configures the Axis Summary window. See "Axis Objects" section below in this chapter for more information.

Open and Configure Filter Summary-- Clicking on this button opens and configures the Filter Summary window. See "Filter Objects" section below in this chapter for more information.

Open and Configure Motor Summary-- Clicking on this button opens and configures the Motor Summary window. See "Motor Objects" section below in this chapter for more information.

Open and Configure SERCOS Ring Summary-- Clicking on this button opens and configures the SERCOS Ring Summary window. See "SERCOS Ring Objects" section below in this chapter for more information.

Open and Configure SERCOS Node Summary-- Clicking on this button opens and configures the SERCOS Node Summary window. See "SERCOS Node Objects" section below in this chapter for more information.

Open and Configure SERCOS Idn Summary-- Clicking on this button opens and configures the SERCOS Idn Summary window. See "SERCOS Idn Objects" section below in this chapter for more information.

Configure Grid Rows-- Clicking on this button displays a window to configure the Row Configuration of the highlighted Object Summary window. This allows the configfuration of each window to display only the required parameters. This will simplify the Motion Console interface and hide parameters that should not be modified. The Row Configuration settings can be saved to an initialization file.

Add Controller-- Clicking on this button adds a new Controller object. See "Controller Objects" section below in this chapter for more information.

Refresh-- Clicking on this button will refresh the Motion Console display. While the Status tabs at the bottom of the Object Summary windows are constantly updated, the Configuration tabs at the top are only updated when manually changed by the user, when Motion Console is restored after being minimized, or when the Refresh button is clicked. This is particularly helpful if another application is also accessing the XMP controller and changing the controller configuration.

Panic Button-- Clicking on this button activates a Panic action for each Motion Supervisor.

WARNING! The Panic Stop behaves according to the user-specified Panic Action parameter located in the Motion Supervisor Summary / Config tab. Depending upon how Panic Action is configured, a panic stop may initiate a slow or rapid motion stop, an error state, or no error at all. For details on configuring your Panic Stop, see the "Motion Supervisor Object" section below in this chapter. You must custom-configure your Panic Stop according to the level of control and safety required by your motion system!

NOTE-- The Shift and Ctrl keys can be used to modify the action performed when clicking on a toolbar button that opens a window. The modified actions are listed below:

  • Shift + button — Changes the state of the window. If the window is closed, it will be opened. If the window is open, it will be closed.
  • Ctrl + button — If the window is already open, it activates the window and brings it to the foreground. This is useful for locating a window that is buried under other windows.

Furthermore, for those buttons that open object Summaries, the Ctrl and Shift keys will cause the Summary Object List Configuration dialog box to be by-passed. The Summary window will be opened to the current configuration.


Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Adding a New Controller

Recall that each Controller is represented by an actual, physical controller. Therefore, a new Controller cannot be added until a new motion controller has first been installed in the computer. After installation is complete, click on the Add Controller button on the toolbar of the Object Explorer to add a new controller.

Clicking on the Add Controller button displays the Add Controller dialog box. Enter the name of the new Controller in the Name field. This may be any alphanumeric label up to 27 characters long ("Controller 1," "XY Table," "Julie Ann," etc.). The Name need not be the same as the Controller Number, but many users find this less confusing.

There are three ways to address a new controller:

  • If only one controller is being installed on the host computer, simply assign a Name, then click on the OK button. The Controller number will be 0. This is the Default option.

    •
  • Click on the Device tab if there is more than one controller card in the computer.

    •
  • Click on the Client tab if the controller card resides inside a separate client computer (i.e., not in the same computer running Motion Console), linked across a TCP/IP network with it.
Device Settings

Device settings should be used whenever more than one XMP controller card is in the host system. If ALL controllers reside inside the host, you may ignore settings on the Client tab.

  • Controller Number-- the MEI-specific index, inside the device list, that is used by the computer to identify each controller. Although you may customize the name of the controller, you cannot customize the “Controller Number,” because it is already preconfigured to coordinate with the appropriate XMP controller board. For example, you can call a controller “Martha,” but if the Controller Number is 3, Motion Console will be referencing the 3rd board installed on your system.
Client Settings

Note

 Before a client-based controller can be added to the object tree, the client computer must be running the server.exe utility. If you have not already done so, start the utility now before proceeding. Once server.exe is running, it can be "minimized" on the client computer's monitor and kept running in the background.

Client settings apply to XMP controllers which reside on separate client computers (i.e., computers other than the one running the Motion Console utility). To access a client controller, its client computer must be networked with the host computer and be running the server.exe application.

  • Controller Number-- the MEI-specific index, inside the device list, that is used by the computer to identify each controller. Although you may customize the name of the controller, you cannot customize the “Controller Number,” because it is already preconfigured to coordinate with the appropriate XMP controller board. For example, you can call a controller “Martha,” but if the Controller Number is 3, Motion Console will be referencing the 3rd board installed on your system.

    •
  • Port-- Socket connection to use for the client.

    Note

             In most cases this will be the same for host and client(s), and the default value (3300) can be used.

  • Server-- IP address of the client computer serving the XMP controller.
Error Messages

If error messages are encountered while adding a new controller, refer to the table below.

Add Controller Error Messages

Error Message

Controller Type

Action

A

mpiControlInit failed while
creating (controller name)1

Device

Recheck hardware installation, especially PCI bus socket.

A

B

Open the "Control Panel" and double-click "Devices." Find the "MeiXMP" device and make sure its status is "started."

B

C

Swap XMP board with a reliable card in a reliable host computer. If card fails to respond, contact MEI.

C

D

Client

Recheck client address.

D

E

Verify that client is running server.exe application.

E

F

Refer to Actions A and C above.

F

G

Controller (controller name) will not be added because a board already exists at the specified address.

Device

Verify Controller Number field under the Device tab is different from existing controller(s).

G

H

Client

Verify that Controller Number, Port and Server fields under the Client tab are different from existing controller(s).

H

I

MPIControlInit() returns 0x8603:Packet:communication error

All

Verify that client is running server.exe application.

I

1. This error is most likely caused if the “MEIXMP” device driver has not been started. Despite the error, a “phantom” Controller object will appear on the Motion Console Object Explorer window; however, it will not be active. To remove the phantom Controller object, highlight the object with your mouse, then click on the Remove Controller icon.

Removing Controllers

Controllers may be removed quickly with the Object Explorer by highlighting the controller to be removed and clicking on the Remove Controller icon. A controller can also be removed by clicking on the Remove button for the controller on the Operations tab of the Controller Summary window.

A Note Regarding Synchronized Motion

Designers should bear in mind that Motion Console does NOT support synchronized motion between separate controllers. (For example, you cannot perform a precision, interpolated move between Controller 0 and Controller 1 using only Motion Console.) However, coordinated motion between controllers on the order of milliseconds is supportable from user-written applications. Please contact an MEI applications engineer.


Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Object Summary Windows

Object Summary windows display the attributes of individual objects using a grid control, much like a spreadsheet. Each object is represented by a column and the attributes are represented by rows. For some objects, there are so many attributes that they are divided and categorized into several tab windows. The user can configure which objects are to be displayed by an Object Summary.

Configuring Object Summaries

Summary windows are configured to display objects directly or by association. For example, the Axis Summary can be configured to display a set of axes, such as Axis 0, Axis 1, and Axis 2, or it can be configured to display all the axes associated with a set of super-objects, such as MS 0, MS 1, and MS 2.

Object Summaries can be configured by using 1) the Object Explorer, or 2) the Object List Configuration dialog box, or 3) the View Sub-objects buttons on another Summary window. See the sections related to these windows for more information. The View Sub-objects buttons are described below.

View Sub-Objects

The View Sub-objects button is displayed as a general configuration item on most object windows. It is not displayed for DAC and IDN objects because they do not have any sub-objects. A "sub-object" is meant to signify any object that is mapped to another object, either directly or indirectly. The summaries shown are identical to those presented by clicking on summary icons in the Object Explorer. For example, clicking on the View Sub-objects button within the Controller Summary window displays eight types of subordinate objects:

A lower-level object such as the Filter object will display fewer sub-object types:

Sub-object summaries are displayed by selecting them with the mouse. More than one summary can be selected from a list by simultaneously holding down the <Shift> key while clicking on both.

Anatomy of an Object Summary

Below is a diagram that illustrates the various parts of an Object Summary window.

"Configurable Attributes" versus "Status Parameters"

Some summary windows are divided into two sections. The top section of the window lists attributes which may be altered through direct data entry; these are configurable. The bottom section of the window contains read-only information regarding the status of objects; these are not configurable. An example of one such panel (an Axis summary) is shown below.

In this example, the bottom, read-only parameters provide status information about the axis; they cannot be manually changed. Attributes in the upper portion of summary windows may be altered by manually entering values.

Cell Controls

Each grid cell contains a user interface control that displays data and, for configurable attributes, allows the user to enter data. Below are shown some controls found within an object grid.

Edit Box-- Data is entered manually into the cell using the keyboard.

Combo Box-- Clicking on a cell yields a pull-down menu of options, which can be selected, or data can be manually entered via the keyboard. Combo boxes consist of two parts: 1) the edit box; 2) a drop-down button. If you choose to type in your selection manually, you must enter it exactly as shown in the list of options. Clicking on drop-down button will cause a window to appear that displays the option list. You may then click on a selection. If you do not want to use a mouse for entry, type <Alt><down arrow> to display the choice list and then use the navigation keys to make a selection. Every control type has a method for entering data without using the mouse.

Checklist Combo Box-- Similar to the regular combo box, except it has selectable check boxes.

Push Buttons-- Clicking on the button will cause an action to be performed on the selected object. If multiple buttons are selected in a row, then the action will be executed on all selected objects. Selecting buttons on multiple rows is not allowed. Buttons can also be activated by selecting the cell containing the button and pressing the Space bar.

Button Grid-- This is a set of Push Buttons displayed in a grid, with each button appearing in a separate row. Each individual button behaves exactly as a regular push button. Multiple buttons may be selected.

CAUTION! Parameter values take effect immediately. If you are entering a value which influences machine movement, be certain to keep clear of moving components!

Navigating Within a Summary

Mouse-less Navigation within a Summary Window

Tab-- Move the focus to the next control in the window.

Shift + Tab-- Move the focus to the previous control in the window.

<Arrow Key>-- Within a grid control, set the current cell to the adjacent cell in the direction of the arrow key. The arrows keys are also used to change the tab page on a tab control.

Ctrl + <Arrow Key>-- Set the current cell to the extreme cell in the direction of the arrow key. For example, Ctrl + sets the current cell to the right-most cell in the current row.

Ctrl + Home-- Set the current cell to the top, left-most cell.

Ctrl + End-- Set the current cell to the bottom, right-most cell.

Selecting Cells

To select a single cell within the the table, click on the cell. To toggle the selection state of a single cell, hold down the <Ctrl> key while clicking on the cell. To select a range of cells, click on the first cell in the range, then hold down the shift key while clicking on the last cell in the range.

An entire row of cells can be selected by clicking on the row header button. An entire column can be selected by clicking on the column header button.

Cells can also be selected with the keyboard:

Shift + <Arrow Key>-- Set the current cell to the next cell in the direction of the arrow key and select both the new and previous current cell.

Shift + Ctrl <Arrow Key>-- Set the current cell to the extreme cell in the direction of the arrow key and select all cells between the former current cell and the new current cell.

Shift + Ctrl + Home-- Set the current cell to the top, left-most cell and select all cells in the range between the former current cell and the new current cell.

Shift + Ctrl + End-- Set the current cell to the bottom, right-most cell and select all cells in the range between the former current cell and the new current cell.

Copying Cell Data

It is possible to select cells within the grid, then copy them to another group of cells. (For example, when configuring two side-by-side columns.) Text values of selected cells can also be copied into the window's clip board by typing <CTRL> C, or using Edit / Copy.

Configure Grid Rows

The Configure Grid Rows button (Ctrl-R) will open a window that customizes the Object Summary display. This allows the user to select which parameters to display. This provides a simplified display for Motion Console that omits many unneeded or pre-configured parameters. It also hides parameters that should not be changed by users less familiar with the system.

In order to click the Configure Grid Rows button, one of the Object Summary windows must first be selected. Clicking the button will display a new window with all the parameters for the Object. Each parameter has a Check Box in the Hidden column. To hide a Row, simply select the appropriate Check Box. In the example below, the Axis Summary Row Configuration window is open. Note that the Relative Distance, AccelJerk and DecelJerk rows have been checked as Hidden. This causes the Axis Summary window to no longer displays these rows. To display these rows, simply un-check the appropriate box in the Row Configuration window.


Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Object Explorer

The Object Explorer provides the topmost, "bird's eye" view of the XMP motion control system. Objects such as Motion Supervisors and Motors are grouped together in their own separate folders. When opened, folders reveal objects available for mapping.

In this example, the Filter icon is double-clicked to reveal currently available Filter objects (or you can click once on the file tree's "+" junction).

Tool Buttons-- Clicking on a tool button causes an action to be performed in relationship to the object or folder currently selected in the object explorer. Another way to act on a selection is to right-click on the selected icon. Actions that can be performed on a specific type of object are unique to that object. Therefore, the user will notice that the tool buttons in the toolbar will change when a different object is selected.

The Tool Buttons can be roughly divided up into two groups:

  • buttons that open and configure object Summaries
  • buttons that perform an action on the selected object
Summary of Configuration Buttons

When you click on a summary button, it opens and configures the selected object’s summary window (see below).

For example, suppose Axis 1 is selected on the Object Explorer. Clicking on the Filter Summary button will configure the Filter Summary window to display the Filter objects that are mapped to Axis 1. Clicking on the Axis Summary button will program the Axis Summary window to display Axis 1.

Summary buttons are lettered with the first letter of the object they represent. In the case of Motion Supervisor and Motor objects, the Motor is represented by an M, while the Motion Supervisor is represented with an S.

Within the View menu, summaries can also be displayed by typing their hot keys ("c" for Controller, "a" for Axis, etc.).

The Other Tool Buttons include:

- Reset the selected controller(s)

- Refresh display of the selected controller(s) and sub-objects

- Upload the firmware of the selected controller(s) to a file

- Download firmware from a file to the selected controller(s)

- Remove the selected controller(s)

- Add a controller

- Disassociate (un-map) the selected sub-object from the object containing it.

Object Explorer: Mouse Controls
  • Shift-click— When holding down the Shift key and clicking on a Summary window icon, the selected object is either: 1) added to the Summary window (if it is not already there); or 2) removed from the Summary window (if it is already being displayed).

  • Right mouse button-- The functions performed by the toolbar buttons can also be accessed by clicking on the selected object or folder with the right mouse button. This provides a drop-down menu listing of all actions that can be applied to the selected item.

    • Each item on the pull-down menu corresponds to an icon on the tool bar.


Object List Configuration Dialog Boxes

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Object List Configuration Dialog Boxes

When using Motion Console, it is sometimes necessary to define a list of objects. The Object List Configuration Dialog Box is used for this purpose. Object lists are used for three different purposes:

To display all objects mapped to a list of objects

An Object Summary can be programmed to display all the objects mapped directly or indirectly to a list of objects. For this purpose, the Object List Configuration Dialog Box is opened by clicking on one of the Open and Configure Object Summary buttons on the main frame toolbar, or by selecting one of the View/Object Summary menu items.

To map sub-objects to a super-object

A super-object(Motion Supervisor 1, for example) can be mapped to a list of sub-objects (Axis 0-3, for example) . The Object Explorer can be used to map sub-objects one at a time to a super-object, but the Object List Configuration Dialog Box is used to define the entire list of sub-objects all at once. For this purpose, the Object List Configuration Dialog Box is opened by clicking on the sub-object map button on the Config tab page of the Object Summary. These buttons are listed below for each object that has sub-objects:

  • Motion Supervisor: Axis Map
  • Axis: Filter Map
  • Filter: Motor Map

Save objects to flash memory

A list of objects can be defined to save to flash memory. There is a Save To Flash button on the Config tab page of each Object Summary. Clicking on this button will open the Object List Configuration Dialog Box, allowing multiple objects to be selected and saved to flash memory.

The title bar of the Object List Configuration Dialog Box tells the user what function is currently being performed. It may be one of the following:

  • [Object] Summary Object List Configuration: For example: MS Summary Object List Configuration. In this case, the Object List Configuration Dialog Box is being used to configure the MS Summary to display a set of Motion Supervisors.
  • [Object] [Sub-Object] List Configuration: [Object Name]: For Example: "MS Axis List Configuration: MS 0, Controller 0". In this case, the Object List Configuration Dialog Box is being used to map a set of axes to MS 0, Controller 0.
  • Save To Flash Memory Object List Configuration: The Object List Configuration Dialog Box is being used to define a list of objects to save to flash memory.

Object List

The Object List displays the list of objects that will be the result of clicking the OK button. In most cases, the order of objects in the Object List is insignificant. The only exception to this is when configuring the Motion Supervisor Axis List. When the order of objects in the Object List is significant, then the order of the list can be modified using the Up and Down buttons, or by using the mouse to drag selected objects to a new position. (The Up and Down buttons are hidden if the order of objects in the Object List is insignificant.)

Object Pool

The Object Pool displays all objects that are valid candidates for the Object List. It consists of a set of tab pages, one for each type of object that can be in the Object List. The set of tab pages will vary, depending on the function of the object list that is being defined.

Summary Object List Configuration

For this purpose, the Object Pool will include all objects hierarchically greater than or equal to the object type that is being displayed. For example, when configuring the Motor Summary Object List, the Object Pool will contain all Motors, Filters, Axes, Motion Supervisors, and Controllers. This is because the Motor Summary window can be configured to display motor objects directly, or it can be configured to display all motors that are associated with a set of super-objects.

Sub-object List Configuration

For this purpose, the only objects displayed in the Object Pool will be those of the same type as the sub-object list that is being configured. For example, when the Axis List of a Motion Supervisor is being configured, then only axes will appear in the Object Pool.

Save to flash memory object list configuration

Every object will appear in Object Pool.

Buttons

Add-- Adds the highlighted object(s) in the Object Pool to the Object List.

Note

 You may select more than one object in the Object Pool by holding down the Ctrl button while clicking on individual objects with the mouse. To select ALL objects between two items, hold down the <Shift> button while using the mouse to click on both items. Objects can also be selected without the mouse by using the navigation keys in conjunction with <Ctrl> and <Shift>. <Ctr><Enter> will toggle selection of the current object.

The entire list can be selected by double-clicking on any member in the list. Selected items in either list can be dragged and dropped onto the other list.

Note

 Clicking the Add button is equivalent to dragging the selection in the Object Pool and dropping it into the Object List.

Set-- Sets the Object List to those objects selected in the Object Pool.

Note

 Clicking on the Set button is equivalent to dragging the selection in the Object Pool and dropping it into the Object List while simultaneously holding town the Alt key

Configure Sub-object Summaries Identically-- This check box is only visible when configuring an Object Summary and the object type for the Summary that is being configured has sub-objects associated with it. Checking the box will cause all the Object Summaries that display objects that are hierarchically lower than the object type of the Summary that is currently being configured, to be configured identically. For example, if the Motion Supervisor Summary is being configured to display MS 0, then the Axis, Filter, and Motor Summary windows will be configured to display all of their associated object types that are directly and indirectly mapped to MS 0.

Note

 The sub-object Summary windows must be open for them to be configured.

Up and Down-- Clicking on the Up or Down button will move objects that are selected in the Object List up or down one position. The same result can be achieved by dragging the selected objects and dropping them into the desired position. These buttons are hidden when the order of objects in the Object List is insignificant.

Remove-- Removes highlighted object(s) from the Object List.

Note

 Clicking on the Remove button is equivalent to dragging the selection in the Object List and dropping it into the Object Pool.

OK-- Closes the dialog box and retains the Object List settings.

Cancel-- Closes the dialog box without retaining the Object List settings.


Getting Started with Motion Console

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console

Configuring New Systems with Motion Console

Introduction

This section describes how to configure a new motion control system using Motion Console. If you are new to Motion Console, you should read this section first, then proceed to the other sections in this manual.

Getting Started with Motion Console

Motion Console is a utility designed to assist software and hardware designers with MEI motion controllers. There are two major releases of Motion Console: one for the XMP Series motion controllers, and another, older release for DSP Series motion controllers. This section discusses only the XMP version of Motion Console; the DSP release is outlined in separate documents available from MEI.

What is Motion Console?

Briefly stated, Motion Console is a software interface linking the programmer to your MEI motion controller. It gives you the ability to perform simple motions with hardware and verify that controller-hardware wiring is working properly. Motion Console is NOT a software authoring tool. It does not compile programs or check code. However, using Motion Console alongside a line editor and compiler will allow you to quickly troubleshoot programs and determine whether problems lie in hardware or software. Motion Console also provides a quick way to demonstrate the full range of mechanical movement in your system, so that you may perfect hardware designs while software is still being developed.

What is Motion Scope?

Another MEI utility, separate from Motion Console, is Motion Scope. Motion Scope provides a virtual "oscilloscope" to plot the movements of your motion system. Using Motion Scope in conjunction with Motion Console allows you to command and plot the movement of any axis. Motion Scope is described separately in this manual, in Chapter 3.

First Things First: Safety

Before configuring your system, you must consider the safety aspects of your motion control system. Such configurations as "amplifier enabling" impact every movement that your system makes, and dramatically redefine the degree of safety. Specifically, the following safety issues must be addressed when configuring new systems:

  • What hazards are posed by your motion control system to personnel and material? Has a safety zone been established to exclude personnel, their hands and fingers, etc. from dangerous spaces? Are warnings posted to alert personnel when and where hardware is in motion?
  • Are safety interlocks in place to automatically protect personnel from exposed high voltage and mechanical movements? Are emergency switches in place to perform instant, electro-mechanical shut-downs when needed?
  • How will your drive amplifiers be wired? Are they wired in a fail-safe mode which leaves your system safe when power is suddenly or unexpectedly lost? (See the Hardware Manual for details regarding amplifier enabling.)

Designers of new systems are sometimes tempted to rush and ignore basic safety issues; however, safety is integral to your system's usability. If you design your system with safety in mind from the beginning, you will alleviate major hardware and software design problems later, saving valuable lives and time.


Saving Parameter Settings

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Saving Parameter Settings

Before proceeding, you must learn to save your object settings and mappings. If you do not save your configurations, they will be lost the next time your controller is reset and/or powered down. Saving in Motion Console is NOT like saving files in other applications. (Remember, you are dealing with a lower-level hardware controller which interacts directly with hardware.) Motion Console saves parameter settings directly to its own flash memory, which ensures the same settings are reused when you repower your controller. You may also upload settings from flash memory to a firmware file, located on a hard disk or separate storage media. This permits the saving of more than one set of parameter settings, and allows multiple controllers to be loaded with the same parameter values. To ensure that your settings are protected, it is recommended that you both Save to Flash and save to an archived firmware file (Firmware Upload). Both functions are explained below.

Saving to Flash Memory

Each object has its own Save to Flash [Memory] button, which opens the Save Objects to Flash Memory dialog box. This dialog box configures a list of objects to be saved to flash memory. When the controller is powered down and restarted, the last-flashed settings are loaded automatically. For example, clicking on the Save to Flash button under Motor 2 will open the dialog box, with Motor 2 shown in the object list.

Uploading Firmware

Firmware settings which are flashed to the controller's memory can also be saved as a file on separate media using the FW [Firmware] Upload function. It is highly recommended that settings be uploaded to an archive for secure storage. This ensures protection of your settings in case the controller is damaged or lost, and allows storage of multiple configurations.

IMPORTANT! The FW Upload function saves only what is stored in flash memory, not settings on the Motion Console screen. Therefore, you must first use the Save to Flash function (see above) before using the FW Upload function.

The FW Upload function can be accessed either from the Object Explorer window, or the Controller Summary window.

Clicking on the FW Upload button displays a file manager window:

Enter the path and filename of the firmware file to be saved, then click on the Save button. The controller's firmware in flash memory will be saved to the file indicated.

Downloading Firmware

The opposite of uploading is downloading. Once a firmware file has been saved, the FW Download function copies the saved firmware file into the controller's flash memory, and volatile memory as well.

To download a firmware file into the controller's flash memory, click on the FW Download function in the Object Explorer or Controller Summary windows.

Clicking on the FW Download button displays a file manager window:

Enter the path and filename of the firmware file to be loaded, then click on the Open button. The selected file will be loaded into the controller's flash memory.

Clicking the Advanced button allows the user to choose the FPGA files that will be loaded with the Firmware code. Please contact MEI for more information about using custom FPGA files. Choosing the Basic button will automatically find and download the default FPGA files.


Associating Objects with Motion Console

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Associating Objects with Motion Console

Motion Console's Object Explorer can be used to associate objects comprising your motion control system. Objects are associated (mapped) in specific ways, for example:

  • Motors are mapped to Filters
  • Filters are mapped to Axes
  • Axes are mapped to Motion Supervisors

If SERCOS is employed, you must also configure:

  • SERCOS rings
  • SERCOS nodes
  • SERCOS IDNs

Note

 At this time, Motion Console is not used to configure SERCOS rings or nodes. This is done using a separate SERCOS initialization program (sercinit).
How Many Controllers?

In Motion Console, each "Controller" designates a physical piece of hardware: one XMP controller, with or without an expansion card. Depending upon how your XMP controller is configured, you will be able to command 8-24 axes per controller. If you require more axes, you will need to install additional XMP controllers.

Creating a New Controller Object

Before any mapping can de done, you must first add a Controller. To determine whether a Controller object already exists, look at the Object Explorer. The Object Explorer may appear as shown below if a Controller has not yet been added. (No objects will be listed below the Controllers icon in Object Explorer, or listed within the Controller Summary.)

An unconfigured Motion Console.

To add a Controller to Motion Console, click on the Add Controller icon on the Object Explorer toolbar or the main toolbar.

Clicking on the Add Controller icon displays the Add Controller dialog box. In most cases, the default settings may be left as-is. If you desire to make changes to settings, refer to the "Controller Object" section of this chapter for a description of attributes.

Click on the OK button to add a new Controller. The new Controller will be added to the object tree of the Object Explorer, which now appears as shown here:

Whenever a Controller is added to the Object Explorer, it will have a number of sub-objects. These objects are explained below.

Mapping a Motion Supervisor

The Motion Supervisor is a high-level, motion "task master," which may be configured to manage any number of axes. In the majority of cases, however, it is advantageous to assign to each Motion Supervisor one Axis. This keeps the architecture simple, and offers maximum flexibility. In limited cases (e.g., gantry cranes), it may prove helpful to map additional axes to a single Motion Supervisor.

The mapping displayed below shows one configuration. In this case, Axis 0 has been mapped to MS 0. Motion Supervisors 1-7 (not shown below) are also mapped to the same Controller object, giving a total of eight (8) Motion Supervisors.

As shown here, Motion Supervisor 0 has the following sub-objects mapped to it: Axis 0; Filter 0; and Motor 0. Other mappings and combinations are possible too, subject to the user's control.


Configuring a Motion Supervisor

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Configuring a Motion Supervisor

Because Motion Supervisors comprise the highest level of object organization (after the controller itself), they provide a convenient starting point from which to map. Mapping will require some forethought. Some of these objects are linked tightly together (e.g., Axes, Motors and Filters); therefore, it is useful to think of them as a single unit, operating under the direction of a given Motion Supervisor. Other objects may operate independently of others.

The Object Explorer gives the best single overview of your motion control system. To look at what you have configured, open the object tree below Motion Supervisors by clicking on the file "branch" at this point. It will look something like the object tree shown here:

In this example, we have displayed some of the objects for MS 0, MS 1 and MS 2. Notice that only MS 0 has sub-objects mapped to it (Axis 0, Filter 0, and Motor 0, respectively). MS 1 and MS 2 have no objects yet mapped to them. In the descriptions below, an example of each object will be mapped to a Motion Supervisor.

Mapping Axes

Classically, a single motion axis is powered by a single motor. The XMP's architecture accommodates this traditional arrangement, but also allows more than one motor to be mapped to a single axis. (Through the use of Filters, multiple motors can be configured to operate differently upon the same axis.) For now, do not worry about the type of motor(s) to be used. Think only of the axes of motion. Before further mapping, you should know the following about your motion control system:

  • How many axes of motion are required?
  • Do some axes have special requirements or limitations?
  • Will some motors always operate with other motors? How?

After these questions have been answered, you may begin mapping Axis objects to Motion Supervisors. In the examples which follow, it is assumed that objects will be mapped in numerical order (e.g., we will map Motor 1 before we map Motor 2). This is the usual order of progress, although you may do things differently if you prefer.


Mapping One Object to Another

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Mapping One Object to Another

To map Axis 1 to MS 0, use the cursor to select the Axis 1 object, then drag it into MS 0.

A dialog box will be displayed to confirm the object mapping:

To confirm the object mapping, click on the Yes button. The Object Explorer will now show Axis 1 mapped to Motion Supervisor 0:

To map several objects to their "default" sub-object, i.e., the one with the same number, use the "Sub-Object Map" button on the Summary window. (For Motion Supervisors, this button is labeled "Axis Map.") If the entire row is selected and the button is clicked, then an Object List Configuration Dialog Box will be opened to map sub-objects to each object. If the <Shift> key is held down when the button is clicked, then each object will be mapped to its default sub-object.

Mapping Filters, and Motors

Each Axis has at least one Motor and Filter object associated with it. Mapping of these objects is performed exactly as demonstrated above with Axis objects.

Before mapping these objects, it will help to answer the following questions:

  • What types of motors are required by your system? Servo or stepper? If servo-type, what phase? What are the speed and travel constraints of each axis? How does this affect the torque capabilities of your selected motors? What duty cycle is expected of your motors?
  • Is your system closed-loop or open-loop? If closed-loop, how many encoders? What levels of resolution and repeatability are required?
  • Which motion path algorithm will best answer your needs (PID, PVT, PD, etc.)? How will you tune and adjust your system?

Based upon the mechanical requirements and overall architecture of your system, you should proceed to mapping objects with the simplest configuration possible. Motor objects correlate to specific pieces of hardware having connection and power constraints. These can be determined by referring to the XMP Hardware section and the manufacturer's specifications.


Removing (Deleting) a Mapped Object

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Removing (Deleting) a Mapped Object

Recall that in the example above, Axis 0 was mapped to Motion Supervisor 0. But what if you prefered to map Axis 1 to Motion Supervisor 0 (MS 0) instead? To do this, you must first remove Axis 0 from MS 0. Object removal is done by first selecting the object to be removed, then clicking on the Remove Axis From List icon (or use the <Delete> key).

A dialog box will be displayed to confirm the object removal:

To confirm the object removal, click on the Yes button. The Object Explorer will now appear as shown here:

Notice that Axis 0 is no longer mapped to MS 0. Moreover, all of the
sub-objects associated with Axis 0 (e.g., Filter 0 and Motor 0) have also been removed from MS 0. This is because Filter 0, and Motor 0, were mapped to Axis 0. When we removed Axis 0, all its sub-objects were removed with it.

Note that Axis 0 has not been entirely removed from use. If you click on the Axes portion of the object tree, you will still find it there. But, it is no longer mapped to another object.


Safety Reminders

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Safety Reminders

As you map out your motion control system using the Object Explorer, you must address specific safety factors. These should be addressed BEFORE you mechanically engage motors to axes, and connect motion hardware to the controller.

Establish a Safety Zone

If you have not already done so, define a safety zone around the motion system to be configured. Areas traversed by hardware should be clearly marked and/or partitioned to keep out personnel, hands, fingers, etc. Warning signs and labels should be clearly posted.

Mount an Emergency Off Switch

At least one emergency off (EMO) switch should be prominently mounted where operators and technicians can easily locate and reach it at all times. Depending upon your system, the EMO should effect a rapid and safe stop of all components, preferably wired through the power lines of the system components themselves. Consider using automatic mechanical braking where heavy and/or fast components might coast dangerously after the loss of a controller.

Wire all Drive Amplifiers for Fail Safe Operation

The wiring of your system's drive amplifiers is a critical design detail and is discussed in the XMP Hardware Installation Manual. As part of your design, you must decide whether to wire the drive's amplifier enable (Amp En) line as "active high" or "active low." Regardless of the method used, ensure that your motion system cannot run away when power to the controller is lost. Design for the worst possible power loss scenario, then ask yourself: "Is this machine safe with power to the controller turned off?" Amplifier enabling should be tested in crude hardware fashion before the system is either mechanically coupled or connected to an XMP controller. Once hardware wiring has been tested for fail-safe design, proceed to the configuration of Motor Summary / General Configuration attributes (see below).

Configure Motor Summary / General Configuration Attributes

Attributes in the Motor Summary / Config tab page configure both motors and encoders. Of particular import to safety are the following:

  • Amp Enable
  • Type
  • Amp Polarity
  • Encoder Phase
  • Encoder Term
  • Encoder Cnts/Rev.
  • Amp Disable Delay
  • Brake Delay

Each of these attributes are described in a separate section of this chapter. The Amp Enable and Polarity attributes are treated in the XMP Hardware Installation Manual. Note especially that once a motor's Amp Enable line has been wired, the Amp Enable and Polarity attributes must accord with system wiring to avoid problems.

Encoder Phase and Encoder Cnts/Rev affect the safety of your system by telling the controller which way an axis is moving, how far and how fast. If encoder attributes are set wrong, you may experience runaway problems.

Configure Motion Supervisor Summary / General Configuration Attributes

Attributes in the Motion Supervisor Summary / Config tab page include those used to configure a motion system's panic actions. These tell the controller what to do when an error or panic stop command is encountered. If they are not correctly configured, your controller may ignore an operator's command to stop! Attributes include the following:

  • Stop Time
  • E-Stop Time
  • Panic Action

The Panic Action parameter is of particular importance. When switched to None, the controller will take no action after panic events! Please note that the <F12> panic stop key generates a panic action for all Motion Supervisors, according to how Panic Action is configured.


Controller Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Controller Objects

Within the Motion Console program, Controller objects occupy the highest
level on the motion control tree. This prominent software position reflects the hardware reality: each controller represents a separate, physical piece of
hardware (i.e., an XMP card) having local control. Moreover, each controller is capable of operating multiple motion supervisors, each with its own subordinate array of axes, motors, SERCOS nodes, etc.

If you have not already added a Controller, please see the Add Controller section.

Controller-Client Configuration

A Controller is physically connected with a host computer via PCI bus. Hosts may be linked to clients, which allows virtually unlimited configuration combinations.

Each controller in a machine is assigned a unique device identification number by the operating system. Motion Console uses this number to communicate with the controller. When all controllers reside within a single host computer, Motion Console requires only Controller numbers (0, 1, 2, etc.) to differentiate between them. When controllers reside in separate client computers linked through a network to the Motion Console host, each controller must also be assigned a unique IP address and Port Number.

XMP Controller Placement on PCI Buses

PCI bus architecture imposes constraints which must be observed during card installation. When adding controllers to Motion Console, each XMP board is assigned a physical location on the PCI bus in the form of a Controller Number. This is a device index number beginning at "0," which indexes with each new addition of a controller board, and which ignores non-MEI devices. Motion Console uses the device index number to associate configuration/status information with a particular controller.

Adding, removing or rearranging PCI devices can cause a motion controller device number to change. For systems with only a single controller, this is not a problem. For systems with multiple controllers, Motion Console will not know whether the device index to the physical controller map has changed. This is because some data is stored in the Motion Console initialization file and is associated with the device number. The following data will be associated with the wrong controller in Motion Console if the device number changes:

  • Controller name
  • Summary object list configuration
  • Axis attributes:

Position 1

Position 2

Velocity

Acceleration

Deceleration

Jerk Percent

WARNING! When using Motion Console with multiple controller systems, make sure you know exactly which physical controller is associated with which device index. Be sure to always verify controller-to-device index relationships before commanding any motion.

The Controller Summary window lists Controller attributes in four tab pages: Actions, Config, Version, and Stats.

Configuration Attributes: "Actions" Tab Page

"Config" Filter attributes include configurations for standard and custom filter features.

  • Reset-- Resets the controller to the power-up configuration saved in flash memory.
  • Refresh-- Refreshes display to reflect any external modifications.
  • FW Upload-- Uploads Flash memory to the firmware file. See the Uploading Firmware section earlier in this chapter for more information.
  • FW Download-- Downloads the firmware file to Flash memory. See the Downloading Firmware section earlier in this chapter for more information.
  • Remove-- Removes controller from Motion Console controller list.
Controller Configuration Attributes: "Config" Tab Page
  • Save to Flash-- Pre-selects current Controller settings for saving to flash memory. For more information on using Save to Flash, see the description in the first part of this chapter.
  • View Sub-objects -- Shows all sub-objects for the Controller. For more information, see the View Sub-object section.
  • User Version -- User defined version.*
  • Sample Rate -- Sample Rate (samples/sec).*
  • MS Count-- Number of enabled Motion Supervisor objects.*
  • Axis Count -- Number of enabled Axis objects.*
  • Filter Count -- Number of enabled Filter objects.*
  • Motor Count-- Number of enabled Motor objects.*
  • Adc Count-- Number of enabled Adc objects.*
  • Capture Count -- Number of enabled Capture objects. (Not configurable.) *
  • Compare Count-- Number of enabled Compare objects. (Not configurable.) *
  • DAC Count -- Number of enabled DAC objects.*
  • Aux DAC Count -- Number of enabled Auxiliary DAC objects.*
  • Record Count-- Number of enabled Record objects.*
  • Sequence Count -- Number of enabled Program Sequence objects.*
  • SERCOS Count -- Number of initialized SERCOS rings.* This is a read-only attribute.
  • Available Memory -- The amount of external memory available on the controller. The maximum value for Record Count and Axis Count is limited by the available memory.
* also see MPIControlConfig.
Configuration Attributes: "Version" Tab Page
  • Model-- Currently only “XMP.”
  • Type-- Currently either “Device” or “Client.”
  • Number-- The device number of the controller on the IDE bus.
  • Address-- The device driver for “Device” type controllers, the IP address for “Client” type controllers.
  • Port-- Port for “Client” type controllers only.
  • Firmware Dev. ID-- Firmware Development ID.
  • Firmware Version-- Firmware Version.
  • Firmware Revision-- Firmware Revision.
  • Firmware Option-- Firmware Option.
Configuration Attributes: "Stats" Tab Page
  • Zero Max. Times-- Zeros the maximum foreground and background timers.
  • Recalculate-- Triggers a recalculation of the timing statistics.
  • Max Fg. Time -- Maximum foreground time in microseconds.
  • Max Bg. Time-- Maximum background time in microseconds.
  • Max Delta-- Maximum Delta (samples/ background cycle).
  • Avg. Bg. Cycle Rate-- Average interrupted background cycle rate (cycles/sec).
  • Avg. Bg. Cycle Time-- Average interrupted background cycle time in microseconds.
  • Bg. Cycle Time-- Uninterrupted background cycle time in microseconds.


Motion Supervisor Object

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Motion Supervisor Object

Motion Supervisors can be thought of as specialized task-masters for motion control. Many system designers find it convenient to divide their system into specialized sub-tasks, each handled by a separate motion supervisor. As you organize your motion control system, the advantages of this approach will become obvious.

The Motion Supervisor summary window is divided into two configuration tab pages, plus a General Status page as shown below, and includes such attributes as Motion Type and Stop Time:

Configuration Attributes: "Config" Tab Page

Save to Flash-- Pre-selects current Motion Supervisor settings for saving to flash memory. For more information on using Save to Flash, see description in the first part of this chapter.

View Sub-objects-- Shows all sub-objects for the Motion Supervisor. For more information, see Object Summary Windows.

Axis Map-- Displays the MS Axis List Configuration window. For more information, see Object List Configuration Dialog Boxes.

Motion Type-- There are ten Motion Type settings; however, only three are supported in Motion Console. All are supported by the MPI library.

  • Jog -- (Unsupported)
  • PT -- (Unsupported)
  • PVT -- (Unsupported)
  • Spline -- (Unsupported)
  • B-Spline 2-- (Unsupported)
  • Bessel-- (Unsupported)
  • B-Spline-- (Unsupported)
  • S-Curve -- Implements an S-curve velocity trajectory, using the Jerk Percent parameter to reach the target position.
  • Trapezoidal -- (Default) Implements a trapezoidal velocity trajectory to reach the target position. Does not use the Jerk Percent parameter.
  • Velocity -- Implements an S-curve velocity trajectory using the Jerk Percent parameter to reach the target velocity.

Attributes-- Applies special attributes to motion objects via mpiMotionModify.

  • Relative-- Axes are commanded to move to a point relative to their present location (i.e., without regard to their starting points).
  • Sync End-- Axes are commanded to end motion simultaneously at the same point.
  • Sync Start-- Axes are commanded to start motion simultaneously from the same point.
  • Stop Time--Time (in seconds) to decelerate axis to a stop.

CAUTION! Actual stopping time is limited by mass and speed! If you are moving a heavy object at high speed and command a very rapid Stop Time, your motion control or mechanical system may be unable to comply. Verify that drive and motor manufacturer's specifications meet the demands placed upon your system BEFORE assuming a stop time.

E-Stop Time-- Time to decelerate to an emergency stop. When E-Stop is activated, the State will be flagged with a Stopping Error while the axis is decellerated. An Error state is flagged when the axis comes to a complete stop. However, amp enable outputs are NOT disabled.

Note

 If the axis is close to completing a move when E-Stop is activated, the axis may halt before the E-Stop Time has expired.

Normal Feedrate-- Speed scaling factor applied to movement. 0 = stopped; 1 = normal speed (unscaled); 1.5 = 150%; 2 = 200%, -1 = reversed norma speed; etc.

Delay-- Time delay (in seconds) before execution of next move command. If operating in Repeat Mode, the delay will be applied to the beginning of each move segment.

Panic Action-- Action to execute when the <F12> panic key is activated.

Note

 Some panic action states (E-Stop and Abort) flag a fault condition. To reset the system after a fault, click on the Clear Fault button (MS Summary / Actions tab page).

  • None-- Motion is halted at the end of the currently commanded move. (No-fault condition.)

    •
  • Stop-- Motion is halted using a Stop. (No-fault condition.)

    •
  • E-Stop-- Motion is halted using an E-Stop, and a fault condition is flagged.

    •
  • E-Stop, Abort-- Motion is halted using both an E-Stop and an Abort, and a fault condition is flagged. A fault condition is flagged.

    •
  • Abort-- Motion is halted using an Abort.
Configuration Attributes: "Actions" Tab Page

Repeat Mode-- [Enabled; (not enabled)] Repeats programmed motion.

Note

 Each repeated motion will be delayed by the Delay amount (see description above on Delay).

Move Pos. 1-- Command each axis associated with the Motion Supervisor to Position 1.

Move to Further-- Command each axis associated with the Motion Supervisor to either Position 1 or Position 2, whichever is further away.

Move Pos. 2-- Command each axis associated with the Motion Supervisor to Position 2.

Stop -- Stops movement of objects under control of current Motion Supervisor within Stop time (seconds).

E-Stop -- Emergency stop. Halts movement of objects under control of current Motion Supervisor within E-Stop time (seconds) and leaves the axes in an Error state.

Note

 E-Stop does NOT disable closed-loop control and does not disable the amp enable output(s).

Abort -- Immediately stops movement of objects under control of current Motion Supervisor, disables closed-loop control, and disables the amp enable output(s), leaving the axes in an Error state.

CAUTION! Do not use Abort when testing equipment which depends upon servos or stepper motors to secure personnel or equipment (e.g., lifting cranes, elevators, etc.). The Abort command disables servos and steppers and, in some circumstances, may present a hazard to personnel or equipment due to sudden loss of power.

Zero Position-- Sets the origin of the axis to the current actual position and the command position to 0. The algorithm for setting the origin is:

new origin = current origin + actual position

Clear Fault-- Clears the Motion Supervisor's error state and all sub-object
statuses.

Status Attributes

Status fields are read-only:

State -- Current motion state. (See Motion States table below.)

Motion States

State

Description

Idle (State parameter). Awaiting a move command.

In motion (State parameter). Performing a move command.

Stopping. (State parameter). Motion has been commanded to stop.

Moving when not commanded to move. NOTE: This occurs when another application commands a move.

Initializing.

Unknown state.

Fault or limit detected. (See Event Status Flags below.)

Error States
Event Status Flags

Error

Flag

Description

Amp[lifier] Fault

Amplifier fault.

Home Limit

Encoder home pulse exceeded or not found.

Position Error Limit

Error between command and actual position exceeds user-defined limit.

HW Neg. limit

Hardware negative limit activated.

HW Pos. limit

Hardware positive limit activated.

SW Neg. limit

Software negative limit exceeded.

SW Pos. limit

Software positive limit exceeded.

Encoder Fault

Encoder fault detected.

Motion Done

Move command completed.

At Velocity

Commanded velocity attained.


Axis Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Axis Objects

Axis objects are classically associated with a single vector of motion, particularly as it relates to a specific motor. In Motion Console, Axis objects bridge the control link between Filters and Motion Supervisors.

Object Explorer panel

Axis Summary Window

Configuration Attributes: "Motion" Tab Page

The following attributes appear on the Motion configuration tab page:

  • Position 1-- Target position when user clicks on
  • Position 2-- Target position when user clicks on

Note

 Either Position 1 or 2 can be the target position at the end of the move. Position 1 is where the axis will be commanded to move when the user clicks on [image] .

  • Velocity-- Command velocity during move (in encoder counts / second).
  • Acceleration-- Command acceleration during move (in encoder counts / sec2).
  • Deceleration-- Command deceleration during move (in encoder counts / sec2).
  • Jerk Percent-- Percentage of acceleration / deceleration curve utilized for transitioning between Acceleration, Velocity, and Deceleration components. In the figure below, the effects of various Jerk Percent values are illustrated for a simple triangular profile move.
Changes in Jerk Percent parameter change the acceleration-deceleration curve characteristics. The graphs below display commanded and actual velocities
Configuration Attributes: "Config" Tab Page

The following attributes appear on the General Config tab page:

  • Save to Flash-- Pre-selects current Axis settings for saving to flash memory. For more information on using Save to Flash, see the description in the first part of this chapter.
  • View Sub-objects-- Shows all sub-objects for Axis object. For more information, see Object Summary Windows.
  • Filter Map-- Displays the Axis Filter Map Configuration window. For more information, see Object List Configuration Dialog Boxes.
  • Pos. Tol., Fine-- Fine Positional Tolerance. Maximum allowable positional deviation (error) from target position to be considered done.
  • Pos. Tol., Coarse-- Coarse Positional Tolerance. Arbitrarily set deviation (error) from target position.

Note

 The Pos. Tol., Coarse parameter is useful for triggering auxillary events just prior to attaining target position. (E.g., on an automated milling machine, Pos. Tol., Coarse can be used to trigger the flow of cutting fluid when the tool is close to the object being milled.)
  • Velocity Tol.-- Velocity Tolerance. Maximum allowable velocity deviation (error) from target velocity to be considered "at velocity."
  • Settling Time-- Minimum time interval for both the Fine Pos[itional] Tol[erance] and Velocity Tol[erance] attributes to qualify as "done."

Note

 As they approach their target positions / velocities, all axes will spend some interval of time settling. Only when an axis attains both its Fine Positional Tolerance and Velocity Tolerance within the Settling Time is that axis regarded as truly "done"; this triggers a Motion Done event (See Motion Supervisor objects).
  • Settle on Stop -- When checked, the settling criteria is applied to moves halted by a stop.
  • Settle on E-Stop -- When checked, the settling criteria is applied to moves halted by an E-Stop.
Status Parameters
  • Actual Position -- Real, current position of axis. Where the axis actually is.
  • Command Position -- Commanded axis position. Where the axis should be.
  • Position Error -- Difference between Command and Actual positions.
  • Velocity -- Command velocity.
  • Acceleration -- Command acceleration.
  • State -- Current state of the axis.

Motion States and Descriptions

Motion State

Description

Moving toward target position 1.

Moving toward target position 2.

Moving when not commanded to move. NOTE: this occurs when another application commands a move while Motion Console is displaying the MS.

Error state

Idle


Filter Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Filter Objects

Filters provide linkage between motors and axes: motors are mapped to filters, and filters are mapped to axes. (It is not possible to map a motor directly to an axis without a filter.) Depending upon the algorithm employed, filters use such coefficients as gains, feed forward and torque limits.

Filter Configuration Attributes

The Filter Summary window lists Filter attributes in three tab pages:
"Config," "Coeffs," and "SERCOS."
Configuration Attributes: "Config" Tab Page

"Config" Filter attributes include configurations for standard and custom filter features.

  • Save to Flash-- Pre-selects current Filter settings for saving to flash memory. For more information on using Save to Flash, see description in the first part of this chapter.
  • View Sub-objects-- Shows all sub-objects for Filter object. For more information, see Object Summary Windows.
  • Motor Map-- Displays the Filter Motor Map Configuration window. For more information, see Object List Configuration Dialog Boxes.
  • Algorithm -- Software filter algorithm. There are five types:

None -- Filter is OFF. No algorithm is applied.

PID -- Proportional Integral Differential algorithm.

PIV -- Proportional Integral Velocity.

PIV1 -- Proportional Integral Velocity.

SERCOS Drive -- SERCOS protocols applied. (See "SERCOS Coefficients" below.)

User -- User-defined algorithm defined in firmware. (For more information, please contact MEI.)

Configuration Attributes: "Coeffs" Tab Page

The display of filter coefficients changes according to the Algorithm chosen (selectable from the Filter / General panel). The algorithm combo box on the Coeffs tab merely changes how the coefficients are displayed. It changes the row headers and displays N/A for coefficients that are not used for the selected algorithm. If the algorithm of a filter object does not match the algorithm being displayed, then N/A is displayed for all coefficients.

Each set of coefficients is described in separate tables below.

PID Coefficients

PID coefficients are defined in the table below.

Filter Coefficients (PID Algorithm)

Coefficient

Description

Kp

Proportional gain

Ki

Integral gain

Kd

Derivative gain

Kpff

Position feed forward gain

Kvff

Velocity feed forward gain

Kaff

Acceleration feed forward gain

Kfff

Friction feed forward gain

ImaxMoving

Position loop integration maximum (while moving)

IMaxRest

Position loop integration maximum (while resting)

DRate

Derivative sub-sampling rate

Output Limit

Voltage command output limit

Output Limit High

Maximum command output voltage limit.

Output Limit Low

Minimum command output voltage limit.

Output Offset

Offset added to output.

Ka0

Fast Fourier transform (FFT) testing gain (0)

Ka1

Fast Fourier transform (FFT) testing gain (1)

Ka2

Fast Fourier transform (FFT) testing gain (2)

PIV Coefficients

PIV coefficients are described in the table below.

Filter Coefficients (PIV Algorithm)

Coefficient

Description

Kpp

Position loop proportional gain

Kip

Position loop integral gain

Kpv

Velocity loop proportional gain

Kvff

Velocity feed forward gain

Kaff

Acceleration feed forward gain

Kfff

Friction feed forward gain

ImaxMoving

Position loop integration maximum (while moving)

IMaxRest

Position loop integration maximum (while resting)

Kdv

Velocity estimate feedback gain

Output Limit

Voltage command output limit

Output Limit High

Upper voltage command output limit.

Output Limit Low

Lower voltage command output limit.

Output Offset

Offset added to output

Kiv

Velocity loop integral gain

VintMax

Velocity loop integration maximum

Ka0

Fast Fourier transform (FFT) testing gain (0)

Ka1

Fast Fourier transform (FFT) testing gain (1)

SERCOS Coefficients

SERCOS coefficients are described in the table below.

Filter Coefficients (SERCOS Algorithm)

Coefficient

Description

IDN Value 0

Value of IDN mapped to this coefficient.

.

.
.

.

.
.

IDN Value 15

Value of IDN mapped to this coefficient.

Kvff

Velocity feed forward gain

Kaff

Acceleration feed forward gain

Kfff

Friction feed forward gain

Ksff

Feed forward scale factor.

Configuration Attributes: "SERCOS" Tab Page

The SERCOS tab page maps gain values to IDNs. If the map value is 0, then the gain is not mapped to an IDN. If the gain value is non-zero, then the MPI functions for getting and setting gain values will automatically read/write the gain values to the drive via the SERCOS service channel.


Motor Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Motor Objects

Motor objects are mapped to Filter objects. Because motor type determines many other attributes found in Motion Console, it is essential that attributes in the Motor Summary window are the first ones configured.

Motor Summary Window

The four configuration pages are: Config, Events, I/O, and SinCom.

  • Config-- General motor, stepper, and encoder configuration table.
  • Events-- Dedicated I/O and encoder event configuration table.
  • IO-- Transceiver and User I/O configuration table.
  • SinComm-- Sinusoidal Commutation configuration table.

There are also two status pages:

  • Status-- Fault and Limit event status display.
  • IO-- Dedicated I/O, Tranceiver I/O and User I/O status display.
Configuration Attributes: "Config" Tab Page

  • Save to Flash-- Pre-selects current Motor settings for saving to flash memory. For more information on using Save to Flash, see description in the first part of this chapter.
  • Types

Servo-- Configure a servo-type motor (including DC brush/brushless and linears) for ± 10V servo output.

Stepper-- Configure step/direction, pull up/down, or clockwise/counterclockwise type motor for stepper output.
See the XCVR configuration section to determine whether to set for step/dir or CW/CCW.

SERCOS Drive-- Configure motor for use with SERCOS drive.

  • Amp Enable-- Set active Amp Enable output state.

Enabled-- Enable amplifier.

Note

 actual state depends on Amp Polarity and wiring. See the XMP Hardware Installation Manual for more information.

(not enabled)-- Disable amplifier.

Note

 enable state depends on Amp Polarity and wiring. See the XMP Hardware Installation Manual for more information.
  • Amp Polarity-- Configure polarity of Amp Enable Output.

Inverted-- Amplifier enabled when output signal is high.

Note

 this is dependent upon external wiring. See the XMP Hardware Installation Manual for more information.

(not inverted)-- Amplifier enabled when output signal is low.

Note

 this is dependent upon external wiring. See the XMP Hardware Installation Manual for more information.

Encoder Phase-- Determines which direction of motor movement results in incrementing or decrementing encoder counts. It is very important to use the correct encoder phasing so that positive voltage will result in increasing counts and vice-versa.

Note phasing can also be reversed by reconfiguring the A+/- and B+/- encoder wires, e.g., swapping the A+ and A- wires.

(not reversed)-- Encoder phasing is passed to the controller directly, as wired.

Reversed-- Inverts direction of actual position traveled for given encoder feedback.

  • Encoder Term-- Encoder termination.

Enabled-- Enables 100 Ω resistor between complimentary encoder signals. Use this setting for XMP controllers without SIM4 modules.

(not enabled)-- Disables 100 Ω resistor between complimentary encoder signals. Use this setting for XMP controllers with SIM4 modules, using analog interpolated feedback.

  • Encoder Type--

Incremental-- Standard incremental-type encoders. No absolute position information stored.

ABS 0-- Configures encoder feedback for absolute encoders. Not all absolute encoders are supported; please contact MEI.

  • Encoder Cnts/Rev-- (Used with ABS 0 above.) Encoder counts per revolution. Used primarily for sinusoidal commutation.
  • Amp Disable Delay-- Delay (in seconds) before disabling amplifier on events that cause an Abort.
  • Brake Delay-- (Unsupported.)
  • Step Pulse Width-- Sets the width of a step pulse. (Range: 50 ns to 1.6 ms)
  • Step Loopback-- (Used with stepper motors only.) Loops back the step output pulses into the encoder inputs to simulate feedback.

Enabled-- Uses step output to determine IN.POSITION and ACTUAL.POSITION. (Correct choice for stepper systems to prevent unwanted error limit events.)

(not enabled)-- Requires feedback device for ACTUAL POSITION, Error Limit, etc. (Should be selected for non-stepper systems.)

  • Step Resource # -- Reflects which motor block the motor is associated with. This parameter is only useful for XMP-Pulse controllers. All other XMP controllers should set the Step Resource Number equal to the Motor number.

  • For XMP-Pulse users -- the Step Resource Number can be used to share the resources of a single motor block between two stepper motors. This is useful when you have more motors than motor blocks. You can remap a motor so that it will share resources with another motor block by setting the ResourceNumber to the appropriate Motor Block number. Each motor block can have up to two stepper motors mapped to it. The Step Resource Number reflects which motor block a stepper motor is mapped to. For more infomation, see the XMP-Pulse Appliction Note 218.

  • DAC Offset-- Adds an offset value to the Motor's DAC Output signal. Valid values are +10V through -10V.
  • AUX DAC Offset-- Adds an offset value to the Motor's Auxiliary DAC Output signal. Valid values are +10V through -10V.
  • SIM4-- Scale Interpolation Module. For more information regarding the SIM4 module, refer to Application Note 206, available from MEI.

Enabled-- Using SIM4 module.

(not enabled)-- Not using SIM4 module.

Configuration Attributes: "Events" Tab Page

The generation of Motor events is based upon the Motor configuration attributes.

Motor events are state changes in the motor object that can be programmed to trigger a particular action. The status of motor events can be monitored in the Event Status page of the Motor Summary window. Motor events are passed up to the Motion Supervisor object (via Filter and Axis objects) and can be monitored as event status flags on the Status tab page on the Motion Supervisor Summary window. If action is taken when the event is triggered, then the event status flag is "sticky," i.e., stays on until explicitly cleared by the user. This allows the user to determine which motor(s) caused an error. Events have some or all of the below configurable attributes.

Triggers

Triggers listed on the Motor Summary / Events tab page include:

Triggers can be a state change (e.g., Amp Fault Trigger or Hardware Negative Limit Trigger) or positional information (e.g., Error Limit Trigger).

Inverted-- I/O polarity is inverted.

(not inverted)-- Condition triggers event.

Actions

Actions listed on the Motor Summary / Events tab page include:

Actions are taken when an event is triggered (see "Triggers" section above). In all cases, the following acions are available:

None-- No action taken. The event status will be flagged only while the condition of the event is met. For all other actions, the event status is "sticky."

Stop-- Stop the motor within the Stop Time defined in the Motion Supervisor / General Config tab page associated with the motion of this motor. There is no effect on the state of the axis (axes) or Motion Supervisor(s) associated with the motor. The event status is "sticky," but it will clear the next time motion is commanded.

E-Stop-- Stop the motor within the E-Stop Time defined in the Motion Supervisor / General Config tab page associated with the motion of this motor. The Axis (or Axes) and Motion Supervisor(s) associated with the motor will be left in an error state.

E-Stop, Abort-- Same as E-Stop action (above), except that the motor amplifier is disabled after the motor stops. An additional delay can be defined by setting the Amp Disable Delay attribute on the Motor Summary / General Config tab page.

Abort-- Disable the motor amplifier. A delay can be inserted before disabling the amplifier by setting the Amp Disable Delay attribute on the Motor Summary / General Config tab page.

Duration

Minimum amount of time, in seconds, that the Trigger condition must exist for the event to trigger.

Direction

The Direction attribute, when Enabled, characterizes the Hardware Negative or Positive Limit Trigger directionally.

When not enabled, the event will always be triggered, even when the motor is not in motion. When enabled, both hardware and software limit events are triggered when the motor is commanded to move only in the Direction the limit is associated with.

Configuration Attributes: "I/O" Tab Page

Tranceiver (XCVR) configurations are controlled from the Motor Summary /
I/O tab page. Input-output status can be monitored by viewing the I/O status page at the bottom of the window.

  • XCVR A[B, C] Config-- Configures transceiver (XCVR) for use.

Input-- XCVR configured to receive an input signal.

Output-- XCVR configured to send an output signal.

Step-- XCVR configured for step mode. (XCVR A and B only.)

Dir[ection]-- XCVR configured for direction mode.
(XCVR A and B only.)

CW-- Clockwise. (XCVR A and B only.)

CCW-- Counterclockwise. (XCVR A and B only.)

Quad A-- Standard quadrature operation (A).
(XCVR A and B only.)

Quad B-- Standard quadrature operation (B).
(XCVR A and B only.)

Compare-- XCVR C only.

Diag-- XCVR C only.

  • XCVR A[B, C] Invert-- Inverts the polarity of XCVR configured for Output (incl. step, etc.) if Inverted is selected.
  • XCVR A[B, C] Out Level-- Active or (not active).
  • User Out: Invert-- Inverts the polarity of output bit (Inverted), or normal.
  • User I/O: Out Level-- When Active, internal logic sets bit level to high.
Configuration Attributes: "SinCom" Tab Page
  • Mode--

None-- Non-commutated.

Closed Loop Mode-- Commutated, closed loop.

Open Loop Mode-- Commutated, open loop.

Simulate-- Sets the motor commutation mode to MEIXmpCommModeSIMULATE.

  • Length-- Number of encoder counts per revolution for a rotary motor and the number of counts of one electrical cycle length for a linear motor.
  • Scale-- (Type float) Total number of commutation points per motor revolution, divided by the total number of encoder counts per revolution (i.e., Length).
  • Output Level-- Sets the DAC level during open-loop commutation. Output level is in DAC units (i.e., 32,767 = 10V).
  • Offset-- Expressed in units of commutation table points (i.e., 1024). 1024 table points equal 360 electrical degrees.
  • Phase Delta-- Usually set to 120 degrees for a three-phase, brushless motor with 120 degrees of phase separation. [120 degrees is represented by 341 commutation table points (i.e., 1024/3).] Switchable options include: 0 degrees; 90 degrees; 120 degrees.

    Note

             90 degrees is normally reserved for a two- or four-phase motor.
  • DAC Phasing-- Sets phasing of three-phase motors.

(Normal)-- Phasing is unaltered.

Reversed-- Phasing is reversed 120 degrees.

Status Attributes: "Status" Tab Page

This page displays the status of motor events, as well as several general stats flags. DAC output level is also displayed.

  • Amp Fault-- Amp Fault Event status
  • Home Limit-- Home Limit Event status
  • Position Err Limit-- Position Error Limit Event status
  • HW Neg. Limit-- Hardware Negative Limit Event status
  • HW Pos. Limit-- Hardware Positive Limit Event status
  • SW Neg. Limit -- Software Negative Limit Event status
  • SW Pos. Limit-- Software Positive Limit Event status
  • Power Failure-- Power Failure Event status
  • Comm. Error-- Communication Error status flag
  • Illegal State -- Illegal State status flag
  • Abs. Enc. Fault -- Absolute Encoder Fault status flag
  • DAC Level-- DAC output level in volts
  • Aux DAC Level -- Auxiliary DAC output level in volts
Status Attributes: "I/O" Tab Page

This page displays Motor I/O status.

  • Amp Enable-- Amp Enable output status
  • XCVR A In Level-- Transceiver A input level
  • XCVR B In Level-- Transceiver B input level
  • XCVR C In Level-- Transceiver C input level
  • XCVR D In Level-- Transceiver D input level
  • XCVR E In Level -- Transceiver E input level
  • XCVR F In Level-- Transceiver F input level
  • User I/O In Level-- User I/O input level
  • Broken Wire -- Broken Wire input level
  • Illegal State -- Illegal State input level
  • + Overtravel-- Positive Limit input level
  • - Overtravel-- Negative Limit input level
  • Home Sensor-- Home Limit input level
  • Amp Fault-- Amp Fault input level


SERCOS Ring Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
SERCOS Ring Objects

Configuration Attributes

All SERCOS Ring attributes are read-only in Motion Console. They are set by running a custom SERCOS ring initialization application (sercinit).

  • Phase-- Displays current SERCOS phase.
  • Node Count-- Displays the number of Nodes found on the SERCOS loop.
  • Baud Rate-- Current baud rate used in SERCOS loop.
  • Intensity-- Intensity of XMP's transmitter in SERCOS loop.


SERCOS Node Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
SERCOS Node Objects

SERCOS Node objects are mapped to SERCOS Ring objects. The SERCOS Node attributes viewable in the Node Summary are read-only. They are set by running a custom SERCOS ring initialization application (sercinit).

Configuration Attributes
  • Address-- SERCOS address of the Node.
  • Motor-- Motor number assigned to the SERCOS Node.
  • Filter-- Filter number assigned to the SERCOS Node.
  • Mode-- Operating mode for control loop. A Node may be in one of the following modes:

Openloop, Position dual

Openloop, Position external

Openloop, Position motor

Openloop, Torque

Openloop, Velocity

Position, Torque external

Position, Torque motor

Position, Velocity external

Position, Velocity motor

For Openloop and Position motor, feedback is provided by the motor; for Openloop and Torque, there is NO feedback.

Status Attributes

Node status attributes display the current state of bits in the Node's status word.

Amplifier-- Handshake bit. Service transport and handshake for Node.

Busy-- If set (1), Node is processing service channel data.

Service Error-- If set (1), error ocurred processing service channel data.

Procedure-- If set (1), a procedure has finished in the Node.

Real Time 1-- State of real-time status bits. See IDNs for mapping.

Real Time 2-- State of real-time status bits. See IDNs for mapping.

Diag. Class 3-- If set (1), see IDN S-0-0013.

Diag. Class 2-- If set (1), see IDN S-0-0012.

Shutdown-- If set (1), see IDN S-0-0011. This will cause an Amp Fault to occur in the XMP.

Ready-- Indicates ready state of Node:

  • 0 = 0x00 -> not ready
  • 1 = 0x01 -> ready for main power
  • 2 = 0x10 -> ready; main power applied; servo not active.
  • 3 = 0x11 -> ready; main power applied; servo active.


Idn Objects

CONTENTS:
Object-oriented Motion Control
Motion Console Objects
Motion Console User Interface
Main Motion Console Frame
Adding a New Controller
Object Summary Windows
Object Explorer
Object List Configuration Dialog Boxes
Configuring New Systems with Motion Console
Getting Started with Motion Console
Saving Parameter Settings
Associating Objects with Motion Console
Configuring a Motion Supervisor
Mapping One Object to Another
Removing (Deleting) a Mapped Object
Safety Reminders
Motion Console Objects
Controller Objects
Motion Supervisor Object
Axis Objects
Filter Objects
Motor Objects
SERCOS Ring Objects
SERCOS Node Objects
Idn Objects
CHAPTER 2
Motion Console
Idn Objects

Configuration Attributes

Idn objects are mapped to SERCOS Node objects. Note that attributes Factor, Length, Variable, Procedure, Data Type and Places are all aquired from the Attribute parameter.

Number-- IDN element #1. IDN number.

Name-- IDN element #2. Name; text string.

Attribute-- IDN element #3. Attributes; 32-bit binary value.

Units-- IDN element #4. Units, text strings.

Minimum-- IDN element #5. Minimum data value, valid only if data field is a 16- or 32-bit value.

Maximum-- IDN element #6. Maximum data value, valid only if data field is a 16- or 32-bit value.

Data-- IDN element #7. Writable. Can be 16 or 32 bits, or a text string. If the data is variable, 8-bit data, then it will be displayed, and editable, as a character string. If it is variable 16-bit, 32-bit, or IDN, then it is editable as a multi-line edit control.

Factor-- Scaling factor used for the data element. See also Places parameter.

Length-- Size of data in the data element:

  • 0 = 8 bits
  • 1 = 16 bits
  • 2 = 32 bits

Variable-- Indicates whether data element is of variable length.

Procedure-- Indicates whether IDN is a procedure or not.

Data Type-- Specifies data type of data element. The Data Type will be one of the following:

Binary
Unsigned
Long
Hex
Text
IDN

Places-- Places after the decimal point. Used with Factor (see above) to determine scaling applied to data.
E.g., Places = 7 yields scaling of Factor * 10-7 places.

Count-- Number of entries in data field.

Periodic Refresh-- When Enabled, Motion Console periodically updates element #7 (Data).


Description of Motion Scope

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Description

Motion Scope plots and traces IO signal data from the motion controller. It is similar in its presentation to an oscilloscope, and provides a utility for checking and troubleshooting motion control systems. It is a purely "passive," read-only utility, with no ability to write data, or control motion. Combined with the Motion Console and VM3 utilities, Motion Scope serves as the system designer's eyes while working with the XMP motion control system. Motion Scope can also be used in conjunction with the designer's motion control application.

Material Contained Within This Chapter

This chapter contains two important sections: an early section provides a Quick-start Guide to using Motion Scope for new users; in another section, Motion Scope's unique control features are referenced in detail.


Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Installing and Launching Motion Scope

Both Motion Scope and Motion Console are installed using a dedicated InstallShield software release package. To launch Motion Scope, locate and double-click its application icon.


Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Motion Scope User Interface

Motion Scope is designed to function as a virtual "oscilloscope," tracing signal data and presenting it visually to the user. Signal data can be assigned separate colors (see Trace / Color section below).

In addition, Motion Scope data can be exported for use by third-party programs and spreadsheets. See the "Export" section for more information.


Motion Scope Quick-Start Guide

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Motion Scope Quick-start Guide

Quick-start Description

This section will guide you through the most basic steps of using Motion Scope. It does not describe how to utilize advanced features, but it should prove helpful to new users. Three quick-start scenarios are presented below:

Scenario A: How to use the built-in Demo feature. No XMP controller required.

Scenario B: How to use Motion Scope motion data from XMP controller configured for stepper motors with simulated (step loopback) feedback.

Scenario C: How to use Motion Scope with Motion Console or application. Motion data from XMP controller with real motion system.

Select a scenario (e.g., "B"), then follow the steps labeled with that letter below.

1. Launch Motion Scope

Double click on the Motion Scope icon to launch the utility. A pane is displayed for XMP Controller 0:

  1. Motion Scope start-up screen.

If you wish to close this pane, click on the Close icon [image] in the upper-right corner.

2. Open and Configure a New Pane

If a pane is not already visible, the Motion Scope screen will appear blank, as shown here:

To open a new (or additional) pane, click on the File / New menu option. You will be presented with the Pane Mode panel:

The Pane Mode panel identifies the source of signal data to be plotted. Depending upon your scenario, use the following list as a setting guide:

  • To Quickly Demonstrate Motion Scope's Features

If you wish to quickly demonstrate Motion Scope's features without connecting to real signal data, use the built-in Demo option. You should set your Pane Mode options as follows:

Data Source | Demo
Acquire Cycle | 50 ms (default setting)
Redraw Time | 200 ms (default setting)

  • To Use Motion Scope Using Simulated Feedback Data

Motion Console can be used to generate simulated data, which is then viewed using Motion Scope. The simplest way to do this is to run Motion Console on the same platform where Motion Scope is installed. Set your Pane Mode options as follows:

Data Source | Device (MPI)
Controller Number# | 0
Acquire Cycle | 50 ms (default setting)
Redraw Time | 200 ms (default setting)

NOTE: The Motion Console set-up for generating simulated feedback data is included below in Step #3.

  • To View Real Signal Data with Motion Scope

If you intend to use Motion Scope to view real motion control data, set your Pane Mode options as follows:

Data Source | Device (MPI) (if controller card resides within same platform where Motion Scope is installed)
Controller Number# | # of contoller card (On platforms running a single control card, set this to 0; otherwise, enter the number of the active controller.)
- OR -
Data Source | Client (MPI) (if controller card resides on a remotely networked platform, separate from where Motion Scope is installed)
Controller Number# | # of contoller card (On platform where control card resides)
Port | of platform where controller is installed
Server | IP address of platform where controller is installed
Acquire Cycle | 50 ms (default setting)
Redraw Time | 200 ms (default setting)

The Motion Console set-up for generating fake signal data is included below in Step #3.

Click the OK button to enter settings into the Pane Mode panel and close.

3. Configure Trace Settings

At this point, you have a blank pane with no traces. The next step is to tell Motion Scope which signal data to trace. This is done using the Pane / Traces menu item.

To Quickly Demonstrate Motion Scope's Features

If you have configured the new pane to run the built-in Demo (from Step 2-A above), you have only four sources of signal data available to you. All of them are "fake" and exist only in your computer's memory. Now, let's look at them.

Click either on the Pane / Traces menu item, or use the Traces button at the top-middle of the display pane to access the Select Traces Set panel:

In the left column of the panel are listed the four sources of signal data available to you. They consist of:

  • ActualPosition
  • ActualVelocity
  • PositionError
  • ControlOutput

Remember, the displayed signals consist of "fake," archival data for demonstration purposes only. They do not correspond to anything real on your motion controller.

To select demo data for tracing, click on the signal(s) to be plotted, then click on the Add==> button near the bottom-left corner of the panel. The selected signal(s) will be listed to the right, within the "Trace Set for Pane" window. If you make a mistake, or want to deselect a signal, highlight the signal with your mouse, then click on the Delete button on the right side of the pane.

Click the OK button to close the Select Traces Set panel.

To Use Motion Scope Using Simulated Feedback Data

After you have configured the new pane to view simulated data from an XMP controller (from Step #2B above), Then you need to configure the XMP controller for step controller for step motor control with sinusoidal feedback:

  • Disconnect your XMP controller from all external motion control hardware. (i.e., leave the controller in the computer, but disconnect all external cables between the card and motion equipment.) This will allow you to practice with Motion Console and Motion Scope in complete safety.
  • Launch Motion Console.
  • Use the Object Explorer to map Axis 0 to Motion Supervisor 0 (MS 0).

Map Motor 0 to Filter 0 and Filter 0 to Axis 0.

  • Open the Motion Supervisor Summary / General Config tab page for Controller 0.

Set the Motion Type field to either Trapezoidal or S-curve.

On the Motion Supervisor / Actions page, switch Repeat Mode to Enable.

  • Open the Motor Summary / General Config tab page.

Set the Type field to Stepper.

Switch the Step Loopback field to Enabled.

  • Open the Axis Summary / Motion tab page.

Set Position 1 to 0.

Set Position 2 to 10000.

Set Velocity, Acceleration and Deceleration to 100000.

Your Motion Console panels should appear similar to those shown here:

  • Set Motion Console in "motion" by clicking on the Move to Farthest Position button [image] You should see the Command and Actual Position fields on the Axis Summary panel count back and forth between the Position 1 and 2 values (simulating a back-and-forth motion). This will continue running until you click on the MS Summary panel's Stop icon.
  • If you experience difficulty, recheck your Motion Console settings. If the system appears to be hung, click on the Stop icon on the MS Summary panel and the Clear Fault button, then retry the Move to Farthest Position button.

With the XMP controller generating the simulated data, you are now ready to use Motion Scope to view the data. Click either on the Pane / Traces menu item, or use the Traces button at the top-middle of the display pane to access the Select Traces Set panel:

In the left column of the panel are listed the signal data available to you. Remember that for this example we have configured Motion Console to utilize Axis 0; therefore only Ax 0 signals will produce interesting traces. All other non-configured signals will generate flat, "dead" traces.

To select data for tracing, click on the signal(s) to be plotted, then click on the Add==> button at the bottom of the panel. The selected signal(s) will be listed to the right, within the "Trace Set for Pane" window. If you make a mistake, or want to deselect a signal, highlight the signal with your mouse, then click on the Delete button on the right side of the pane.

For this example, click on the Ax 0 Cmd Pos and Ax 0 TC. Velocity signals.

Click the OK button to close the Select Traces Set panel.

To View Real Signal Data with Motion Scope

If you have configured the new pane to view real motion controller data (from Step #2C above), you may now proceed to setting your hardware into motion and using Motion Scope to view controller data. We will follow a procedure similar to Step #3B above, except that you do not need Motion Console. The intent here is to establish a simple, repeated motion with your hardware, then trigger Motion Scope at the point of interest to you.

If Using Motion Console...
If you wish to use Motion Console to command motion, configure it now to operate your hardware. Motion Console is detailed in separate chapters of this manual. Ideally, you should establish a simple, repeating motion that can be examined over and over.

If Using a Motion Control Application...
If you wish to examine motion details as hardware is commanded by a motion control application, set your application up now. Again, a simple, repeating motion is preferred.

You are now ready to use Motion Scope to view the data. Click either on the Pane / Traces menu item, or use the Traces button at the top-middle of the display pane to access the Select Traces Set panel:

In the left column of the panel are listed the signal data available to you. Any signal data can be plotted, but only active signals will produce interesting traces. All other non-configured signals will generate flat, "dead" traces.

To select data for tracing, click on the signal(s) to be plotted, then click on the Add==> button at the bottom of the panel. The selected signal(s) will be listed to the right, within the "Trace Set for Pane" window. If you make a mistake, or want to deselect a signal, highlight the signal with your mouse, then click on the Delete button on the right side of the pane.

Click the OK button to close the Select Traces Set panel.

4. Configure Trigger

The next step consists of configuring the trigger to start Motion Scope. Because Motion Scope has a limited memory buffer, it cannot acquire and display data indefinitely. You must configure it to acquire data during the time of particular interest to you.

Triggering operates the same, regardless of how you have configured your Trace panel, or whether you are working with real or fake data.

Click either on the Pane / Trigger menu item, or use the Trigger button at the top-middle of the display pane to access the Trigger Conditions panel:

For quick-start purposes, we will trigger manually. Other forms of triggering are discussed in the "Trigger" reference section of this chapter below.

  • Set "Start Condition"

To manually trigger Motion Scope, select the Go button menu item.

  • Set "End Condition"

To halt tracing manually, select the Stop button menu item.

  • Set "Trigger Detection"

Select the Status Data Stream menu item.

Click the OK button to close the Trigger Conditions panel.

5. Generate a Trace!

The final step consists of making a trace with Motion Scope. At this point, you should have followed Steps #1-4 above to configure your pane, select the traces you want, and set up manual triggering. Signal data--either real or simulated--should now be available for plotting.

To trigger a plot, click on the Go button located at the front of the display pane. You should see the data trace begin on the left side, then sweep right and continue.

Your pane may appear as shown here:

When triggering manually, Motion Scope will continue tracing data until the Stop button is clicked.

In the "Motion Scope Feature Reference" section remaining in this chapter, you may learn more about Motion Scope's features, or contact MEI for assistance.


CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Motion Scope Toolbar Functions

File Menu Items

File menu items found in Motion Scope match those found in most Windows programs. They may be accessed either through the File pull-down menu, or (in the case of New, Open and Save), by clicking on icons located within the toolbar.

Note

 Motion Scope files consist of Motion Scope settings, not traces. To save traces, use a print screen command (Print Scrn key) from within the Windows operating system to copy the screen's image to your computer clipboard. Once the screen is copied in this fashion, you may use a graphics program to edit and save the image.

New-- Opens a new Motion Scope file.

Open-- Opens the selected Motion Scope file. If the selected file includes trace data, you can then choose to import the data by checking the "Include data" checkbox at the bottom of the "Open" dialog box. You can also select the file to be opened as read-only by checking the "Read-only" checkbox. In this case, the pane associated with the file will not be "active," (i.e. data acquisition will be disabled). If the selected file does not include data, then the "Include data" and "Read-only" checkboxes are disabled. See screenshots below.

Close-- Closes the selected Motion Scope file.

Save-- Saves the selected file to a directory specified by the user.

Save As-- Assigns a new file name to the current file.

Print-- Prints the selected file as it appears on the display panel.

Note

 The layout of the display panel may be altered by utilizing View commands before printing (see "View Commands" section below).

Print Setup-- Accesses your computer's printer setup utility.

Exit-- Quits the Motion Scope utility.


View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
View Menu Items

View menu items permit you to alter the layout of the Motion Scope panel by enabling/disabling various toolbars and menus. Refer to the diagram below for the location of each View menu item.

Each menu item is fully described in its own section below.

Note

 Movable control bars-- All control bars may be moved from the display panel to your computer's desktop area by clicking and dragging with the mouse. Control bars continue to operate normally while not on the panel.


Pane Menu Items

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Pane Menu Items

A "pane" is a viewing area within Motion Scope's main frame, and Pane menu items are at the heart of what Motion Scope does. They allow you to select which IO signal data is plotted, how plots are triggered, and how they are displayed. Motion Scope can display multiple panes simultaneously, one per controller.


Display

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Display

The Pane Display Settings panel sets the X- and Y-axis plotting characteristics for Motion Scope. Menu Items include:

Y-axis / Connect points-- When enabled, traces are displayed with the Y-axis plotted as a continuous line between sample points. When disabled, Y-axis sample points are plotted as discrete points.

X-axis menu items:

Sample Band-- When enabled, a blue sample band is added to the bottom of the plot which indicates individual samplings. Immediately below the blue sample band, separate Gain Index and Custom Drive Mode bands are visible when zoomed-in to higher magnification using the
Zoom In button (see below).

  • Gain Index (0 = red, 1 = yellow, 2 = orange, 3 = green)
  • Custom Drive Mode

Sample numbers-- Changes the X-axis units from milliseconds (default) to sample numbers.

Note

 Enabling this menu item will affect the Range units displayed within the Range bar near the top of the Motion Scope
panel.


Export

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Export

The Export command allows the export of Motion Scope trace data in text (*.txt) format for third-party programs such as spreadsheets (e.g., Microsoft Excel). Exported data is tab and new line-delineated. Tabs delineate individual fields of data, new lines delineate a sample's worth of data. A segment from a typical presentation for a dual trace ("Ax 0 Cmd Pos" and "Ax 0 Act Pos") is shown below:

The leftmost column is the sample number ("Sample #"), followed by columns for "Ax 0 Cmd Pos" and "Ax 0 Act Pos," respectively.

The text file name defaults to the current Controller number. For example, in the Save As panel above, the File name field defaults to "Controller 0.txt," which reflects the currently active controller.


Import

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Import

The Import command allows the import of Motion Scope trace data in text (*.txt) format from third-party programs such as spreadsheets (e.g., Microsoft Excel). You can only import data that is tab and new line-dilineated. See Export section for an example of a properly formatted .txt file.

Note

 In Microsoft Excel, you can save data in a spreadsheet as a *.txt file by selecting “Text (Tab delimited) (*.txt)” from the Save As Type menu options.


Mode

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Mode

The Pane Mode panel is the first panel presented when opening a new (File / New) trace pane. Through it, the user informs the Motion Scope software which source of signal data to use, and what the data access and redraw cycles are.

Data Source-- The actual source of data to be traced. Three menu items:

Demo-- Built-in data traces for demonstration and training purposes.

Note

 This setting is not used for signal data measurements!

Device (MPI)-- Standard, default option for examining signal data from controller cards installed within the host computer running Motion Scope.

Controller #-- PCI-assigned controller card whose signal data is to be accessed.

Client (MPI)-- Option for examining signal data from a controller card installed within a remotely networked client computer.

Controller #-- PCI-assigned controller card whose signal data is to be accessed.

Port-- Port number of client computer to be accessed.

Server-- IP address (XXX.XXX.XXX.XXX) of client computer to be accessed.

Acquire Cycle Time-- Time between acquisitions of view data from the controller. Data is appended to the memory buffer.

Redraw Time-- Cycle time to write (plot) signal data in memory buffer to display pane.


Print

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Print

"Print" the contents of the active pane. The Print Setup dialog box will appear. You can also print by clicking, File > Print.


Traces

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Traces

"Traces" refer to the actual signal data plot(s) generated on a display pane. The Traces menu item may be selected either by clicking on Pane / Traces in the pull-down menu, or by clicking on the Traces button on the main display. This displays the Select Traces Set panel:

On the left side of the panel are listed some of the possible signal data which can be traced. They are selected by clicking with the mouse, then clicking on the Add==> button below.

Click on the signal data to be traced , then on the Add==> button . The signal data will be added to the Trace Set for Pane list.
  • To select all signal data between two listings, hold down the Shift key while selecting with the mouse.
  • To select two or more signal data, hold down the Ctrl key while selecting each with the mouse.

Trace Ordering-- Once a list is defined in the "Trace Set for Pane" window, you may order the arrangement by using the Trace Ordering switch. There are three menu items:

UserName-- Orders the list by user name.

MapName-- Orders the list by map name.

Address-- Orders the list by memory address (as ordered within the controller's firmware memory). TIP: click this menu item again to reverse the order.

Trace Ordering menu items arrange signal data on the Trace Set for Pane window by user name, map name, or memory address.

Modify Trace

Modify Trace menu items create, edit and close individual traces. These menu items are accessed on the right side of the Select Traces Set panel:

New and Edit-- Clicking on either the New or Edit button displays the Edit Trace Properties panel. If no trace is currently listed or selected within the "Trace Set for Pane" window, only the New button may be used.

Name-- Name assigned to the new or edited trace. Trace names can be assigned to correlate to specific axes, such as "X," "Y," etc.

Address-- Hexadecimal memory address to be assigned to the selected trace.

Note

 An Address must be specified for each Name. To determine the memory address of signal data, use the VM3 utility (described in Chapter 4 of this manual).

In the example below, SystemData.SampleCounter is shown on the VM3 screen with its hexadecimal address. When this address (0x00028010) is entered into the Address field of the Edit Traces Properties window, it may be plotted on the Motion Scope grid. The data's name (SystemData.SampleCounter) is manually entered into the Name field. Configure the Trigger window, then plot the data. Notice that the plot of SystemData.SampleCounter, which records time, is a constantly increasing line.

Plot of SystemData.SampleCounter data.

Bitmasking-- Allows bitmasking of current trace address. The following fields are used:

Masking Enabled-- When enabled, the data is masked.

Mask-- Bit pattern to be masked (bitwise ANDed with mask).

Normalize Right-- If a Mask has zeros in its lower-order bit(s), the data value is shifted to the right. This is especially convenient for viewing binary, two-state values.

Data type-- Specifies the data type of the value stored at the Address. The following data types are selectable:

long-- Data is a long integer (32 bits).

float-- Data is a floating decimal point value (32 bits).

unsigned long-- Data is an unsigned, long integer (32 bits).

Display as hex-- When selected, data stored at the Address is displayed in hexadecimal form. If not selected, data stored at the Address is displayed in its default format.

Units-- Units applied to the vertical (Y) axis of the display pane. The following units are selectable:

Counts-- Encoder counts.

Counts/sec-- Encoder counts per second.

MilliSecs-- Milliseconds.

MilliVolts-- Millivolts.

None-- No units are applied to the vertical axis.

OK-- Enters settings and closes the Edit Trace Properties panel.

Cancel-- Closes the Edit Trace Properties panel without changing settings.

Note

 Demo traces (available from the Pane / Mode menu item) cannot be edited.

Status Banding

The Status Banding menu item within the "Select Traces Set" panel turns on-off separate trace bands at the top of the pane for monitoring IN_COARSE and IN_FINE status on a single axis. Two color schemes are used: green = FALSE; red = TRUE.

Trace showing use of Status Banding menu items.

In above, the Status Banding menu item has been enabled for the axis indicated by the Axis field. Command velocity (trapezoidal profile) reveals motor movement. As the command position (curved profile) crosses the IN_COARSE position value at [image] , the IN_COARSE band (topmost band) changes color from green-FALSE, to red-TRUE. (Meaning, the position of the axis is now within the IN_COARSE envelope of the target position.) As the axis reaches the target position, it enters the IN_FINE envelope at [image] , and the lower (IN_FINE) status band changes color from green-FALSE, to red-TRUE.

Note

 The IN_COARSE status band remains green-FALSE for all conditions if the servo-stepper system is not commanded (e.g., dead or disconnected). Green can be interpreted as "not in position," which usually, but not always, means "moving."


Trigger

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Trigger

The Trigger Conditions panel may be accessed in either of two ways:

  • Click on the Pane / Trigger menu item.
  • Click on the Trigger button.

Trigger includes menu options for beginning and ending signal data acquisition, such as by manually clicking on the Go and Stop buttons, or through the use of external inputs such as motor movement.

The Trigger Conditions panel is divided into four different sections, each of which is described below, along with their respective menu items.

Start Condition

Start Condition defines the triggering event used to start signal data acquisition. This may be either user-triggered, or activated automatically using an outside condition.

Go button-- Traces are started when the Go button is clicked on the front of the display pane. Selecting this option displays two support buttons on the front of the display pane:

  • Go-- Tracing begins immediately after the Go button is clicked.
  • Stop-- Tracing is halted when the Stop button is clicked.

Motion Start-- Tracing begins when movement is detected in the Motion Supervisor chosen for tracing after the Arm button is clicked on the display pane. Selecting this option displays two support buttons on the front of the display pane:

  • Arm-- The Arm button is displayed on the display pane whenever Motion Start is selected. Tracing does not begin until the Arm button has been clicked; tracing ends according to the condition set in the "End Condition" box of the Trigger Conditions panel (see below).
  • Repeat-- The Repeat button is used to continue data acquisition beyond a single pane, after the Arm button has been clicked. The previous move data will be overwritten and the new move data will be displayed.

External Event-- (Not yet implemented.)

Pre-Trigger (ms)-- [Usable only when Motion Start enabled.] Amount of data to include with plot before triggered data.1

End Condition

The End Condition defines how tracing is to be halted.

Stop button-- Tracing ends when the Stop button is clicked on the main display panel.

Buffer Full-- Tracing ends when the data buffer has filled. NOTE: the data buffer size is set by the MaxBuffer field on the main display pane and may be as large as 50000 ms.

Motion Done-- Tracing ends when motion halts (i.e., when MotionDone condition is TRUE).

External Event-- (Not yet implemented in Version 1.19.07.)

Trigger Source

If either the Start Condition or End Condition fields are set to Motion Start or Motion End respectively, the Trigger Source field will be enabled. This field specifies which Motion Supervisor is used to trigger start and/or end of tracing.

Trigger Detection

Trigger detection may be implemented either by monitoring changes to motion status in the data stream (Status Data Stream), or by polling the controller for status (Status Poll). Note that changes to the motion status can be extremely fast, and may go undetected. Under most conditions, selection of the Status Data Stream menu item is recommended.

1. Acquisition of data is ongoing, even before the start of tracing. When a Pre-trigger time is entered, the display will include buffered data of Pre-trigger length with the triggered trace.


Trace Menu Items

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Trace Menu Items

The Trace pull-down menu features one menu item:

  • Color-- This feature is used to custom-color individual traces to distinguish them.
  • Edit-- Open the Edit Trace Properties dialog box. This is the same dialog box that is documented in the Traces section.

To use the Color menu item, first select the trace to be colored from the pull-down Trace field in the upper-left corner of the main Motion Scope panel. Next, click on Trace / Color to access the Color panel.

Colors may be chosen directly from the pallet provided, or click on the Define Custom Colors>> button to access the custom color function. Custom colors are defined in one of two ways:

  • Move the cursor to a point of the spectrum pallet which best approximates the desired color.
  • Enter the correct values for: Hue, Saturation, Luminosity, Red, Green, and Blue to render the desired color.

To add the color to the custom color to the pallet, click on the Add to Custom Colors button.

To set the selected trace to the new color and close the Color panel, click on the OK button.


Window Menu Items

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Window Menu Items

Window menu items control the manner in which two or more Motion Scope panels are displayed. There are two menu items:

Cascade-- Presents panels in a "cascading" format.

Tile-- Presents panels in a "tiled" format.

Note that in either format panels may be dragged and sized to suit the user. (The Windows menu items merely set up the initial presentation.) Note that the Tile format is useful for comparisons between multiple plots.


Max Buffer (ms) and SampleSize

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Other Data and Display Features

In addition to the data and display menu items described above, there are other basic display features built into Motion Scope. These menu items control qualities such as presentation and data buffer size.

MaxBuffer (ms) and SampleSize (samples)

The MaxBuffer and SampleSize fields occupy the same portion of the Motion Scope control panel; when one is selected, the other is deselected. Both serve the same function: setting the amount of memory to be used for recording data. Both also affect X-axis scaling of the display pane.

  • The Max Buffer field is displayed when the Display / X-Axis / Sample Numbers menu item is not selected. This value is entered in milliseconds and may be set up to 50000 ms (50 seconds).
  • The SampleSize field is displayed when the Display / X-Axis / Sample Numbers menu item is selected. This value is entered in samples and may be set up to 200000.

MaxBuffer and SampleSize set the amount of buffered memory available for tracing. As new signal data is written to the memory buffer, old signal data is permanently lost. Therefore, you should set this value to a size at least as large as the event to be traced.

Note that as the size of MaxBuffer and SampleSize increases, the width of the XOffset slider bar decreases. (See "XOffset" section below.) This is because, for larger samples, the displayed portion of the data shown in the pane represents a smaller portion of the whole.


XRange and XOffset Fields

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
XRange and XOffset Fields

The XRange value controls the scale of the X-axis. As this value is changed, plots are stretched and compressed horizontally; simultaneously, X-axis units change at the bottom of the display pane. XRange units of measurement depend upon whether MaxBuffer (units in milliseconds) or Sample Size (units in samples) is selected in the Pane / Display window. You may enter XRange values in one two ways:

  • Manual entry in the XRange field (click with cursor and enter value).
  • Use of Zoom Bar functions.

As XRange is increased-decreased, X-axis units are rescaled to fit the display pane.

The XOffset value controls which X-axis portion of the buffered data (see "MaxBuffer" section above) is displayed inside the pane. XOffset may be adjusted by moving the slider bar left-right, or by entering a value into the XOffset field manually.


YScale and YOffset Fields

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
YScale and YOffset Fields

YScale sets Y-axis scaling of data selected in the Trace field. You may enter YScale values in one of two ways:

  • Manual entry in the YScale field (click with cursor and enter value).
  • Use of YScale slider bar.

IMPORTANT! Displayed Y-axis units apply only to data selected in the Trace field! As different data is selected using the Trace pull-down menu, Y-axis values change. Verify that the correct data is selected in Trace field before reading units.

YOffset is used to offset displayed Trace plots vertically. This can be especially useful when trying to separate one data plot from another (e.g., "Ax 0 Com Pos" versus "Ax 0 Act Pos").

You may enter YOffset values in one two ways:

  • Manual entry in the YOffset field (click with cursor and enter value).
  • Use of YOffset slider bar.

To realign offset data plots, use AutoScale and (if applicable) zoom Full Out.


XRange and YRange Bar

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
XRangeBar and YRangeBar

XRangeBar- The XRangeBar provides another way of modifying the XScale and XOffset of either the currently selected trace or all traces.

Left Click +Drag - Move selected trace.

Shift + Left Click - Same as above, but applied to all traces.

YRangeBar- The YRangeBar provides another way of modifying the YScale and YOffset of either the currently selected trace or all traces. The functionality of the YRangeBar is broken down into the following parts:

High Span--

Left Click +Drag - Nudge selected trace up. This decreases the YOffset.

Shift + Left Click - Same as above, but applied to all traces.

Ctrl + Left Click - Extend the YRangeBar up to the clicked location for the selected trace. This affects both the YOffset and the YScale.

Ctrl + Shift + Left Click - Same as above, but applied to all traces.

Low Span-- behaves as the High Span, but in the opposite direction.

Slider--

Left Click +Drag - Move selected trace. This only affects the YOffset.

Shift + Left Click +Drag - Same as above, but applied to all traces.

Ctrl + Left Click - Shorten the Slider to the clicked position for the selected trace.

Shift + Ctrl + Left Click - Same as above, but applied to all traces.

Left Double-Click - Step in for the selected trace.

Shift + Left Double-Click - Same as above, but applied to all traces.

Right Double-Click - Step out for the selected trace.

Shift + Right Double-Click - Same as above, but applied to all traces.


Zoom and Step Buttons

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Zoom and Step Buttons

When traces are generated, the pane automatically scales the X-axis to the XRange size, and scales the Y-axis to accommodate the full vertical range of the data. Zoom and Step buttons are used to magnify portions of a pane by rescaling a selected area. Zoom buttons rescale both X- and Y-axis; the Step button rescales only the X-axis. To select an area for zooming or stepping, click and drag with the mouse to form a box cursor over the area of interest, then select one of the zoom buttons below.

Zoom In-- Magnifies area within box cursor by rescaling both X- and Y-axis.

Zoom Out-- Resizes previously zoomed-in area of pane to last used X- and Y-axis scaling.

Full Out-- Returns X- and Y-axis scaling of pane to their original (starting)
values. The pane's X-axis is resized to its full XRange value.

Step In-- Magnifies area within box cursor by rescaling only the X-axis.

Step Out -- Resizes previously stepped or zoomed-in area of pane to last used X-axis scaling.


Trace and AutoScale Menu Items

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope
Trace and AutoScale Menu Items

Trace-- The Trace field lists all currently plotted signal data using a pull-down menu. Y-axis scaling applies only to data currently selected from the Trace field.

Note

You may also select traces by clicking on them with the right mouse button.

The color of the selected trace can be toggled by clicking the left and right mouse buttons anywhere within the pane.

AutoScale button-- Automatically scales the vertical, Y-axis of the display pane according to the range of data points plotted within the space afforded by the user-sized window. Selection of this menu item disables the YScale and YOffset fields (see "YScale and YOffset Fields" sections above).


Direct Cursor Measurement of Traces

CONTENTS:
Description
Installing and Launching Motion Scope
Motion Scope User Interface
Motion Scope Quick-Start Guide
Motion Scope Toolbar Functions
File Menu Items
View Menu Items
Pane Menu Items
Display
Export
Import
Mode
Print
Traces
Trigger
Trace Menu Items
Window Menu Items
Other Data and Display Features
MaxBuffer (ms) and SampleSize
XRange and XOffset Fields
YScale and YOffset Fields
XRange and YRange Bar
Zoom and Step Buttons
Trace and AutoScale Menu Items
Direct Cursor Measurement of Traces
CHAPTER 3
Motion Scope

Direct Cursor Measurement of Traces

Motion Scope permits direct measurement of selected traces to determine X- and Y-axis values. This is done by clicking and dragging with the mouse (left button) while simultaneously holding down the Ctrl key.

The X- and Y-axis values for the cursor intersection are framed by fields at the lower-right and upper-left corners, respectively.


Introduction to VM3

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

Introduction

VM3 is the third version of the "View Memory" utility written for MEI motion controllers; earlier versions (VM and VM2) worked with DSP-series controllers. The VM3 utility allows you to view and alter data stored in memory on the XMP-series controller card. This includes data inside and outside the SHARC DSP processor. When using VM3 to alter data on motion controllers, exercise extreme caution at all times:

DANGER! Changes made to memory take effect immediately, including data designed for motion components such as motors and encoders. Verify that personnel are clear of the movement zone and equipment is safeguarded BEFORE making any changes to memory data. Always operate equipment with an emergency off switch (EMO) at the ready, especially when writing and testing new software configurations.


Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

Installing and Running VM3

VM3 is installed with each full XMP software installation, along with Motion Console, Motion Scope and various system files. The VM3 executable (vm3.exe) is normally located within the XMP/bin/Win95 and WinNT paths. The utility is launched from the DOS command prompt by entering vm3.

When booting, VM3 first examines data in the xmpNNLN.xmp file to map memory, where NNN is the firmware version number. It is necessary that the version of VM3 you are running matches the firmware version of the
xmpNNN.map file; otherwise, the system will fault or request an update.


VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

VM3 Layout

VM3 is organized into panels and functions, each of which is assigned a function key. The "Board Data" panel is accessed by pressing the F1 key, the "Commands" panel is accessed with the F2 key, and so on.

Function Key Assignments, VM3

Function
Key

Description

Esc

Exits VM3

F1

"Board Data" panel. XMP board configuration.

F2

"Commands" panel. Data organized by command number.

F3

"Auto" panel. Memory organized by object. Data is automatically displayed in most commonly used form, either hexadecimal or decimal.

F4

"Hex" panel. Memory organized by object. All data is displayed in hexadecimal form.

F5

"Decimal" panel. Memory organized by object. All data is displayed in decimal form.

F6

"Float" panel. Memory organized by object. All data is displayed in floating decimal point form.

F7

"Recorder" panel. (Not implemented in this version.)

F8

"Dump/Save" panel. Dumps xmp memory to xmpdump.bin.
F9 | "Reset." Resets motion controller (reloads from flash).
F10 | "Toggle." Toggles the screen between a 32-bit format and a 16-bit format.

Within panels, various control keys permit you to move the cursor between lines of data, and between objects:

Command Keys

Command
Key

Description

PgUp/PgDn

Moves forward-backward through data.

Ctrl-PgUp / PgDn

Moves to next class of object.

Ctrl-

Moves to next instance within the object class.

Ctrl-Home

Jumps to first memory address.

Ctrl-End

Jumps to last memory address.

R

Moves to beginning of RipTide Data.

>

Follows data pointer, pushing current location onto address stack.

<

Pops pointer from address stack, making it the current location.


Board Data Panel (F1)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Board Data" Panel (F1)

The start-up panel contains data about the controller board, including software and hardware configuration.

"Board Data" VM3 Panel.

  • Board Type-- XMP controller board installed. Two settings:

01-- Hammerhead1

02-- XMP standard (includes both PCI and CPCI).

  • FPGA Prom Version-- FGPA (Field Programmable Gate Array) Version type on controller board.

XXX--

Undetermined-- VM3 cannot determine version of FPGA PROM

  • Board Revision-- Revision designator for XMP board. Two options:

01-- Old version.

02-- New version.

  • Signature-- Only one signature is used: C0FFEE. This confirms that firmware has been successfully loaded onto the board. Any other signature--or a missing signature--indicates that the board lacks firmware and/or is malfunctioning.
  • Maximum Axes-- Maximum number of axes configurable on the XMP controller. This is hardware-dependent, and ranges between 1 and 24 axes. Standard XMP boards can accommodate up to 8 axes; additional axes may be added via an expansion board.
  • Enabled Motors-- Number of Motors currently configured for the XMP controller.
  • Enabled Filters-- Number of Filters currently configured for the XMP controller.
  • Enabled Axes-- Number of Axes currently configured for the XMP controller card. This number cannot exceed the Maximum Axes value.
  • Enabled Motion Supervisors-- Number of Motion Supervisors currently configured for the XMP controller.
  • Enabled Program Sequencers-- Number of Program Sequencers currently configured for the XMP controller.
  • Software ID-- Firmware number. This is usually a three-digit number (e.g., 266, etc.).
  • Revision-- Firmware revision number.
  • Sub-Revision-- Firmware minor revision number.
  • Developmental-- N/A.
  • Option-- Optional number for custom firmware identifier.
  • Timer-- Cumulative timer counts. To reset the motion controller and zero the timer, use the F9 key.
  • Sample Period-- Samples per second. Default is 20 kHz (19999). Each tick is 50 nanoseconds.
  • Command Buffer Address-- Location of command buffer.
  • Map File-- Map file utilized in current configuration (e.g., xmpNNN.map, where NNN is the firmware version number). NOTE: NNN must be the same as the firmware number.

1. The "Hammerhead" board (FPGA Prom Version 01) is a prototype controller card which preceded the standard XMP-series controller.


VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

VM3 Data Panels and Header Files

XMP data structures displayed on VM3 panels correspond to data structures in the xmp.h header file. Consider the following example:

In this example, data structures MEIXmpSystemData and MEIXmpData (bottom), located in the header file xmp.h, are represented in VM3 as shown (top).


Commands Panel (F2)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Commands" Panel (F2)

Pressing the F2 key displays external memory (i.e. memory located on XMP board componenets other than the SHARC DSP processor), organized by command number. The first address in this memory block is 0x00400000.

"Commands" VM3 Panel


Auto Panel (F3)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Auto" Panel (F3)

Pressing F3 displays memory data, arranged by object, with data values displayed in either hexadecimal, decimal, or float format. Objects with pointers have their data preceded by an asterisk (e.g., *0x0028026 on the sixth memory data line below). The choice of which data format to use is determined automatically, with data generally displayed in its most commonly used format.

"Auto" VM3 Panel


Hex Panel (F4)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Hex" Panel (F4)

Pressing F4 displays memory data, arranged by object, with data values displayed in hexadecimal format only.

"Hex" VM3 Panel


Decimal Panel (F5)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Decimal" Panel (F5)

Pressing F5 displays memory data, arranged by object, with data values displayed in decimal format only.

"Decimal" VM3 Panel


Float Panel (F6)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Float" Panel (F6)

Pressing F6 displays memory data, arranged by object, with data values displayed in floating decimal format.

"Float" VM3 Panel


Dump/Save Panel (F8)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Dump/Save" Panel (F8)

Pressing F8 dumps memory data to the file, "Xmpdump.bin" in the local directory. This file can be loaded later into VM3 for further inspection.

"Dump" VM3 Panel


Reset Panel (F9)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Reset" Panel (F9)

Pressing F8 resets the motion controller (reloads from flash)


Toggle Panel (F10)

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

"Toggle" Panel (F10)

Pressing F10 toggles the display of the screen between a 32-bit format and a 16-bit format. In VM3, since most of the XMP data is 32-bit, the default setting shows all of the data in a 32-bit format (long, hex, or float). However, for viewing 16-bit data like the Riptide, DAC, and Dedicated Input/Output, it is easier to understand the data when viewing the data in a 16-bit format. Pressing F10 allows the viewing mode to switch between a 32-bit and 16-bit format.

"Toggle" VM3 Panel


Command Line Options

CONTENTS:
Introduction
Installing and Running VM3
VM3 Layout
“Board Data” Panel (F1)
VM3 Data Panels and Header Files
“Commands” Panel (F2)
“Auto” Panel (F3)
“Hex” Panel (F4)
“Decimal” Panel (F5)
“Float” Panel (F6)
“Dump/Save” Panel (F8)
“Reset” Panel (F9)
“Toggle” Panel (F10)
Command Line Options
CHAPTER 4
VM3

Command Line Options

VM3 supports eight command line options: -control #, -delay, -map, -load, -save.

-control, -server, -port

These options allow the control of various controllers on different servers, ports and/or traces.

The -control option allows the usage of any controller that is properly mapped. The default control number is zero.

The -server option allows the usage of controllers located on different host and remote servers.

The -port option allows the usage of controllers using different port settings.

For instance:

        • To use VM3 with controller 1 on the host machine, type: vm3 -control 1
        • To use VM3 with controller 2 on a remote host named "Orion" using TCP/IP port number 5000, type: vm3 -control 2 -server Orion -port 5000

-delay
The -delay option determines how often the VM3 screen is refreshed. The default value is 10 milliseconds. Setting the delay to a smaller value will cause the screen to be updated more frequently. Setting the delay to 0 will update the screen as fast as possible, but will cause noticeable delay in other applications. Since most video monitors do not refresh more often than every 10 milliseconds, there is usually no advantage gained by lowering the delay. For example, the command:

vm3 -delay msec (8)

will cause the screen to refresh every 8 milliseconds.

-map
The -map option allows the loading of an alternative map file. For example, the command:

vm3 -map myfile.map

will cause VM3 to use the file "myfile.map" instead of using the default map file. The default map file is XmpNNN.map where NNN is the firmware version number.

-load
The -load option causes VM3 to browse the firmware memory images from a file. Only the MEIXmpData{} and MEIXmpBufferData{} structures are loaded. This feature works in conjunction with the -save option. For example, the command:

vm3 -load Xmpdump.bin

will load the previously saved “Xmpdump.bin” file for viewing.

-save
The -save option specifies the name to be used for saving memory images when F8 is pressed. The -save option does not need to be specified to save memory images when F8 is pressed. The default is “Xmpdump.bin.” For example, the command:

vm3 -save dump1.bin

will save the memory images to the “dump1.bin” file. Memory images will continue to be saved to this file when F8 is pressed for the remainder of the session.


Introduction to XMP Configuration Utility

CONTENTS:
Introduction
Command-Line Syntax 5
Examples
Firmware/Library Upgrades
Modifying Configuration
Open Issues
CHAPTER 5
XMP Configuration Utility

Introduction

The XMP Configuration Utility provides a means of configuring the XMP using text files. The text files contain symbolic configuration data for MPI objects in a format that is independent of firmware version. You can get configuration data for MPI objects from XMP RAM or flash memory and save it to a text file. Similarly, you can load configuration data for MPI objects from a text file and set either XMP RAM or flash memory. Command line arguments to the config utility make it possible to selectively configure MPI objects.

The config utility makes it easy to upgrade to a new release of XMP firmware while retaining custom firmware configuration. It is also easy to configure the XMP without writing any code.


Command-Line Syntax

CONTENTS:
Introduction
Command-Line Syntax 5
Examples
Firmware/Library Upgrades
Modifying Configuration
Open Issues
CHAPTER 5
XMP Configuration Utility

Command-Line Syntax

The config utility is located in the XMP\bin\WinNT directory of your MPI/XMP installation path. The command-line syntax is as follows:

config [-ram|-flash] [-map map-file] get output-file [object[#] ...]

config [-ram|-flash] [-map map-file] set input-file [object[#] ...]

Options:

-ram | use XMP's volatile memory (default)
-flash | use XMP's non-volatile (flash) memory
-map | use map-file in place of the default input map file
map-file | filename of input map file

NOTICE

The default input map file is named xmp###.map where ### is the firmware version number for which the config utility was built. It is installed into the XMP\bin\WinNT directory of your MPI/XMP installation path.

The input map file will be searched for in the directory from which the config utility was executed, the current directory, the Windows system directory (system32), the Windows directory and the directories in the PATH environment variable.

get | get configuration from XMP RAM or flash and save to output-file
set | load configuration from input-file and set XMP RAM or flash
output-file | path/filename for output configuration file
input-file | path/filename for input configuration file
object | MPI object(s) to get/set.

Case-sensitive values for object are:

  • adc[#]
  • axis[#]
  • capture[#]
  • control
  • dac[#]
  • eventmgr
  • filter[#]
  • motion[#]
  • motor[#]
  • node[#]
  • recorder
  • sequence[#]
  • sercos[#]

The absence of a number (i.e. #) immediately following an object on the command line indicates that all objects of that type are selected. Otherwise, only the object specified by the number is selected. Objects must be separated by a space. If no objects are specified, all objects are selected.


Examples
Firmware/Library Upgrades
Modifying Configuration
Open Issues
CHAPTER 5
XMP Configuration Utility

Examples

The examples below use a configuration file with a suffix of ".cfg". The use of this suffix is recommended, but it is not required.

To get RAM configuration of all MPI objects and save to a file:

config get all.cfg

To get flash configuration of all MPI objects and save to a file:

config -flash get all.cfg

To load configuration of all MPI objects from a file and set flash (non-volatile) memory:

config -flash set all.cfg

To get RAM configuration for all axes and save to a file:

config get axes.cfg axis

To get RAM configuration for axis 3 and filter 5 and save to a file:

config get a3f5.cfg axis3 filter5

To load configuration of axis objects from a file and set flash (non-volatile) memory:

config -flash set all.cfg axis

To load configuration of axis objects from a file and set RAM:

config set a3f5.cfg axis

Note that the a3f5.cfg file contains configuration data only for axis3 and filter5, so the only axis that will actually be configured is axis 3. Similarly, while the following defaults to all MPI objects, only axis3 and filter 5 will be configured:

config set a3f5.cfg

To get RAM configuration of the control object and save to a file:

config get control.cfg control

To set RAM configuration to an axis count of 8:

Create file axis.cfg with the following line:

MPIControl Config.axisCount 8

config set axis.cfg control

-OR-

config set axis.cfg


Firmware/Library Upgrades
Modifying Configuration
Open Issues
CHAPTER 5
XMP Configuration Utility

Firmware/Library Upgrades

Configuration files are usable with different firmware and library revisions, i.e. older configuration files will generally work with newer versions of the firmware and library. The exception is when a field from an older configuration file is no longer supported. In such a case, one of the following messages will be displayed:

`field`: name not found

This message indicates that the `field` member of an MPI Config{} structure is either no longer supported or in error.

`field`: `value`: name not found

This message indicates that the `field` member of an MPI Config{} structure is a pointer and the symbolic XMP address `value` is either no longer supported or in error.

In either case the field will be ignored.

If a new field has been added, there is no way for an older configuration file to handle it. Newly added fields will remain at their current value.

To upgrade to a new version of the MPI library and/or XMP firmware while retaining custom configuration, do the following:

  • config -flash get all.cfg
  • install new library and firmware
  • config -flash set all.cfg


Modifying Configuration
Open Issues
CHAPTER 5
XMP Configuration Utility

Modifying Configuration

It is possible to create a configuration file or to modify an existing one. For example, to modify gain configuration for filters 0 through 2, create a file called filter.cfg with the following lines:

MEIFilterConfig[0].GainSwitchType 0

MEIFilterConfig[0].GainDelay 0.000000

MEIFilterConfig[0].GainWindow 500

MEIFilterConfig[1].GainSwitchType 0

MEIFilterConfig[2].GainDelay 0.000000

MEIFilterConfig[1].GainWindow 500

MEIFilterConfig[2].GainSwitchType 0

MEIFilterConfig[2].GainDelay 0.000000

MEIFilterConfig[3].GainWindow 500

Changing the numeric value on the right hand side will change the configuration value on the XMP, only after you execute a config set command, such as any of the flowing:

config set filter.cfg

config set filter.cfg filter

config set filter.cfg filter0 filter1 filter2

You must not change the data type when you change a value. Values for type long may be specified in decimal, octal (leading 0) or hexadecimal (leading 0x). Values for type float or double must contain a decimal point. Values for type pointer must be a symbolic XMP address.


Open Issues
CHAPTER 5
XMP Configuration Utility

Open Issues

There is no backward compatibility with earlier configuration files. This is the only open issue at this time.

Return to Utilities' Main Menu


Microsoft HTML Help Compiler 4.74.8702

Compiling \\LEO\WEBSITE\MEI_TECH_SUPPORT\tech_support.chm

HHC5003: Error: Compilation failed while compiling \\LEO\WEBSITE\MEI_TECH_SUPPORT\_errorlog.txt.
HHC3004: Warning: opr1.htm : The HTML tag "=. </td" is not a valid HTML tag (it does not begin with an alphanumeric character).
HHC3004: Warning: opr1.htm : The HTML tag ".</td" is not a valid HTML tag (it does not begin with an alphanumeric character).

The following files were not compiled:
\\LEO\WEBSITE\MEI_TECH_SUPPORT\_errorlog.txt


MEI:

You Are Using Netscape. This site has been designed to operate most effectively with Internet Explorer vr.3.0 and Greater. You may choose to Download the most recent version of IE or close this window.


This files were modified in order to create the support_motioneng.chi and support_motioneng.chm files.

These files are not ideal for the CD version anymore because the PDF/Notes page was taken out (HTML Help does not support the use of *.pdf).

-Dean


MotionEng-Tech. Support

adc1.c
adc2.c
adcFBak.c
ampFlt1.c
anticol1.c
capture1.c
coffee.c
comp.c
compare.c
encfltcfg.c
encoder.c
event1.c
event3.c
frame1.c
home1.c
initFlsh.c
limitSw1.c
mboard1.c
mboard2.c
motGate1.c
motGate2.c
motid1.c
motid2.c
motid3.c
motion1.c
motion2.c
motion3.c
motmap1.c
motmap2.c
motmod1.c
motorio1.c
notify1.c
path1.c
path3d1.c
PT1.c
PTAppend.c
PVT1.c
quickStart1.c
record1.c
record2.c
record3.c
record4.c
scclose.c
scdither.c
schall.c
scopen.c
scstep.c
scview.c
seq1.c
seq2.c
seq3.c
seq4.c
seqKill.c
seqrec.c
settle1.c
settle2.c
shape.c
sidn1.c
sidn2.c
stepcfg.c
stepcfg2.c
stoprate.c
template.c
usrlim1.c
usrlim2.c
usrlim3.c


Sample Application: Select by Function

Function
(Click on a function description below to view its source code)
If you are unsure of the specific name of your program, try finding it by function. Select the function description that most closely matches the action you are attempting. This selection will lead you to a brief description of the function and some sample code to get you started.

Copyright © 2002
Motion Engineering


Table of Contents for Sample Applications

Sample Applications

--Table of Contents--

Filename | Topic | pg
adc1.c | Read the analog to digital converter | 4
adc2.c | Determine scale and offset calibration for analog to digital convert input | 10
adcFBak.c | Set up an axis to use analog (ADC) position feedback | 17
ampFlt1.c | Configure the amp fault input | 21
anticol1.c | Program sequencer aborts axes prior to a collission | 27
capture1.c | Perform a velocity move and capture position based on home or index pulse | 34
coffee.c | Read XMP firmware signature | 42
comp.c | Configure axis compensation tables | 45
compare1.c | Compare an encoder counter and set an XCVR output when the condition is TRUE | 52
encfltcfg.c | Configure encoder fault settings for a motor | 57
encoder.c | Continuous display of motor actual position | 61
event1.c | Perform a repeated 2-axis motion while polling an event manager | 67
event3.c | Perform a repeated single-axis motion using command-line-specified axis | 74
frame1.c | Simple multi-axis frame generated motion profile | 82
home1.c | Simple homing routine that captures the hardware position, set the origin | 89
initFlsh.c | Controller initialization and automatic firmware download | 98
limitSw1.c | Configure positive and negative hardware limit inputs | 106
mboard1.c | Setup multiple controllers, clear positions, and perform a 2-point motion | 110
mboard2.c | 2-point motion on multiple controllers with an event manager in polling mode. | 116
motGate1.c | Load and trigger a point-to-point motion using a control gate | 124
motGate2.c | Load and trigger motion profiles using a control gate | 130
motid1.c | Point-to-point motion with motion done event identification | 139
motid2.c | Point-to-point motion with motion/axis event identification | 147
motid3.c | Point-to-point motion with ID, APPEND, and HOLD attributes | 155
motion1.c | Perform point-to-point trapezoidal profile motion | 165
motion2.c | 2-axis motion, with synchronized and coordinated S-Curve motion with velocity specified using position | 169
motion3.c | Custom point-to-point S-Curve motion with velocity specified using position | 176
motmap1.c | Motion object and Motion Supervisor axis map configuration | 182
motmap2.c | Motion object and Motion Supervisor Axis mapping with events | 192
motmod1.c | Point-to-Point trapezoidal profile motion with end point modification | 202
motorio1.c | Configure transceiver as input or output and toggle | 206
notify1.c | Create notify object and wait for events | 210
path1.c | 2-axis path motion, around a rectangle with rounded corners | 217
path3d1.c | 3-axis path motion with velocities, acceleration and timeSlices | 226
PT1.c | Simple motion path generation, specified by position/time points | 237
PTAppend.c | Simple motion path generation, using position/time/point with Motion Append | 244
PVT1.c | Simple motion path generation, specified by position/velocity/time points | 252
quickStart1.c | Simple point-to-point motion program for Quick Start procedure. | 260
record1.c | Read/display data recorder records from specified axis (default 0) | 267
record2.c | Record data and demonstrate how to start/stop/restart recorder | 271
record3.c | Interrupt-driven display of data recorder records from specified axis (default 0) | 277
record4.c | Perform a diagonal 2-axis motion and record command velocity and status | 283
scclose.c | Transition control from open-loop to closed-loop mode. | 291
scdither.c | Sinusoidal commutation initialization using the dithering mode | 295
schall.c | Single-axis sinusoidal commutation sample program with hall initialization | 305
scopen.c | Transition commutation from close-loop to open-loop mode | 322
scstep.c | Single axis sinusoidal commutation sample configuration program | 325
scview.c | Display commutation parameters | 333
seq1.c | Perform a repeated multi-axis motion command sequence | 337
seq2.c | Perform a repeated multi-axis motion command sequence, wait for an I/O bit | 344
seq3.c | Wait for an I/O bit to toggle before commanding motion with a sequencer | 351
seq4.c | Perform a repeated multi-axis motion sequence, wait for I/O, & monitor location | 359
seqKill.c | Program sequence to monitor an I/O bit and abort all axes when active | 374
seqrec.c | Track status of specified motion supervisors and enable data recorder on any motion | 382
settle1.c | Configure in-position tolerance and settling time for an axis | 388
settle2.c | Configure settling criteria and exception event settling conditions | 391
shape.c | Configure trajectory shaping filters | 402
sidn1.c | SERCOS node idn get/display | 409
sidn2.c | SERCOS node idn get/display/set | 418
sinit1.c | SERCOS ring initialization | 429
stepcfg.c | Configure a motor as a stepper motor | 441
stepcfg2.c | Configure an 8 axis XMP to support 8 Servos and 8 Steppers | 448
stoprate.c | Set deceleration rate for MPIActionSTOP and MPIActionE_STOP | 456
template.c | Template application (one-line description for sample app) | 460
usrlim1.c | User limit watch input bit and set an output bit | 463
usrlim2.c | Position comparison using User Limits to generate events | 474
usrlim3.c | Position comparison using User Limits to generate events and outputs | 486


Table of Contents for Hardware

Chapter 1 | XMP Hardware Overview
 | XMP Hardware
 | Controller Configurations
 | Expansions and Add-ons
 | Host Computer Electrical Requirements
 | XMP Controller Installation

Chapter 2 | XMP Bus Interface
 | Introduction
 | PCI Bus
 | CPCI-6U Bus
 | CPCI-3U Bus
 | PMC Bus

Chapter 3 | Configuring an XMP-analog Motion Control System
 | Introduction
 | Connect to Analog Servo Amplifiers
 | Drive Enable Wiring
 | Connect To Digital Quadrature Encoders
 | Connect System I/O
 | Analog Inputs
 | Connect XMP Transceiver I/O as a Capture Input
 | Connect Two XMP Boards (12-16Axes)
 | Configuring Analog Connections

Chapter 4 | XMP-analog I/O
 | Introduction
 | XMP-PCI
 | CPCI-6U
 | CPCI-6U Expansion Board, Backplane Connectors
 | CPCI-3U
 | XMP-SERCOS-PMC
 | Transceiver (XCVR) and User I/O Details

Chapter 5 | XMP Controller Motion Drive I/O: SERCOS
 | Introduction
 | SERCOS Connection Hardware
 | XMP-SERCOS Connector Ports
 | Assistance with SERCOS Networks

Chapter 6 | XMP Controller Motion Drive I/O
 | Architectural Overview
 | Host Bus
 | Encoder Inputs
 | Digital-to-Analog Converter (DAC) Subsystem
 | Analog Inputs
 | SHARC DSP Processor Subsystem
 | Memory Organization
 | Faults and Resets
 | XMP Data Architecture


Use the following search to find any topic relating to the XMP Motion Controller Hardware Installation Manual.

To receive a result, type in part of a word, a single word, or a collection of words. To broaden or narrow the search, use the "find all words," "find any word," or "exact match" functions.


<?php
$SRC_DIR = $DOCUMENT_ROOT . "/sub/mei/c_src/";
$OUT_DIR = $DOCUMENT_ROOT . "/sub/mei/c_out/";
?>


PDFs and Notes

Unfortunately, HTML Help does not support the viewing of pdf documents within its viewable window. When you click on a link to a *.pdf document, you will be asked to save the file to your hard drive and open the file from that location.

Therefore, MEI recommends accessing the PDFs/Notes page from the support.motioneng.com website.

Please go to http://support.motioneng.com/pdf_notes/main_frame.html.


{APPNAME} - {CLASS_PACKAGE} - Class: {CLASS_NAME}

File: {CLASS_FILE}
{APPNAME} - {CLASS_PACKAGE}

{CLASS_NAME}

{CLASS_TREE}

{CLASS_SHORTDESCRIPTION}{CLASS_UNDOC}

{CLASS_ACCESS} {CLASS_ABSTRACT} {CLASS_STATIC} {CLASS_FINAL} class {CLASS_NAME} {CLASS_EXTENDS}

{CLASS_SHORTDESCRIPTION}
{CLASS_DESCRIPTION}

See Also | {SEE}
Links | {LINK}
Authors | {AUTHOR}
Since | {SINCE}
Version | {VERSION}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Direct known subclasses: {ELEMENTS}

Methods inherited from {SOURCE}
{ELEMENTS}

{ACCESS} Method Summary
{RETURNTYPE}

{NAME}({PARAMETER})

{SHORTDESCRIPTION}{UNDOC}

Fields inherited from {SOURCE}
{ELEMENTS}

{ACCESS} Field Summary
{TYPE}

{NAME}

{SHORTDESCRIPTION}{UNDOC}

Constants inherited from {SOURCE}
{ELEMENTS}

{ACCESS} Constant Summary
{NAME} >>{VALUE}<< {SHORTDESCRIPTION}{UNDOC}

Included files inherited from {SOURCE}
{ELEMENTS}

Included files Summary, Type: {TYPE}
{FILE} {SHORTDESCRIPTION}{UNDOC}

{ACCESS} Method Details

{NAME}
{ACCESS} {ABSTRACT} {STATIC} {FINAL} {RETURNTYPE} {NAME}( {PARAMETER} )
{SHORTDESCRIPTION}
{DESCRIPTION}

{UNDOC}

Parameter
{TYPE} | {NAME} | {DEFAULT}
 | {DESCRIPTION}{UNDOC}
Returns {TYPE} {NAME}

{DESCRIPTION}

Throws | {EXCEPTIONS}
Required global variables
{TYPE} {NAME} {DESCRIPTION}
Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}

{ACCESS} Field Details

{NAME}
{ACCESS} {STATIC} {FINAL} {TYPE} {NAME}

>>{VALUE}<<

{SHORTDESCRIPTION}
{DESCRIPTION}

Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}

{ACCESS} Constant Details

{NAME}

 define( {NAME}, >>{VALUE}<< )
Case: {CASE}

{SHORTDESCRIPTION}
{DESCRIPTION}

Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}

Included Files, Type: {TYPE}

{FILE}
{TYPE}( {FILE} )

{SHORTDESCRIPTION}
{DESCRIPTION}

Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Classtrees

Classtrees

{BASECLASS}

{TREE}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Elementlist

{CHAPTER}

{CHAPTER}
{ELEMENTNAME} {ELEMENT}
{SHORTDESCRIPTION}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Frameset Packageelements

Packagelist

{PACKAGE_NAME}
Classes
{EMPTY}
{ELEMENT}
Modules
{EMPTY}
{ELEMENT}


Extensions
----------
MySQL, ODBC, FTP, Calendar, BCMath, COM, PCRE, Session, WDDX and XML support is *built-in*.
You don't need to load any additional extensions in order to use these functions.

Folders
-------
- mibs
The mibs directory contains support files for SNMP.
This directory should be moved to DRIVE:\usr\mibs (DRIVE being the drive where PHP is installed.)

- dlls
Some DLLs that are required for PHP and some extensions. Please copy them to your to your windows/system (Win9.x)
or winnt/system32 (WinNT, Win2000) directory.
If you already have these DLLs installed on your system, overwrite them only if something is not working correctly.
Before overwriting them, it is a good idea to back them or move them to another folder - just in case something goes wrong.

Installtion instructions
------------------------

Apache:
1. Stop the Apache Webserver.
Edit the httpd.conf and put in these lines, modified to your environment:

# for the apache module
LoadModule php4_module c:/php/sapi/php4apache.dll
AddType application/x-httpd-php .php4

#for the cgi binary (you can use that one compiled with force cgi redirect too)
ScriptAlias /php4/ "C:/php/"
Action application/x-httpd-php4 "/php4/php.exe"
AddType application/x-httpd-php4 .php

2. Unzip the Package to c:\php, now move php4ts.dll to the windows/system(32) directory, overwritte any older file!

3. Copy the php.ini-dist to your sysroot (directory where you installed windows), rename it to php.ini, and
edit the php.ini to fit your needs.

4. Restart the Apache server.

Oreilly Wesite Pro:
1. First make sure that you got atleast Version 2.5
2. Edit the Server Properties and select the tab "Mapping"
3. From the List select "Associations" and enter the desired extension (".php") and the path to the cgi exe or the isapi dll
4. Now select "Content Types" add the same extension ".php" and enter the contenttype:
cgi wwwserver/shellcgi
isapi wwwserver/isapi

5. Copy the php.ini-dist to your Systemroot (Directory where you installed windows), rename it to php.ini, and
edit it to fit your needs.
6. Edit the php.ini to fit your needs.

Xitami:
1. Copy the php.ini-dist to your Systemroot (Directory where you installed windows), rename it to php.ini, and
edit it to fit your needs.
2. Make sure the webserver is running, and point your browser to xitamis admin console (usually http://127.0.0.1/admin), and click on Configuration
3. Now navigate to the Filters, and put the extension which php should parse (i.e. .php) into the field File extensions (.xxx)
4. In Filter command or script put the path and name of your php executable i.e. c:\php\php.exe
5. Press the 'Save' icon

IIS 4.0+ (isapi):
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), rename it to php.ini, and
edit it to fit your needs
2. Start the Microsoft Management Console or the Internet Services Manager, located in your Control Panel
3. Click on your webserver, and select properties
4. If you don't want to perform HTTP Authentication using PHP, you can (and should) skip this step. Under ISAPI Filters,
add a new ISAPI filter. Use PHP as the filter name, and supply a path to the php4isapi.dll
5. Under Home Directory, click on the Configuration button. Add a new entry to the Application Mappings. Use the path the
php4isapi.dll as the Executable, supply .php as the extension, leave Method exclusions, blank, and check the Script engine
checkbox
6. Stop IIS completely
7. Start IIS again

IIS 4.0+ (CGI)
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), rename it to php.ini, and
edit it to fit your needs
2. Start the Microsoft Management Console (may appear as 'Internet Services Manager', either in your Windows NT 4.0
Option Pack branch or the Control Panel->Administrative Tools under Windows 2000).
3. Right click on your Web server node (will most probably appear as 'Default Web Server'), and select 'Properties'.
4. Under 'Home Directory', click on the 'Configuration' button. Add a new
5. entry to the Application Mappings; Use the path to php.exe as the Executable, supply .php as the extension, leave
'Method exclusions', blank, and check the Script engine checkbox.
6. Put a .php file under your Web server's document root and check if it works!

PWS 4.0+ (isapi):
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), rename it to php.ini, and
edit it to fit your needs
2. Edit the enclosed PWS-php4isapi.reg (ISAPI interface) or PWS-php4cgi.reg (CGI interface) file to reflect the location of
your php4isapi.dll / php.exe. Forward slashes should be escaped, for example:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="C:\\Program Files\\PHP\\php4isapi.dll"
3. In the PWS Manager, right click on a given directory you want to add PHP support to, and select Properties. Check the 'Execute' checkbox, and confirm.

PWS 4.0+ (CGI):
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), rename it to php.ini, and
edit it to fit your needs
2. Edit the enclosed PWS-php4.reg file to reflect the location of your php.exe. Forward slashes should be escaped,
for example:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="C:\\Program Files\\PHP\\php.exe"
3. In the PWS Manager, right click on a given directory you want to add PHP
support to, and select Properties. Check the 'Execute' checkbox, and
confirm.
4. At this point, PWS should have built-in PHP support.

NETSCAPE SERVERS, PHP as CGI (for Netscape Enterprise Server, iPlanet, perhaps Fastrack..)
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), and edit it to fit your needs
2. Copy php4ts.dll to your systemroot (the directory where you installed windows)
3. Make a file assocition from the command line (type the 2 following lines)
      assoc .php=PHPScript
      ftype PHPScript=d:\php4\php.exe %1 %*
4. In the Netscape Enterprise Administration Server create a dummy shellcgi directory and remove it just after
      (this step creates 5 important lines in obj.conf and allow the web server to handle shellcgi scripts)
5. In the Netscape Enterprise Administration Server create a new mime type
      (Category:type,Content-Type:magnus-internal/shellcgi,File Suffix:php)
6. Do it for each web server instance you want php to run
7. More details http://benoit.noss.free.fr/php/install-php.html

NETSCAPE SERVERS, PHP as NSAPI (for Netscape Enterprise Server, iPlanet, perhaps Fastrack..)
1. Copy the php.ini-dist to your systemroot (the directory where you installed windows), and edit it to fit your needs
2. Copy php4ts.dll to your systemroot (the directory where you installed windows)
3. Make a file assocition from the command line (type the 2 following lines)
      assoc .php=PHPScript
      ftype PHPScript=d:\php4\php.exe %1 %*
4. In the Netscape Enterprise Administration Server create a new mime type
      (Category:type,Content-Type:magnus-internal/x-httpd-php,File Suffix:php)
5. Stop your web service and edit obj.conf
6.1 At the end of the Init section, place this 2 lines (necessarely after mime type init!)
      Init fn="load-modules" funcs="php4_init,php4_close,php4_execute,php4_auth_trans" shlib="d:/php4/sapi/php4nsapi.dll"
      Init fn="php4_init" errorString="Failed to initialise PHP!"
6.2 In The < Object name="default" > section, place this line necessarely after all 'ObjectType' and before all 'AddLog' lines!
      Service fn="php4_execute" type="magnus-internal/x-httpd-php"
6.3 At the end of the file, create a new object called x-httpd-php, by inserting this lines
      <Object name="x-httpd-php">
      ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
      Service fn=php4_execute
      </Object>
7. Restart your web service and apply changes
8. Do it for each web server instance you want php to run
9. More details http://benoit.noss.free.fr/php/install-php4.html


{APPNAME} - {MODULE_PACKAGE} - Module: {MODULE_NAME}

File: {MODULE_FILE}
{APPNAME} - {MODULE_PACKAGE}

{MODULE_GROUP}::{MODULE_NAME}

{MODULE_SHORTDESCRIPTION}{MODULE_UNDOC}

{MODULE_ACCESS} module {MODULE_NAME}

{MODULE_SHORTDESCRIPTION}
{MODULE_DESCRIPTION}

See Also | {SEE}
Links | {LINK}
Authors | {AUTHOR}
Since | {SINCE}
Version | {VERSION}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Direct known subclasses: {ELEMENTS}

{ACCESS} Method Summary
{RETURNTYPE}

{NAME}({PARAMETER})

{SHORTDESCRIPTION}{UNDOC}

{ACCESS} Constant Summary
{NAME} >>{VALUE}<< {SHORTDESCRIPTION}{UNDOC}

Included files Summary, Type: {TYPE}
{FILE} {SHORTDESCRIPTION}{UNDOC}

{ACCESS} Method Details

{NAME}
{ACCESS} {ABSTRACT} {STATIC} {FINAL} {RETURNTYPE} {NAME}( {PARAMETER} )
{SHORTDESCRIPTION}
{DESCRIPTION}

{UNDOC}

Parameter
{TYPE} | {NAME} | {DEFAULT}
 | {DESCRIPTION}{UNDOC}
Returns {TYPE} {NAME}

{DESCRIPTION}

Throws | {EXCEPTIONS}
Required global variables
{TYPE} {NAME} {DESCRIPTION}
Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}

{ACCESS} Constant Details

{NAME}

 define( {NAME}, >>{VALUE}<< )
Case: {CASE}

{SHORTDESCRIPTION}
{DESCRIPTION}

Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}

Included Files, Type: {TYPE}

{FILE}
{TYPE}( {FILE} )

{SHORTDESCRIPTION}
{DESCRIPTION}

Version | {VERSION}
Since | {SINCE}
Deprecated | {DEPRECATED}
Copyright | {COPYRIGHT}
Magic | {MAGIC}
Brother | {BROTHER}
See Also | {SEE}
Links | {LINK}
Author(s) | {AUTHOR}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Modulegroups

Modulegroups

{MODULEGROUP}

{MODULES}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Packagelist

{APPNAME}

Packagelist

{PACKAGE_NAME}
Classes
{EMPTY}
{ELEMENT}
Modules
{EMPTY}
{ELEMENT}
Overview Packageindex Classtree Help
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Report

Warnings

{FILE}

{NUMWARNINGS} Warning(s).
[{ELEMENTTYPE}] {ELEMENT} {WARNINGTYPE}
{WARNING}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


{APPNAME} - Modulegroups

XML Files
  • {FILE}
Packageindex Classtrees Modulegroups Elementlist Report XML Files
PHPDoc 1.0beta


DISMAN-SCRIPT-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
    Integer32, Unsigned32, mib-2
        FROM SNMPv2-SMI

    RowStatus, TimeInterval, DateAndTime, StorageType, DisplayString
        FROM SNMPv2-TC

    MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP
        FROM SNMPv2-CONF

    SnmpAdminString
        FROM SNMP-FRAMEWORK-MIB;

scriptMIB MODULE-IDENTITY
    LAST-UPDATED "9902221800Z"
    ORGANIZATION "IETF Distributed Management Working Group"
    CONTACT-INFO
        "David B. Levi
         Nortel Networks
         4401 Great America Parkway
         Santa Clara, CA 95052-8185
         U.S.A.
         Tel: +1 423 686 0432
         E-mail: dlevi@nortelnetworks.com

         Juergen Schoenwaelder
         TU Braunschweig
         Bueltenweg 74/75
         38106 Braunschweig
         Germany
         Tel: +49 531 391-3283
         E-mail: schoenw@ibr.cs.tu-bs.de"
    DESCRIPTION
        "This MIB module defines a set of objects that allow to
         delegate management scripts to distributed managers."
    ::= { mib-2 64 }

--
-- The groups defined within this MIB module:
--

smObjects       OBJECT IDENTIFIER ::= { scriptMIB 1 }
smNotifications OBJECT IDENTIFIER ::= { scriptMIB 2 }
smConformance   OBJECT IDENTIFIER ::= { scriptMIB 3 }

--
-- Script language and language extensions.
--
-- This group defines tables which list the languages and the
-- language extensions supported by a script MIB implementation.
-- Languages are uniquely identified by object identifier values.
--

smLangTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmLangEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table lists supported script languages."
    ::= { smObjects 1 }

smLangEntry OBJECT-TYPE
    SYNTAX      SmLangEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular language."
    INDEX { smLangIndex }
    ::= { smLangTable 1 }

SmLangEntry ::= SEQUENCE {
    smLangIndex         Integer32,
    smLangLanguage      OBJECT IDENTIFIER,
    smLangVersion       SnmpAdminString,
    smLangVendor        OBJECT IDENTIFIER,
    smLangRevision      SnmpAdminString,
    smLangDescr         SnmpAdminString
}

smLangIndex OBJECT-TYPE
    SYNTAX      Integer32 (1..2147483647)
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The locally arbitrary, but unique identifier associated
         with this language entry.

         The value is expected to remain constant at least from one
         re-initialization of the entity's network management system
         to the next re-initialization.

         Note, the data type and the range of this object must be
         consistent with the definition of smScriptLanguage."
    ::= { smLangEntry 1 }

smLangLanguage OBJECT-TYPE
    SYNTAX      OBJECT IDENTIFIER
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The globally unique identification of the language."
    ::= { smLangEntry 2 }

smLangVersion OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The version number of the language. The zero-length string
         shall be used if the language does not have a version
         number.
         It is suggested that the version number consist of one or
         more decimal numbers separated by dots, where the first
         number is called the major version number."
    ::= { smLangEntry 3 }

smLangVendor OBJECT-TYPE
    SYNTAX      OBJECT IDENTIFIER
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "An object identifer which identifies the vendor who
         provides the implementation of the language. This object
         identifer SHALL point to the object identifier directly
         below the enterprise object identifier {1 3 6 1 4 1}
         allocated for the vendor. The value must be the object
         identifier {0 0} if the vendor is not known."
    ::= { smLangEntry 4 }

smLangRevision OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The version number of the language implementation.
         The value of this object must be an empty string if
         version number of the implementation is unknown.

         It is suggested that the value consist of one or more
         decimal numbers separated by dots, where the first
         number is called the major version number."
    ::= { smLangEntry 5 }

smLangDescr OBJECT-TYPE
    SYNTAX      SnmpAdminString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "A textual description of the language."
    ::= { smLangEntry 6 }

smExtsnTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmExtsnEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table lists supported language extensions."
    ::= { smObjects 2 }

smExtsnEntry OBJECT-TYPE
    SYNTAX      SmExtsnEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular language extension."
    INDEX { smLangIndex, smExtsnIndex }
    ::= { smExtsnTable 1 }

SmExtsnEntry ::= SEQUENCE {
    smExtsnIndex        Integer32,
    smExtsnExtension    OBJECT IDENTIFIER,
    smExtsnVersion      SnmpAdminString,
    smExtsnVendor       OBJECT IDENTIFIER,
    smExtsnRevision     SnmpAdminString,
    smExtsnDescr        SnmpAdminString
}

smExtsnIndex OBJECT-TYPE
    SYNTAX      Integer32 (1..2147483647)
    MAX-ACCESS  not-accessible
    STATUS      current

    DESCRIPTION
        "The locally arbitrary, but unique identifier associated
         with this language extension entry.

         The value is expected to remain constant at least from one
         re-initialization of the entity's network management system
         to the next re-initialization."
    ::= { smExtsnEntry 1}

smExtsnExtension OBJECT-TYPE
    SYNTAX      OBJECT IDENTIFIER
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The globally unique identification of the language
         extension."
    ::= { smExtsnEntry 2 }

smExtsnVersion OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The version number of the language extension.
         It is suggested that the version number consist of one or
         more decimal numbers separated by dots, where the first
         number is called the major version number."
    ::= { smExtsnEntry 3 }

smExtsnVendor OBJECT-TYPE
    SYNTAX      OBJECT IDENTIFIER
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "An object identifer which identifies the vendor who
         provides the implementation of the extension. The
         object identifer value should point to the OID node
         directly below the enterprise OID {1 3 6 1 4 1}
         allocated for the vendor. The value must by the object
         identifier {0 0} if the vendor is not known."
    ::= { smExtsnEntry 4 }

smExtsnRevision OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The version number of the extension implementation.
         The value of this object must be an empty string if
         version number of the implementation is unknown.

         It is suggested that the value consist of one or more
         decimal numbers separated by dots, where the first
         number is called the major version number."
    ::= { smExtsnEntry 5 }

smExtsnDescr OBJECT-TYPE
    SYNTAX      SnmpAdminString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "A textual description of the language extension."
    ::= { smExtsnEntry 6 }

--
-- Scripts known by the Script MIB implementation.
--
-- This group defines a table which lists all known scripts.
-- Scripts can be added and removed through manipulation of the
-- smScriptTable.
--
smScriptObjects OBJECT IDENTIFIER ::= { smObjects 3 }

smScriptTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmScriptEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table lists and describes locally known scripts."
    ::= { smScriptObjects 1 }

smScriptEntry OBJECT-TYPE
    SYNTAX      SmScriptEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular script. Every script that
         is stored in non-volatile memory is required to appear in
         this script table."
    INDEX { smScriptOwner, smScriptName }
    ::= { smScriptTable 1 }
SmScriptEntry ::= SEQUENCE {
    smScriptOwner       SnmpAdminString,
    smScriptName        SnmpAdminString,
    smScriptDescr       SnmpAdminString,
    smScriptLanguage    Integer32,
    smScriptSource      DisplayString,
    smScriptAdminStatus INTEGER,
    smScriptOperStatus  INTEGER,
    smScriptStorageType StorageType,
    smScriptRowStatus   RowStatus
}

smScriptOwner OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The manager who owns this row in the smScriptTable."
    ::= { smScriptEntry 1 }

smScriptName OBJECT-TYPE
    SYNTAX      SnmpAdminString
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The locally-unique, administratively assigned name for this
         script. This object allows an smScriptOwner to have multiple
         entries in the smScriptTable.
         This value of this object may be used to derive the name
         (e.g. a file name) which is used by the Script MIB
         implementation to access the script in non-volatile
         storage. The details of this mapping are implementation
         specific. However, the mapping needs to ensure that scripts
         created by different owners with the same script name do not
         map to the same name in non-volatile storage."
    ::= { smScriptEntry 2 }

smScriptDescr OBJECT-TYPE
    SYNTAX      SnmpAdminString
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "A description of the purpose of the script."
    ::= { smScriptEntry 3 }

smScriptLanguage OBJECT-TYPE
    SYNTAX      Integer32 (0..2147483647)
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The value of this object type identifies an entry in the
         smLangTable which is used to execute this script.
         The special value 0 may be used by hard-wired scripts
         that can not be modified and that are executed by
         internal functions.

         Note, the data type and the range of this object must be
         consistent with the definition of smLangIndex."
    ::= { smScriptEntry 4 }

smScriptSource OBJECT-TYPE
    SYNTAX      DisplayString
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object either contains a reference to the script
         source or an empty string. A reference must be given
         in the form of a Uniform Resource Locator (URL) as
         defined in RFC 2396. The allowed character sets and the
         encoding rules defined in RFC 2396 section 2 apply.

         When the smScriptAdminStatus object is set to `enabled',
         the Script MIB implementation will `pull' the script
         source from the URL contained in this object if the URL
         is not empty.
         An empty URL indicates that the script source is loaded
         from local storage. The script is read from the smCodeTable
         if the value of smScriptStorageType is volatile. Otherwise,
         the script is read from non-volatile storage.

         Note: This document does not mandate implementation of any
         specific URL scheme. A attempt to load a script from a
         nonsupported URL scheme will cause the smScriptOperStatus
         to report an `unknownProtocol' error.

         Set requests to change this object are invalid if the
         value of smScriptOperStatus is `enabled', `editing',
         `retrieving' or `compiling' and will result in an
         inconsistentValue error."
    DEFVAL { ''H }
    ::= { smScriptEntry 5 }
smScriptAdminStatus OBJECT-TYPE
    SYNTAX      INTEGER {
                    enabled(1),
                    disabled(2),
                    editing(3)
                }
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the desired status of
         the script. See the definition of smScriptOperStatus for
         a description of the values.

         When the smScriptAdminStatus object is set to `enabled' and
         the smScriptOperStatus is `disabled' or one of the error
         states, the Script MIB implementation will `pull' the script
         source from the URL contained in the smScriptSource object
         if the URL is not empty."
    DEFVAL { disabled }
    ::= { smScriptEntry 6 }

smScriptOperStatus OBJECT-TYPE
    SYNTAX      INTEGER {
                    enabled(1),
                    disabled(2),
                    editing(3),
                    retrieving(4),
                    compiling(5),
                    noSuchScript(6),
                    accessDenied(7),
                    wrongLanguage(8),
                    wrongVersion(9),
                    compilationFailed(10),
                    noResourcesLeft(11),
                    unknownProtocol(12),
                    protocolFailure(13),
                    genericError(14)
                }
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The actual status of the script in the runtime system. The
         value of this object is only meaningful when the value of the
         smScriptRowStatus object is `active'.

         The smScriptOperStatus object may have the following values:
         - `enabled' indicates that the script is available and can
            be started by a launch table entry.

         - `disabled' indicates that the script can not be used.

         - `editing' indicates that the script can be modified in the
           smCodeTable.

         - `retrieving' indicates that the script is currently being
           loaded from non-volatile storage or a remote system.

         - `compiling' indicates that the script is currently being
           compiled by the runtime system.

         - `noSuchScript' indicates that the script does not exist
           at the smScriptSource.

         - `accessDenied' indicates that the script can not be loaded
           from the smScriptSource due to a lack of permissions.

         - `wrongLanguage' indicates that the script can not be loaded
           from the smScriptSource because of a language mismatch.

         - `wrongVersion' indicates that the script can not be loaded
           from the smScriptSource because of a language version
           mismatch.

         - `compilationFailed' indicates that the compilation failed.

         - `noResourcesLeft' indicates that the runtime system does
           not have enough resources to load the script.

         - `unknownProtocol' indicates that the script could not be
           loaded from the smScriptSource because the requested
           protocol is not supported.

         - `protocolFailure' indicates that the script could not be
           loaded from the smScriptSource because of a protocol
           failure.

         - `genericError' indicates that the script could not be
           loaded due to an error condition not listed above.

         The `retrieving' and `compiling' states are transient states
         which will either lead to one of the error states or the
         `enabled' state. The `disabled' and `editing' states are
         administrative states which are only reached by explicit
         management operations.

         All launch table entries that refer to this script table
         entry shall have an smLaunchOperStatus value of `disabled'
         when the value of this object is not `enabled'."
    DEFVAL { disabled }
    ::= { smScriptEntry 7 }

smScriptStorageType OBJECT-TYPE
    SYNTAX      StorageType
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object defines whether this row and the script
         controlled by this row are kept in volatile storage and
         lost upon reboot or if this row is backed up by
         non-volatile or permanent storage.

         The script controlled by this row is written into local
         non-volatile storage if the following condition becomes
         true:

         (a) the URL contained in the smScriptSource object is empty
             and
         (b) the smScriptStorageType is `nonVolatile'
             and
         (c) the smScriptOperStatus is `enabled'

         Setting this object to `volatile' removes a script from
         non-volatile storage if the script controlled by this row
         has been in non-volatile storage before. Attempts to set
         this object to permanent will always fail with an
         inconsistentValue error.

         The value of smScriptStorageType is only meaningful if the
         value of the corresponding RowStatus object is `active'.

         If smScriptStorageType has the value permanent(4), then all
         objects whose MAX-ACCESS value is read-create must be
         writable, with the exception of the smScriptStorageType and
         smScriptRowStatus objects, which shall be read-only."
    DEFVAL { volatile }
    ::= { smScriptEntry 8 }

smScriptRowStatus OBJECT-TYPE
    SYNTAX      RowStatus
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "A control that allows entries to be added and removed from
         this table.

         Changing the smScriptRowStatus from `active' to `notInService'
         will remove the associated script from the runtime system.
         The value of smScriptOperStatus will be reset to `disabled'.

         Deleting conceptual rows from this table includes the
         deletion of all resources associated with this row. This
         implies that a script stored in non-volatile storage is
         removed from non-volatile storage.

         An entry may not exist in the `active' state unless all
         required objects in the entry have appropriate values. Rows
         that are not complete or not in service are not known by the
         script runtime system.

         Attempts to `destroy' a row or to set a row `notInService'
         while the script is executing will result in an
         inconsistentValue error.

         Attempts to `destroy' a row or to set a row `notInService'
         where the value of the smScriptStorageType object is
         `permanent' or `readOnly' will result in an
         inconsistentValue error."
    ::= { smScriptEntry 9 }

--
-- Access to script code via SNMP
--
-- The smCodeTable allows script code to be read and modified
-- via SNMP.
--

smCodeTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmCodeEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table contains the script code for scripts that are
         written via SNMP write operations."
    ::= { smScriptObjects 2 }

smCodeEntry OBJECT-TYPE
    SYNTAX      SmCodeEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular fragment of a script."
    INDEX { smScriptOwner, smScriptName, smCodeIndex }
    ::= { smCodeTable 1 }

SmCodeEntry ::= SEQUENCE {
    smCodeIndex         Unsigned32,
    smCodeText          OCTET STRING,
    smCodeRowStatus     RowStatus
}

smCodeIndex OBJECT-TYPE
    SYNTAX      Unsigned32 (1..4294967295)
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The index value identifying this code fragment."
    ::= { smCodeEntry 1 }

smCodeText OBJECT-TYPE
    SYNTAX      OCTET STRING (SIZE (1..1024))
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The code that makes up a fragment of a script. The format
         of this code fragment depends on the script language which
         is identified by the associated smScriptLanguage object."
    ::= { smCodeEntry 2 }

smCodeRowStatus OBJECT-TYPE
    SYNTAX      RowStatus
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "A control that allows entries to be added and removed from
         this table."
    ::= { smCodeEntry 3 }

--
-- Script execution.
--
-- This group defines tables which allow script execution to be
-- initiated, suspended, resumed, and terminated.  It also provides
-- a mechanism for keeping a history of recent script executions
-- and their results.
--

smRunObjects OBJECT IDENTIFIER ::= { smObjects 4 }

smLaunchTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmLaunchEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table lists and describes scripts that are ready
         to be executed together with their parameters."
    ::= { smRunObjects 1 }

smLaunchEntry OBJECT-TYPE
    SYNTAX      SmLaunchEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular executable script."
    INDEX { smLaunchOwner, smLaunchName }
    ::= { smLaunchTable 1 }

SmLaunchEntry ::= SEQUENCE {
    smLaunchOwner               SnmpAdminString,
    smLaunchName                SnmpAdminString,
    smLaunchScriptOwner         SnmpAdminString,
    smLaunchScriptName          SnmpAdminString,
    smLaunchArgument            OCTET STRING,
    smLaunchMaxRunning          Unsigned32,
    smLaunchMaxCompleted        Unsigned32,
    smLaunchLifeTime            TimeInterval,
    smLaunchExpireTime          TimeInterval,
    smLaunchStart               Integer32,
    smLaunchControl             INTEGER,
    smLaunchAdminStatus         INTEGER,
    smLaunchOperStatus          INTEGER,
    smLaunchRunIndexNext        Integer32,
    smLaunchStorageType         StorageType,
    smLaunchRowStatus           RowStatus
}

smLaunchOwner OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION

        "The manager who owns this row in the smLaunchTable. Every
         instance of a running script started from a particular entry
         in the smLaunchTable (i.e. entries in the smRunTable) will be
         owned by the same smLaunchOwner used to index the entry in
         the smLaunchTable. This owner is not necessarily the same as
         the owner of the script itself (smLaunchScriptOwner)."
    ::= { smLaunchEntry 1 }

smLaunchName OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (1..32))
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The locally-unique, administratively assigned name for this
         launch table entry. This object allows an smLaunchOwner to
         have multiple entries in the smLaunchTable. The smLaunchName
         is an arbitrary name that must be different from any other
         smLaunchTable entries with the same smLaunchOwner but can be
         the same as other entries in the smLaunchTable with different
         smLaunchOwner values. Note that the value of smLaunchName
         is not related in any way to the name of the script being
         launched."
    ::= { smLaunchEntry 2 }

smLaunchScriptOwner OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The value of this object in combination with the value of
         smLaunchScriptName identifies the script that can be
         launched from this smLaunchTable entry. Attempts to write
         this object will fail with an inconsistentValue error if
         the value of smLaunchOperStatus is `enabled'."
    ::= { smLaunchEntry 3 }

smLaunchScriptName OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE (0..32))
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The value of this object in combination with the value of
         the smLaunchScriptOwner identifies the script that can be
         launched from this smLaunchTable entry. Attempts to write
         this objects will fail with an inconsistentValue error if
         the value of smLaunchOperStatus is `enabled'."
    ::= { smLaunchEntry 4 }

smLaunchArgument OBJECT-TYPE
    SYNTAX      OCTET STRING
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The argument supplied to the script. When a script is
         invoked, the value of this object is used to initialize
         the smRunArgument object."
    DEFVAL { ''H }
    ::= { smLaunchEntry 5 }

smLaunchMaxRunning OBJECT-TYPE
    SYNTAX      Unsigned32 (1..4294967295)
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The maximum number of concurrently running scripts that may
         be invoked from this entry in the smLaunchTable. Lowering the
         current value of this object does not affect any scripts that
         are already executing."
    DEFVAL { 1 }
    ::= { smLaunchEntry 6 }

smLaunchMaxCompleted OBJECT-TYPE
    SYNTAX      Unsigned32 (1..4294967295)
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The maximum number of finished scripts invoked from this
         entry in the smLaunchTable allowed to be retained in the
         smRunTable. Whenever the value of this object is changed
         and whenever a script terminates, entries in the smRunTable
         are deleted if necessary until the number of completed
         scripts is smaller than the value of this object. Scripts
         whose smRunEndTime value indicates the oldest completion
         time are deleted first."
    DEFVAL { 1 }
    ::= { smLaunchEntry 7 }

smLaunchLifeTime OBJECT-TYPE
    SYNTAX      TimeInterval
    UNITS       "centi-seconds"
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The default maximum amount of time a script launched
         from this entry may run. The value of this object is used
         to initialize the smRunLifeTime object when a script is
         launched. Changing the value of an smLaunchLifeTime
         instance does not affect scripts previously launched from
         this entry."
    DEFVAL { 360000 }
    ::= { smLaunchEntry 8 }

smLaunchExpireTime OBJECT-TYPE
    SYNTAX      TimeInterval
    UNITS       "centi-seconds"
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The default maximum amount of time information about a
         script launched from this entry is kept in the smRunTable
         after the script has completed execution.  The value of
         this object is used to initialize the smRunExpireTime
         object when a script is launched. Changing the value of an
         smLaunchExpireTime instance does not affect scripts
         previously launched from this entry."
    DEFVAL { 360000 }
    ::= { smLaunchEntry 9 }

smLaunchStart OBJECT-TYPE
    SYNTAX      Integer32 (0..2147483647)
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object is used to start the execution of scripts.
         When retrieved, the value will be the value of smRunIndex
         for the last script that started execution by manipulating
         this object. The value will be zero if no script started
         execution yet.

         A script is started by setting this object to an unused
         smRunIndex value. A new row in the smRunTable will be
         created which is indexed by the value supplied by the
         set-request in addition to the value of smLaunchOwner and
         smLaunchName. An unused value can be obtained by reading
         the smLaunchRunIndexNext object.
         Setting this object to the special value 0 will start
         the script with a self-generated smRunIndex value. The
         consequence is that the script invoker has no reliable
         way to determine the smRunIndex value for this script
         invocation and that the invoker has therefore no way
         to obtain the results from this script invocation. The
         special value 0 is however useful for scheduled script
         invocations.

         If this object is set, the following checks must be
         performed:

         1) The value of the smLaunchOperStatus object in this
            entry of the smLaunchTable must be `enabled'.
         2) The values of smLaunchScriptOwner and
            smLaunchScriptName of this row must identify an
            existing entry in the smScriptTable.
         3) The value of smScriptOperStatus of this entry must
            be `enabled'.
         4) The principal performing the set operation must have
            read access to the script. This must be checked by
            calling the isAccessAllowed abstract service interface
            defined in RFC 2271 on the row in the smScriptTable
            identified by smLaunchScriptOwner and smLaunchScriptName.
            The isAccessAllowed abstract service interface must be
            called on all columnar objects in the smScriptTable with
            a MAX-ACCESS value different than `not-accessible'. The
            test fails as soon as a call indicates that access is
            not allowed.
         5) If the value provided by the set operation is not 0,
            a check must be made that the value is currently not
            in use. Otherwise, if the value provided by the set
            operation is 0, a suitable unused value must be
            generated.
         6) The number of currently executing scripts invoked
            from this smLaunchTable entry must be less than
            smLaunchMaxRunning.

         Attempts to start a script will fail with an
         inconsistentValue error if one of the checks described
         above fails.

         Otherwise, if all checks have been passed, a new entry
         in the smRunTable will be created indexed by smLaunchOwner,
         smLaunchName and the new value for smRunIndex. The value
         of smLaunchArgument will be copied into smRunArgument,
         the value of smLaunchLifeTime will be copied to
         smRunLifeTime, and the value of smLaunchExpireTime
         will be copied to smRunExpireTime.

         The smRunStartTime will be set to the current time and
         the smRunState will be set to `initializing' before the
         script execution is initiated in the appropriate runtime
         system.

         Note, the data type and the range of this object must
         be consistent with the smRunIndex object. Since this
         object might be written from the scheduling MIB, the
         data type Integer32 rather than Unsigned32 is used."
    DEFVAL { 0 }
    ::= { smLaunchEntry 10 }

smLaunchControl OBJECT-TYPE
    SYNTAX      INTEGER {
                    abort(1),
                    suspend(2),
                    resume(3),
                    nop(4)
                }
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object is used to request a state change for all
         running scripts in the smRunTable that were started from
         this row in the smLaunchTable.

         Setting this object to abort(1), suspend(2) or resume(3)
         will set the smRunControl object of all applicable rows
         in the smRunTable to abort(1), suspend(2) or resume(3)
         respectively. The phrase `applicable rows' means the set of
         rows which were created from this entry in the smLaunchTable
         and whose value of smRunState allows the corresponding
         state change as described in the definition of the
         smRunControl object. Setting this object to nop(4) has no
         effect."
    DEFVAL { nop }
    ::= { smLaunchEntry 11 }

smLaunchAdminStatus OBJECT-TYPE
    SYNTAX      INTEGER {
                    enabled(1),
                    disabled(2)
                }
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the desired status of
         this launch table entry."
    DEFVAL { disabled }
    ::= { smLaunchEntry 12 }

smLaunchOperStatus OBJECT-TYPE
    SYNTAX      INTEGER {
                    enabled(1),
                    disabled(2)
                }
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the actual status of
         this launch table entry. An `enabled' launch table
         entry can be used to start scripts while a `disabled'
         launch table entry will refuse any attempts to start
         scripts. The value `enabled' requires that the
         smLaunchRowStatus object is active. The value
         `disabled' requires that there are no entries in the
         smRunTable associated with this smLaunchTable entry."
    DEFVAL { disabled }
    ::= { smLaunchEntry 13 }

smLaunchRunIndexNext OBJECT-TYPE
    SYNTAX      Integer32 (1..2147483647)
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "This variable is used for creating rows in the smRunTable.
         The value of this variable is a currently unused value
         for smRunIndex, which can be written into the smLaunchStart
         object associated with this row to launch a script.

         The value returned when reading this variable must be unique
         for the smLaunchOwner and smLauchName associated with this
         row. Subsequent attempts to read this variable must return
         different values.

         This variable will return the special value 0 if no new rows
         can be created.

         Note, the data type and the range of this object must be
         consistent with the definition of smRunIndex."
    ::= { smLaunchEntry 14 }

smLaunchStorageType OBJECT-TYPE
    SYNTAX      StorageType
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object defines if this row is kept in volatile storage
         and lost upon reboot or if this row is backed up by stable
         storage.

         The value of smLaunchStorageType is only meaningful if the
         value of the corresponding RowStatus object is active.

         If smLaunchStorageType has the value permanent(4), then all
         objects whose MAX-ACCESS value is read-create must be
         writable, with the exception of the smLaunchStorageType and
         smLaunchRowStatus objects, which shall be read-only."
    DEFVAL { volatile }
    ::= { smLaunchEntry 15 }

smLaunchRowStatus OBJECT-TYPE
    SYNTAX      RowStatus
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "A control that allows entries to be added and removed from
         this table.

         Attempts to `destroy' a row or to set a row `notInService'
         while scripts started from this launch table entry are
         running will result in an inconsistentValue error.

         Attempts to `destroy' a row or to set a row `notInService'
         where the value of the smLaunchStorageType object is
         `permanent' or `readOnly' will result in an
         inconsistentValue error."
    ::= { smLaunchEntry 16 }

smRunTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF SmRunEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table lists and describes scripts that are currently
         running or have been running in the past."
    ::= { smRunObjects 2 }

smRunEntry OBJECT-TYPE
    SYNTAX      SmRunEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry describing a particular running or finished
         script."
    INDEX { smLaunchOwner, smLaunchName, smRunIndex }
    ::= { smRunTable 1 }

SmRunEntry ::= SEQUENCE {
    smRunIndex          Integer32,
    smRunArgument       OCTET STRING,
    smRunStartTime      DateAndTime,
    smRunEndTime        DateAndTime,
    smRunLifeTime       TimeInterval,
    smRunExpireTime     TimeInterval,
    smRunExitCode       INTEGER,
    smRunResult         OCTET STRING,
    smRunControl        INTEGER,
    smRunState          INTEGER,
    smRunError          SnmpAdminString
}

smRunIndex OBJECT-TYPE
    SYNTAX      Integer32 (1..2147483647)
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "The locally arbitrary, but unique identifier associated
         with this running or finished script. This value must be
         unique for all rows in the smRunTable with the same
         smLaunchOwner and smLaunchName.

         Note, the data type and the range of this object must be
         consistent with the definition of smLaunchRunIndexNext
         and smLaunchStart."
    ::= { smRunEntry 1 }

smRunArgument OBJECT-TYPE
    SYNTAX      OCTET STRING
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The argument supplied to the script when it started."
    DEFVAL { ''H }
    ::= { smRunEntry 2 }

smRunStartTime OBJECT-TYPE
    SYNTAX      DateAndTime
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The date and time when the execution started. The value
         '0000000000000000'H is returned if the script has not
         started yet."
    DEFVAL { '0000000000000000'H }
    ::= { smRunEntry 3 }

smRunEndTime OBJECT-TYPE
    SYNTAX      DateAndTime
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The date and time when the execution terminated. The value
         '0000000000000000'H is returned if the script has not
         terminated yet."
    DEFVAL { '0000000000000000'H }
    ::= { smRunEntry 4 }

smRunLifeTime OBJECT-TYPE
    SYNTAX      TimeInterval
    UNITS       "centi-seconds"
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "This object specifies how long the script can execute.
         This object returns the remaining time that the script
         may run. The object is initialized with the value of the
         associated smLaunchLifeTime object and ticks backwards.
         The script is aborted immediately when the value reaches 0.

         The value of this object may be set in order to increase or
         reduce the remaining time that the script may run. Setting
         this value to 0 will abort script execution immediately,
         and, if the value of smRunExpireTime is also 0, will remove
         this entry from the smRunTable once it has terminated.

         The value of smRunLifeTime reflects the real-time execution
         time as seen by the outside world. The value of this object
         will always be 0 for a script that finished execution, that
         is smRunState has the value `terminated'.

         The value of smRunLifeTime does not change while a script
         is suspended, that is smRunState has the value `suspended'.
         Note, this does not affect set operations. It is legal to
         modify smRunLifeTime via set operations while a script is
         suspended."
    ::= { smRunEntry 5 }

smRunExpireTime OBJECT-TYPE
    SYNTAX      TimeInterval
    UNITS       "centi-seconds"
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "This value specifies how long this row can exist in the
         smRunTable after the script has terminated.  This object
         returns the remaining time that the row may exist before it
         is aged out. The object is initialized with the value of the
         associated smLaunchExpireTime object and ticks backwards. The
         entry in the smRunTable is destroyed when the value reaches 0
         and the smRunState has the value `terminated'.

         The value of this object may be set in order to increase or
         reduce the remaining time that the row may exist.  Setting
         the value to 0 will destroy this entry as soon as the
         smRunState has the value `terminated'."
    ::= { smRunEntry 6 }

smRunExitCode OBJECT-TYPE
    SYNTAX      INTEGER {
                    noError(1),
                    halted(2),
                    lifeTimeExceeded(3),
                    noResourcesLeft(4),
                    languageError(5),
                    runtimeError(6),
                    invalidArgument(7),
                    securityViolation(8),
                    genericError(9)
                }
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the reason why a
         script finished execution. The smRunExitCode code may have
         one of the following values:

         - `noError', which indicates that the script completed
            successfully without errors;

         - `halted', which indicates that the script was halted
            by a request from an authorized manager;

         - `lifeTimeExceeded', which indicates that the script
            exited because a time limit was exceeded;
         - `noResourcesLeft', which indicates that the script
            exited because it ran out of resources (e.g. memory);

         - `languageError', which indicates that the script exited
            because of a language error (e.g. a syntax error in an
            interpreted language);

         - `runtimeError', which indicates that the script exited
            due to a runtime error (e.g. a division by zero);

         - `invalidArgument', which indicates that the script could
            not be run because of invalid script arguments;

         - `securityViolation', which indicates that the script
            exited due to a security violation;

         - `genericError', which indicates that the script exited
            for an unspecified reason.

         If the script has not yet begun running, or is currently
         running, the value will be `noError'."
    DEFVAL { noError }
    ::= { smRunEntry 7 }

smRunResult OBJECT-TYPE
    SYNTAX      OCTET STRING
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The result value produced by the running script. Note that
         the result may change while the script is executing."
    DEFVAL { ''H }
    ::= { smRunEntry 8 }

smRunControl OBJECT-TYPE
    SYNTAX      INTEGER {
                    abort(1),
                    suspend(2),
                    resume(3),
                    nop(4)
                }
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the desired status of the
         script execution defined by this row.

         Setting this object to `abort' will abort execution if the
         value of smRunState is `initializing', `executing',
         `suspending', `suspended' or `resuming'. Setting this object
         to `abort' when the value of smRunState is `aborting' or
         `terminated' will result in an inconsistentValue error.

         Setting this object to `suspend' will suspend execution
         if the value of smRunState is `executing'. Setting this
         object to `suspend' will cause an inconsistentValue error
         if the value of smRunState is not `executing'.

         Setting this object to `resume' will resume execution
         if the value of smRunState is `suspending' or
         `suspended'. Setting this object to `resume' will cause an
         inconsistentValue error if the value of smRunState is
         not `suspending' or `suspended'.

         Setting this object to nop(4) has no effect."
    DEFVAL { nop }
    ::= { smRunEntry 9 }

smRunState OBJECT-TYPE
    SYNTAX      INTEGER {
                    initializing(1),
                    executing(2),
                    suspending(3),
                    suspended(4),
                    resuming(5),
                    aborting(6),
                    terminated(7)
                }
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of this object indicates the script's execution
         status.  If the script has been invoked but has not yet
         begun execution, the value will be `initializing'. If the
         script is running, the value will be `executing'. A script
         which received a request to suspend execution but which
         did not actually suspend execution will be `suspending'.
         A script which has suspended execution will be `suspended'.
         A script which received a request to resume execution but
         which is not yet running is `resuming'. The resuming state
         will finally lead to the `executing' state. A script which
         received a request to abort execution but which is still
         running is `aborting'. A script which stopped execution
         is `terminated'."
    ::= { smRunEntry 10 }

smRunError OBJECT-TYPE
    SYNTAX      SnmpAdminString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "This  contains a descriptive error message if the script
         terminates in an abnormally. An implementation must store a
         descriptive error message in this object if the script exits
         with the smRunExitCode `genericError'.

         The value of this object is the zero-length string as long
         as the smRunExitCode has the value `noError'"
    DEFVAL { ''H }
    ::= { smRunEntry 11 }

--
-- Notifications. The definition of smTraps makes notification
-- registrations reversible (see STD 58, RFC 2578).
--

smTraps OBJECT IDENTIFIER ::= { smNotifications 0 }

smScriptAbort NOTIFICATION-TYPE
    OBJECTS     { smRunExitCode, smRunEndTime, smRunError }
    STATUS      current
    DESCRIPTION
        "This notification is generated whenever a running script
         terminates with an smRunExitCode unequal to `noError'."
    ::= { smTraps 1 }

smScriptResult NOTIFICATION-TYPE
    OBJECTS     { smRunResult }
    STATUS      current
    DESCRIPTION
        "This notification can be used by scripts to notify other
         management applications about script results. It can be
         used to notify managers about a script result.

         This notification is not automatically generated by the
         script MIB implementation. It is the responsibility of
         the executing script to emit this notification where it
         is appropriate to do so."
    ::= { smTraps 2 }

-- conformance information
smCompliances OBJECT IDENTIFIER ::= { smConformance 1 }
smGroups      OBJECT IDENTIFIER ::= { smConformance 2 }

-- compliance statements

smCompliance MODULE-COMPLIANCE
    STATUS      current
    DESCRIPTION
        "The compliance statement for SNMP entities which implement
         the script MIB."
    MODULE      -- this module
    MANDATORY-GROUPS {
            smLanguageGroup, smScriptGroup, smLaunchGroup, smRunGroup
    }
    GROUP   smCodeGroup
    DESCRIPTION
        "The smCodeGroup is mandatory only for those implementations
         that support the downloading of scripts via SNMP."
    OBJECT  smScriptSource
    MIN-ACCESS  read-only
    DESCRIPTION
        "The smScriptSource object is read-only for implementations
         that are not able to download script code from a URL."
    OBJECT smLaunchArgument
    DESCRIPTION
        "A compliant implementation has to support a minimum size
         for smLaunchArgument of 255 octets."
    OBJECT smRunArgument
    DESCRIPTION
        "A compliant implementation has to support a minimum size
         for smRunArgument of 255 octets."
    OBJECT smRunResult
    DESCRIPTION
        "A compliant implementation has to support a minimum size
         for smRunResult of 255 octets."
    OBJECT smRunState
    DESCRIPTION
        "A compliant implementation does not have to support script
         suspension and the smRunState `suspended'. Such an
         implementation will change into the `suspending' state
         when the smRunControl is set to `suspend' and remain in this
         state until smRunControl is set to `resume' or the script
         terminates."
    ::= { smCompliances 1 }

smLanguageGroup OBJECT-GROUP
    OBJECTS {
        smLangLanguage,
        smLangVersion,
        smLangVendor,
        smLangRevision,
        smLangDescr,
        smExtsnExtension,
        smExtsnVersion,
        smExtsnVendor,
        smExtsnRevision,
        smExtsnDescr
    }
    STATUS      current
    DESCRIPTION
        "A collection of objects providing information about the
         capabilities of the scripting engine."
    ::= { smGroups 1 }

smScriptGroup OBJECT-GROUP
    OBJECTS {
        smScriptDescr,
        smScriptLanguage,
        smScriptSource,
        smScriptAdminStatus,
        smScriptOperStatus,
        smScriptStorageType,
        smScriptRowStatus
    }
    STATUS      current
    DESCRIPTION
        "A collection of objects providing information about
         installed scripts."
    ::= { smGroups 2 }

smCodeGroup OBJECT-GROUP
    OBJECTS {
        smCodeText,
        smCodeRowStatus
    }
    STATUS      current
    DESCRIPTION
        "A collection of objects used to download or modify scripts
         by using SNMP set requests."
    ::= { smGroups 3 }

smLaunchGroup OBJECT-GROUP
    OBJECTS {
        smLaunchScriptOwner,
        smLaunchScriptName,
        smLaunchArgument,
        smLaunchMaxRunning,
        smLaunchMaxCompleted,
        smLaunchLifeTime,
        smLaunchExpireTime,
        smLaunchStart,
        smLaunchControl,
        smLaunchAdminStatus,
        smLaunchOperStatus,
        smLaunchRunIndexNext,
        smLaunchStorageType,
        smLaunchRowStatus
    }
    STATUS      current
    DESCRIPTION
        "A collection of objects providing information about scripts
         that can be launched."
    ::= { smGroups 4 }

smRunGroup OBJECT-GROUP
    OBJECTS {
        smRunArgument,
        smRunStartTime,
        smRunEndTime,
        smRunLifeTime,
        smRunExpireTime,
        smRunExitCode,
        smRunResult,
        smRunState,
        smRunControl,
        smRunError
    }
    STATUS      current
    DESCRIPTION
        "A collection of objects providing information about running
         scripts."
    ::= { smGroups 5 }

smNotificationsGroup NOTIFICATION-GROUP
    NOTIFICATIONS {
        smScriptAbort,
        smScriptResult
    }
    STATUS      current
    DESCRIPTION
        "The notifications emitted by the script MIB."
    ::= { smGroups 6 }

END


EtherLike-MIB DEFINITIONS ::= BEGIN

    IMPORTS
        MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY,
        Counter32, mib-2, transmission
            FROM SNMPv2-SMI
        MODULE-COMPLIANCE, OBJECT-GROUP
            FROM SNMPv2-CONF
        ifIndex, InterfaceIndex
            FROM IF-MIB;

    etherMIB MODULE-IDENTITY
        LAST-UPDATED "9908240400Z"  -- August 24, 1999
        ORGANIZATION "IETF Ethernet Interfaces and Hub MIB
                     Working Group"
        CONTACT-INFO
            "WG E-mail: hubmib@hprnd.rose.hp.com
          To subscribe: hubmib-request@hprnd.rose.hp.com

                 Chair: Dan Romascanu
                Postal: Lucent Technologies
                        Atidum Technology Park, Bldg. 3
                        Tel Aviv 61131
                        Israel
                   Tel: +972 3 645 8414
                E-mail: dromasca@lucent.com

               Editor: John Flick
               Postal: Hewlett-Packard Company
                       8000 Foothills Blvd. M/S 5557
                       Roseville, CA 95747-5557
                       USA
                  Tel: +1 916 785 4018
                  Fax: +1 916 785 1199
               E-mail: johnf@rose.hp.com

               Editor: Jeffrey Johnson
               Postal: RedBack Networks
                       2570 North First Street, Suite 410
                       San Jose, CA, 95131
                       USA
                  Tel: +1 408 571 2699
                  Fax: +1 408 571 2698
               E-Mail: jeff@redbacknetworks.com"

        DESCRIPTION "The MIB module to describe generic objects for

                    Ethernet-like network interfaces.

                    The following reference is used throughout this
                    MIB module:

                    [IEEE 802.3 Std] refers to:
                       IEEE Std 802.3, 1998 Edition: 'Information
                       technology - Telecommunications and
                       information exchange between systems -
                       Local and metropolitan area networks -
                       Specific requirements - Part 3: Carrier
                       sense multiple access with collision
                       detection (CSMA/CD) access method and
                       physical layer specifications',
                       September 1998.

                    Of particular interest is Clause 30, '10Mb/s,
                    100Mb/s and 1000Mb/s Management'."

        REVISION    "9908240400Z"  -- August 24, 1999
        DESCRIPTION "Updated to include support for 1000 Mb/sec
                     interfaces and full-duplex interfaces.
                     This version published as RFC 2665."

        REVISION    "9806032150Z"
        DESCRIPTION "Updated to include support for 100 Mb/sec
                     interfaces.
                     This version published as RFC 2358."

        REVISION    "9402030400Z"
        DESCRIPTION "Initial version, published as RFC 1650."

        ::= { mib-2 35 }

    etherMIBObjects OBJECT IDENTIFIER ::= { etherMIB 1 }

    dot3    OBJECT IDENTIFIER ::= { transmission 7 }

    -- the Ethernet-like Statistics group

    dot3StatsTable OBJECT-TYPE
        SYNTAX     SEQUENCE OF Dot3StatsEntry
        MAX-ACCESS not-accessible
        STATUS     current
        DESCRIPTION "Statistics for a collection of ethernet-like
                    interfaces attached to a particular system.
                    There will be one row in this table for each

                    ethernet-like interface in the system."
        ::= { dot3 2 }

    dot3StatsEntry OBJECT-TYPE
        SYNTAX     Dot3StatsEntry
        MAX-ACCESS not-accessible
        STATUS     current
        DESCRIPTION "Statistics for a particular interface to an
                    ethernet-like medium."
        INDEX       { dot3StatsIndex }
        ::= { dot3StatsTable 1 }

    Dot3StatsEntry ::=
        SEQUENCE {
            dot3StatsIndex                      InterfaceIndex,
            dot3StatsAlignmentErrors            Counter32,
            dot3StatsFCSErrors                  Counter32,
            dot3StatsSingleCollisionFrames      Counter32,
            dot3StatsMultipleCollisionFrames    Counter32,
            dot3StatsSQETestErrors              Counter32,
            dot3StatsDeferredTransmissions      Counter32,
            dot3StatsLateCollisions             Counter32,
            dot3StatsExcessiveCollisions        Counter32,
            dot3StatsInternalMacTransmitErrors  Counter32,
            dot3StatsCarrierSenseErrors         Counter32,
            dot3StatsFrameTooLongs              Counter32,
            dot3StatsInternalMacReceiveErrors   Counter32,
            dot3StatsEtherChipSet               OBJECT IDENTIFIER,
            dot3StatsSymbolErrors               Counter32,
            dot3StatsDuplexStatus               INTEGER
        }

    dot3StatsIndex OBJECT-TYPE
        SYNTAX      InterfaceIndex
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "An index value that uniquely identifies an
                    interface to an ethernet-like medium.  The
                    interface identified by a particular value of
                    this index is the same interface as identified
                    by the same value of ifIndex."
        REFERENCE   "RFC 2233, ifIndex"
        ::= { dot3StatsEntry 1 }

    dot3StatsAlignmentErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current

        DESCRIPTION "A count of frames received on a particular
                    interface that are not an integral number of
                    octets in length and do not pass the FCS check.

                    The count represented by an instance of this
                    object is incremented when the alignmentError
                    status is returned by the MAC service to the
                    LLC (or other MAC user). Received frames for
                    which multiple error conditions obtain are,
                    according to the conventions of IEEE 802.3
                    Layer Management, counted exclusively according
                    to the error status presented to the LLC.

                    This counter does not increment for 8-bit wide
                    group encoding schemes.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.7,
                    aAlignmentErrors"
        ::= { dot3StatsEntry 2 }

    dot3StatsFCSErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames received on a particular
                    interface that are an integral number of octets
                    in length but do not pass the FCS check.  This
                    count does not include frames received with
                    frame-too-long or frame-too-short error.

                    The count represented by an instance of this
                    object is incremented when the frameCheckError
                    status is returned by the MAC service to the
                    LLC (or other MAC user). Received frames for
                    which multiple error conditions obtain are,
                    according to the conventions of IEEE 802.3
                    Layer Management, counted exclusively according
                    to the error status presented to the LLC.

                    Note:  Coding errors detected by the physical
                    layer for speeds above 10 Mb/s will cause the
                    frame to fail the FCS check.
                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management

                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.6,
                    aFrameCheckSequenceErrors."
        ::= { dot3StatsEntry 3 }

    dot3StatsSingleCollisionFrames OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of successfully transmitted frames on
                    a particular interface for which transmission
                    is inhibited by exactly one collision.

                    A frame that is counted by an instance of this
                    object is also counted by the corresponding
                    instance of either the ifOutUcastPkts,
                    ifOutMulticastPkts, or ifOutBroadcastPkts,
                    and is not counted by the corresponding
                    instance of the dot3StatsMultipleCollisionFrames
                    object.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.3,
                    aSingleCollisionFrames."
        ::= { dot3StatsEntry 4 }

    dot3StatsMultipleCollisionFrames OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of successfully transmitted frames on
                    a particular interface for which transmission
                    is inhibited by more than one collision.

                    A frame that is counted by an instance of this
                    object is also counted by the corresponding
                    instance of either the ifOutUcastPkts,
                    ifOutMulticastPkts, or ifOutBroadcastPkts,
                    and is not counted by the corresponding
                    instance of the dot3StatsSingleCollisionFrames
                    object.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.4,
                    aMultipleCollisionFrames."
        ::= { dot3StatsEntry 5 }

    dot3StatsSQETestErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of times that the SQE TEST ERROR
                    message is generated by the PLS sublayer for a
                    particular interface. The SQE TEST ERROR
                    is set in accordance with the rules for
                    verification of the SQE detection mechanism in
                    the PLS Carrier Sense Function as described in
                    IEEE Std. 802.3, 1998 Edition, section 7.2.4.6.

                    This counter does not increment on interfaces
                    operating at speeds greater than 10 Mb/s, or on
                    interfaces operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 7.2.4.6, also 30.3.2.1.4,
                    aSQETestErrors."
        ::= { dot3StatsEntry 6 }

    dot3StatsDeferredTransmissions OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames for which the first
                    transmission attempt on a particular interface
                    is delayed because the medium is busy.
                    The count represented by an instance of this
                    object does not include frames involved in
                    collisions.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.9,
                    aFramesWithDeferredXmissions."
        ::= { dot3StatsEntry 7 }

    dot3StatsLateCollisions OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "The number of times that a collision is
                    detected on a particular interface later than
                    one slotTime into the transmission of a packet.

                    A (late) collision included in a count
                    represented by an instance of this object is
                    also considered as a (generic) collision for
                    purposes of other collision-related
                    statistics.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.10,
                    aLateCollisions."
        ::= { dot3StatsEntry 8 }

    dot3StatsExcessiveCollisions OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames for which transmission on a
                    particular interface fails due to excessive
                    collisions.
                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.11,

                    aFramesAbortedDueToXSColls."
        ::= { dot3StatsEntry 9 }

    dot3StatsInternalMacTransmitErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames for which transmission on a
                    particular interface fails due to an internal
                    MAC sublayer transmit error. A frame is only
                    counted by an instance of this object if it is
                    not counted by the corresponding instance of
                    either the dot3StatsLateCollisions object, the
                    dot3StatsExcessiveCollisions object, or the
                    dot3StatsCarrierSenseErrors object.

                    The precise meaning of the count represented by
                    an instance of this object is implementation-
                    specific.  In particular, an instance of this
                    object may represent a count of transmission
                    errors on a particular interface that are not
                    otherwise counted.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.12,
                    aFramesLostDueToIntMACXmitError."
        ::= { dot3StatsEntry 10 }

    dot3StatsCarrierSenseErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "The number of times that the carrier sense
                    condition was lost or never asserted when
                    attempting to transmit a frame on a particular
                    interface.

                    The count represented by an instance of this
                    object is incremented at most once per
                    transmission attempt, even if the carrier sense
                    condition fluctuates during a transmission
                    attempt.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.13,
                    aCarrierSenseErrors."
        ::= { dot3StatsEntry 11 }

    -- { dot3StatsEntry 12 } is not assigned

    dot3StatsFrameTooLongs OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames received on a particular
                    interface that exceed the maximum permitted
                    frame size.

                    The count represented by an instance of this
                    object is incremented when the frameTooLong
                    status is returned by the MAC service to the
                    LLC (or other MAC user). Received frames for
                    which multiple error conditions obtain are,
                    according to the conventions of IEEE 802.3
                    Layer Management, counted exclusively according
                    to the error status presented to the LLC.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.25,
                    aFrameTooLongErrors."
        ::= { dot3StatsEntry 13 }

    -- { dot3StatsEntry 14 } is not assigned

    -- { dot3StatsEntry 15 } is not assigned

    dot3StatsInternalMacReceiveErrors OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of frames for which reception on a
                    particular interface fails due to an internal
                    MAC sublayer receive error. A frame is only
                    counted by an instance of this object if it is
                    not counted by the corresponding instance of

                    either the dot3StatsFrameTooLongs object, the
                    dot3StatsAlignmentErrors object, or the
                    dot3StatsFCSErrors object.

                    The precise meaning of the count represented by
                    an instance of this object is implementation-
                    specific.  In particular, an instance of this
                    object may represent a count of receive errors
                    on a particular interface that are not
                    otherwise counted.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.15,
                    aFramesLostDueToIntMACRcvError."
        ::= { dot3StatsEntry 16 }

    dot3StatsEtherChipSet OBJECT-TYPE
        SYNTAX      OBJECT IDENTIFIER
        MAX-ACCESS  read-only
        STATUS      deprecated
        DESCRIPTION "******** THIS OBJECT IS DEPRECATED ********

                    This object contains an OBJECT IDENTIFIER
                    which identifies the chipset used to
                    realize the interface. Ethernet-like
                    interfaces are typically built out of
                    several different chips. The MIB implementor
                    is presented with a decision of which chip
                    to identify via this object. The implementor
                    should identify the chip which is usually
                    called the Medium Access Control chip.
                    If no such chip is easily identifiable,
                    the implementor should identify the chip
                    which actually gathers the transmit
                    and receive statistics and error
                    indications. This would allow a
                    manager station to correlate the
                    statistics and the chip generating
                    them, giving it the ability to take
                    into account any known anomalies
                    in the chip."
        ::= { dot3StatsEntry 17 }

    dot3StatsSymbolErrors OBJECT-TYPE
        SYNTAX      Counter32

        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "For an interface operating at 100 Mb/s, the
                    number of times there was an invalid data symbol
                    when a valid carrier was present.

                    For an interface operating in half-duplex mode
                    at 1000 Mb/s, the number of times the receiving
                    media is non-idle (a carrier event) for a period
                    of time equal to or greater than slotTime, and
                    during which there was at least one occurrence
                    of an event that causes the PHY to indicate
                    'Data reception error' or 'carrier extend error'
                    on the GMII.

                    For an interface operating in full-duplex mode
                    at 1000 Mb/s, the number of times the receiving
                    media is non-idle a carrier event) for a period
                    of time equal to or greater than minFrameSize,
                    and during which there was at least one
                    occurrence of an event that causes the PHY to
                    indicate 'Data reception error' on the GMII.

                    The count represented by an instance of this
                    object is incremented at most once per carrier
                    event, even if multiple symbol errors occur
                    during the carrier event.  This count does
                    not increment if a collision is present.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.2.1.5,
                    aSymbolErrorDuringCarrier."
        ::= { dot3StatsEntry 18 }

    dot3StatsDuplexStatus OBJECT-TYPE
        SYNTAX      INTEGER {
                        unknown(1),
                        halfDuplex(2),
                        fullDuplex(3)
                    }
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "The current mode of operation of the MAC
                    entity.  'unknown' indicates that the current
                    duplex mode could not be determined.

                    Management control of the duplex mode is
                    accomplished through the MAU MIB.  When
                    an interface does not support autonegotiation,
                    or when autonegotiation is not enabled, the
                    duplex mode is controlled using
                    ifMauDefaultType.  When autonegotiation is
                    supported and enabled, duplex mode is controlled
                    using ifMauAutoNegAdvertisedBits.  In either
                    case, the currently operating duplex mode is
                    reflected both in this object and in ifMauType.

                    Note that this object provides redundant
                    information with ifMauType.  Normally, redundant
                    objects are discouraged.  However, in this
                    instance, it allows a management application to
                    determine the duplex status of an interface
                    without having to know every possible value of
                    ifMauType.  This was felt to be sufficiently
                    valuable to justify the redundancy."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.32,
                    aDuplexStatus."
        ::= { dot3StatsEntry 19 }

    -- the Ethernet-like Collision Statistics group

    -- Implementation of this group is optional; it is appropriate
    -- for all systems which have the necessary metering

    dot3CollTable OBJECT-TYPE
        SYNTAX      SEQUENCE OF Dot3CollEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "A collection of collision histograms for a
                    particular set of interfaces."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.1.1.30,
                    aCollisionFrames."
        ::= { dot3 5 }

    dot3CollEntry OBJECT-TYPE
        SYNTAX      Dot3CollEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "A cell in the histogram of per-frame
                    collisions for a particular interface.  An
                    instance of this object represents the
                    frequency of individual MAC frames for which
                    the transmission (successful or otherwise) on a
                    particular interface is accompanied by a

                    particular number of media collisions."
        INDEX       { ifIndex, dot3CollCount }
        ::= { dot3CollTable 1 }

    Dot3CollEntry ::=
        SEQUENCE {
            dot3CollCount        INTEGER,
            dot3CollFrequencies  Counter32
        }

    -- { dot3CollEntry 1 } is no longer in use

    dot3CollCount OBJECT-TYPE
        SYNTAX      INTEGER (1..16)
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "The number of per-frame media collisions for
                    which a particular collision histogram cell
                    represents the frequency on a particular
                    interface."
        ::= { dot3CollEntry 2 }

    dot3CollFrequencies OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of individual MAC frames for which the
                    transmission (successful or otherwise) on a
                    particular interface occurs after the
                    frame has experienced exactly the number
                    of collisions in the associated
                    dot3CollCount object.

                    For example, a frame which is transmitted
                    on interface 77 after experiencing
                    exactly 4 collisions would be indicated
                    by incrementing only dot3CollFrequencies.77.4.
                    No other instance of dot3CollFrequencies would
                    be incremented in this example.

                    This counter does not increment when the
                    interface is operating in full-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        ::= { dot3CollEntry 3 }

    dot3ControlTable OBJECT-TYPE
        SYNTAX      SEQUENCE OF Dot3ControlEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "A table of descriptive and status information
                    about the MAC Control sublayer on the
                    ethernet-like interfaces attached to a
                    particular system.  There will be one row in
                    this table for each ethernet-like interface in
                    the system which implements the MAC Control
                    sublayer.  If some, but not all, of the
                    ethernet-like interfaces in the system implement
                    the MAC Control sublayer, there will be fewer
                    rows in this table than in the dot3StatsTable."
        ::= { dot3 9 }

    dot3ControlEntry OBJECT-TYPE
        SYNTAX      Dot3ControlEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "An entry in the table, containing information
                    about the MAC Control sublayer on a single
                    ethernet-like interface."
        INDEX       { dot3StatsIndex }
        ::= { dot3ControlTable 1 }

    Dot3ControlEntry ::=
        SEQUENCE {
            dot3ControlFunctionsSupported       BITS,
            dot3ControlInUnknownOpcodes         Counter32
        }

    dot3ControlFunctionsSupported OBJECT-TYPE
        SYNTAX      BITS {
                        pause(0)   -- 802.3x flow control
                    }
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A list of the possible MAC Control functions
                    implemented for this interface."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.3.2,
                    aMACControlFunctionsSupported."
        ::= { dot3ControlEntry 1 }

    dot3ControlInUnknownOpcodes OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current

        DESCRIPTION "A count of MAC Control frames received on this
                    interface that contain an opcode that is not
                    supported by this device.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.3.5,
                    aUnsupportedOpcodesReceived"
        ::= { dot3ControlEntry 2 }

    dot3PauseTable OBJECT-TYPE
        SYNTAX      SEQUENCE OF Dot3PauseEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "A table of descriptive and status information
                    about the MAC Control PAUSE function on the
                    ethernet-like interfaces attached to a
                    particular system. There will be one row in
                    this table for each ethernet-like interface in
                    the system which supports the MAC Control PAUSE
                    function (i.e., the 'pause' bit in the
                    corresponding instance of
                    dot3ControlFunctionsSupported is set).  If some,
                    but not all, of the ethernet-like interfaces in
                    the system implement the MAC Control PAUSE
                    function (for example, if some interfaces only
                    support half-duplex), there will be fewer rows
                    in this table than in the dot3StatsTable."
        ::= { dot3 10 }

    dot3PauseEntry OBJECT-TYPE
        SYNTAX      Dot3PauseEntry
        MAX-ACCESS  not-accessible
        STATUS      current
        DESCRIPTION "An entry in the table, containing information
                    about the MAC Control PAUSE function on a single
                    ethernet-like interface."
        INDEX       { dot3StatsIndex }
        ::= { dot3PauseTable 1 }

    Dot3PauseEntry ::=
        SEQUENCE {
            dot3PauseAdminMode                  INTEGER,
            dot3PauseOperMode                   INTEGER,
            dot3InPauseFrames                   Counter32,
            dot3OutPauseFrames                  Counter32

        }

    dot3PauseAdminMode OBJECT-TYPE
        SYNTAX      INTEGER {
                        disabled(1),
                        enabledXmit(2),
                        enabledRcv(3),
                        enabledXmitAndRcv(4)
                    }
        MAX-ACCESS  read-write
        STATUS      current
        DESCRIPTION "This object is used to configure the default
                    administrative PAUSE mode for this interface.

                    This object represents the
                    administratively-configured PAUSE mode for this
                    interface.  If auto-negotiation is not enabled
                    or is not implemented for the active MAU
                    attached to this interface, the value of this
                    object determines the operational PAUSE mode
                    of the interface whenever it is operating in
                    full-duplex mode.  In this case, a set to this
                    object will force the interface into the
                    specified mode.

                    If auto-negotiation is implemented and enabled
                    for the MAU attached to this interface, the
                    PAUSE mode for this interface is determined by
                    auto-negotiation, and the value of this object
                    denotes the mode to which the interface will
                    automatically revert if/when auto-negotiation is
                    later disabled.  Note that when auto-negotiation
                    is running, administrative control of the PAUSE
                    mode may be accomplished using the
                    ifMauAutoNegCapAdvertisedBits object in the
                    MAU-MIB.

                    Note that the value of this object is ignored
                    when the interface is not operating in
                    full-duplex mode.

                    An attempt to set this object to
                    'enabledXmit(2)' or 'enabledRcv(3)' will fail
                    on interfaces that do not support operation
                    at greater than 100 Mb/s."
        ::= { dot3PauseEntry 1 }

    dot3PauseOperMode OBJECT-TYPE

        SYNTAX      INTEGER {
                        disabled(1),
                        enabledXmit(2),
                        enabledRcv(3),
                        enabledXmitAndRcv(4)
                    }
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "This object reflects the PAUSE mode currently
                    in use on this interface, as determined by
                    either (1) the result of the auto-negotiation
                    function or (2) if auto-negotiation is not
                    enabled or is not implemented for the active MAU
                    attached to this interface, by the value of
                    dot3PauseAdminMode.  Interfaces operating at
                    100 Mb/s or less will never return
                    'enabledXmit(2)' or 'enabledRcv(3)'.  Interfaces
                    operating in half-duplex mode will always return
                    'disabled(1)'.  Interfaces on which
                    auto-negotiation is enabled but not yet
                    completed should return the value
                    'disabled(1)'."
        ::= { dot3PauseEntry 2 }

    dot3InPauseFrames OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of MAC Control frames received on this
                    interface with an opcode indicating the PAUSE
                    operation.

                    This counter does not increment when the
                    interface is operating in half-duplex mode.
                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.4.3,
                    aPAUSEMACCtrlFramesReceived."
        ::= { dot3PauseEntry 3 }

    dot3OutPauseFrames OBJECT-TYPE
        SYNTAX      Counter32
        MAX-ACCESS  read-only
        STATUS      current
        DESCRIPTION "A count of MAC Control frames transmitted on
                    this interface with an opcode indicating the

                    PAUSE operation.

                    This counter does not increment when the
                    interface is operating in half-duplex mode.

                    Discontinuities in the value of this counter can
                    occur at re-initialization of the management
                    system, and at other times as indicated by the
                    value of ifCounterDiscontinuityTime."
        REFERENCE   "[IEEE 802.3 Std.], 30.3.4.2,
                    aPAUSEMACCtrlFramesTransmitted."
        ::= { dot3PauseEntry 4 }

    --  802.3 Tests

    dot3Tests   OBJECT IDENTIFIER ::= { dot3 6 }

    dot3Errors  OBJECT IDENTIFIER ::= { dot3 7 }

    --  TDR Test

    dot3TestTdr OBJECT-IDENTITY
        STATUS      current
        DESCRIPTION "The Time-Domain Reflectometry (TDR) test is
                    specific to ethernet-like interfaces of type
                    10Base5 and 10Base2.  The TDR value may be
                    useful in determining the approximate distance
                    to a cable fault.  It is advisable to repeat
                    this test to check for a consistent resulting
                    TDR value, to verify that there is a fault.

                    A TDR test returns as its result the time
                    interval, measured in 10 MHz ticks or 100 nsec
                    units, between the start of TDR test
                    transmission and the subsequent detection of a
                    collision or deassertion of carrier.  On
                    successful completion of a TDR test, the result
                    is stored as the value of an appropriate
                    instance of an appropriate vendor specific MIB
                    object, and the OBJECT IDENTIFIER of that
                    instance is stored in the appropriate instance
                    of the appropriate test result code object
                    (thereby indicating where the result has been
                    stored)."
        ::= { dot3Tests 1 }

    -- Loopback Test

    dot3TestLoopBack OBJECT-IDENTITY
        STATUS      current
        DESCRIPTION "This test configures the MAC chip and executes
                    an internal loopback test of memory, data paths,
                    and the MAC chip logic.  This loopback test can
                    only be executed if the interface is offline.
                    Once the test has completed, the MAC chip should
                    be reinitialized for network operation, but it
                    should remain offline.

                    If an error occurs during a test, the
                    appropriate test result object will be set
                    to indicate a failure.  The two OBJECT
                    IDENTIFIER values dot3ErrorInitError and
                    dot3ErrorLoopbackError may be used to provided
                    more information as values for an appropriate
                    test result code object."
        ::= { dot3Tests 2 }

    dot3ErrorInitError OBJECT-IDENTITY
        STATUS      current
        DESCRIPTION "Couldn't initialize MAC chip for test."
        ::= { dot3Errors 1 }

    dot3ErrorLoopbackError OBJECT-IDENTITY
        STATUS      current
        DESCRIPTION "Expected data not received (or not received
                    correctly) in loopback test."
        ::= { dot3Errors 2 }

    -- { dot3 8 }, the dot3ChipSets tree, is defined in [28]

    -- conformance information

    etherConformance OBJECT IDENTIFIER ::= { etherMIB 2 }

    etherGroups      OBJECT IDENTIFIER ::= { etherConformance 1 }
    etherCompliances OBJECT IDENTIFIER ::= { etherConformance 2 }

    -- compliance statements

    etherCompliance MODULE-COMPLIANCE
        STATUS      deprecated
        DESCRIPTION "******** THIS COMPLIANCE IS DEPRECATED ********

                    The compliance statement for managed network
                    entities which have ethernet-like network
                    interfaces.

                    This compliance is deprecated and replaced by
                    dot3Compliance."

        MODULE  -- this module
            MANDATORY-GROUPS { etherStatsGroup }

            GROUP       etherCollisionTableGroup
            DESCRIPTION "This group is optional. It is appropriate
                        for all systems which have the necessary
                        metering. Implementation in such systems is
                        highly recommended."
        ::= { etherCompliances 1 }

    ether100MbsCompliance MODULE-COMPLIANCE
        STATUS      deprecated
        DESCRIPTION "******** THIS COMPLIANCE IS DEPRECATED ********

                    The compliance statement for managed network
                    entities which have 100 Mb/sec ethernet-like
                    network interfaces.

                    This compliance is deprecated and replaced by
                    dot3Compliance."

        MODULE  -- this module
            MANDATORY-GROUPS { etherStats100MbsGroup }

            GROUP       etherCollisionTableGroup
            DESCRIPTION "This group is optional. It is appropriate
                        for all systems which have the necessary
                        metering. Implementation in such systems is
                        highly recommended."
        ::= { etherCompliances 2 }

    dot3Compliance MODULE-COMPLIANCE
        STATUS      current
        DESCRIPTION "The compliance statement for managed network
                    entities which have ethernet-like network
                    interfaces."

        MODULE  -- this module
            MANDATORY-GROUPS { etherStatsBaseGroup }

            GROUP       etherDuplexGroup
            DESCRIPTION "This group is mandatory for all
                        ethernet-like network interfaces which are
                        capable of operating in full-duplex mode.
                        It is highly recommended for all

                        ethernet-like network interfaces."

            GROUP       etherStatsLowSpeedGroup
            DESCRIPTION "This group is mandatory for all
                        ethernet-like network interfaces which are
                        capable of operating at 10 Mb/s or slower in
                        half-duplex mode."

            GROUP       etherStatsHighSpeedGroup
            DESCRIPTION "This group is mandatory for all
                        ethernet-like network interfaces which are
                        capable of operating at 100 Mb/s or faster."

            GROUP       etherControlGroup
            DESCRIPTION "This group is mandatory for all
                        ethernet-like network interfaces that
                        support the MAC Control sublayer."

            GROUP       etherControlPauseGroup
            DESCRIPTION "This group is mandatory for all
                        ethernet-like network interfaces that
                        support the MAC Control PAUSE function."

            GROUP       etherCollisionTableGroup
            DESCRIPTION "This group is optional. It is appropriate
                        for all ethernet-like network interfaces
                        which are capable of operating in
                        half-duplex mode and have the necessary
                        metering. Implementation in systems with
                        such interfaces is highly recommended."

        ::= { etherCompliances 3 }

    -- units of conformance

    etherStatsGroup OBJECT-GROUP
        OBJECTS     { dot3StatsIndex,
                      dot3StatsAlignmentErrors,
                      dot3StatsFCSErrors,
                      dot3StatsSingleCollisionFrames,
                      dot3StatsMultipleCollisionFrames,
                      dot3StatsSQETestErrors,
                      dot3StatsDeferredTransmissions,
                      dot3StatsLateCollisions,
                      dot3StatsExcessiveCollisions,
                      dot3StatsInternalMacTransmitErrors,
                      dot3StatsCarrierSenseErrors,
                      dot3StatsFrameTooLongs,

                      dot3StatsInternalMacReceiveErrors,
                      dot3StatsEtherChipSet
                    }
        STATUS      deprecated
        DESCRIPTION "********* THIS GROUP IS DEPRECATED **********

                    A collection of objects providing information
                    applicable to all ethernet-like network
                    interfaces.

                    This object group has been deprecated and
                    replaced by etherStatsBaseGroup and
                    etherStatsLowSpeedGroup."
        ::= { etherGroups 1 }

    etherCollisionTableGroup OBJECT-GROUP
        OBJECTS     { dot3CollFrequencies
                    }
        STATUS      current
        DESCRIPTION "A collection of objects providing a histogram
                    of packets successfully transmitted after
                    experiencing exactly N collisions."
        ::= { etherGroups 2 }

    etherStats100MbsGroup OBJECT-GROUP
        OBJECTS     { dot3StatsIndex,
                      dot3StatsAlignmentErrors,
                      dot3StatsFCSErrors,
                      dot3StatsSingleCollisionFrames,
                      dot3StatsMultipleCollisionFrames,
                      dot3StatsDeferredTransmissions,
                      dot3StatsLateCollisions,
                      dot3StatsExcessiveCollisions,
                      dot3StatsInternalMacTransmitErrors,
                      dot3StatsCarrierSenseErrors,
                      dot3StatsFrameTooLongs,
                      dot3StatsInternalMacReceiveErrors,
                      dot3StatsEtherChipSet,
                      dot3StatsSymbolErrors
                    }
        STATUS      deprecated
        DESCRIPTION "********* THIS GROUP IS DEPRECATED **********

                    A collection of objects providing information
                    applicable to 100 Mb/sec ethernet-like network
                    interfaces.

                    This object group has been deprecated and

                    replaced by etherStatsBaseGroup and
                    etherStatsHighSpeedGroup."
        ::= { etherGroups 3 }

    etherStatsBaseGroup OBJECT-GROUP
        OBJECTS     { dot3StatsIndex,
                      dot3StatsAlignmentErrors,
                      dot3StatsFCSErrors,
                      dot3StatsSingleCollisionFrames,
                      dot3StatsMultipleCollisionFrames,
                      dot3StatsDeferredTransmissions,
                      dot3StatsLateCollisions,
                      dot3StatsExcessiveCollisions,
                      dot3StatsInternalMacTransmitErrors,
                      dot3StatsCarrierSenseErrors,
                      dot3StatsFrameTooLongs,
                      dot3StatsInternalMacReceiveErrors
                    }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    applicable to all ethernet-like network
                    interfaces."
        ::= { etherGroups 4 }

    etherStatsLowSpeedGroup OBJECT-GROUP
        OBJECTS     { dot3StatsSQETestErrors }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    applicable to ethernet-like network interfaces
                    capable of operating at 10 Mb/s or slower in
                    half-duplex mode."

        ::= { etherGroups 5 }

    etherStatsHighSpeedGroup OBJECT-GROUP
        OBJECTS     { dot3StatsSymbolErrors }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    applicable to ethernet-like network interfaces
                    capable of operating at 100 Mb/s or faster."
        ::= { etherGroups 6 }

    etherDuplexGroup OBJECT-GROUP
        OBJECTS     { dot3StatsDuplexStatus }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    about the duplex mode of an ethernet-like
                    network interface."

        ::= { etherGroups 7 }

    etherControlGroup OBJECT-GROUP
        OBJECTS     { dot3ControlFunctionsSupported,
                      dot3ControlInUnknownOpcodes
                    }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    about the MAC Control sublayer on ethernet-like
                    network interfaces."
        ::= { etherGroups 8 }

    etherControlPauseGroup OBJECT-GROUP
        OBJECTS     { dot3PauseAdminMode,
                      dot3PauseOperMode,
                      dot3InPauseFrames,
                      dot3OutPauseFrames
                    }
        STATUS      current
        DESCRIPTION "A collection of objects providing information
                    about and control of the MAC Control PAUSE
                    function on ethernet-like network interfaces."
        ::= { etherGroups 9 }

END


HOST-RESOURCES-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, mib-2,
    Integer32, Counter32, Gauge32, TimeTicks  FROM SNMPv2-SMI

    TEXTUAL-CONVENTION, DisplayString,
    TruthValue, DateAndTime, AutonomousType   FROM SNMPv2-TC

    MODULE-COMPLIANCE, OBJECT-GROUP           FROM SNMPv2-CONF

    InterfaceIndexOrZero                      FROM IF-MIB;

hostResourcesMibModule MODULE-IDENTITY
    LAST-UPDATED "200003060000Z"    -- 6 March 2000
    ORGANIZATION "IETF Host Resources MIB Working Group"
    CONTACT-INFO
        "Steve Waldbusser
        Postal: Lucent Technologies, Inc.
                1213 Innsbruck Dr.
                Sunnyvale, CA 94089
                USA
        Phone:  650-318-1251
        Fax:    650-318-1633
        Email:  waldbusser@lucent.com

        In addition, the Host Resources MIB mailing list is
        dedicated to discussion of this MIB. To join the
        mailing list, send a request message to
        hostmib-request@andrew.cmu.edu. The mailing list
        address is hostmib@andrew.cmu.edu."

    DESCRIPTION
        "This MIB is for use in managing host systems. The term
        `host' is construed to mean any computer that communicates
        with other similar computers attached to the internet and
        that is directly used by one or more human beings. Although
        this MIB does not necessarily apply to devices whose primary
        function is communications services (e.g., terminal servers,
        routers, bridges, monitoring equipment), such relevance is
        not explicitly precluded.  This MIB instruments attributes
        common to all internet hosts including, for example, both
        personal computers and systems that run variants of Unix."

    REVISION "200003060000Z"        -- 6 March 2000
    DESCRIPTION
        "Clarifications and bug fixes based on implementation
        experience.  This revision was also reformatted in the SMIv2
        format. The revisions made were:

        New RFC document standards:
           Added Copyright notice, updated introduction to SNMP
           Framework, updated references section, added reference to
           RFC 2119, and added a meaningful Security Considerations
           section.

        New IANA considerations section for registration of new types

        Conversion to new SMIv2 syntax for the following types and
        macros:
            Counter32, Integer32, Gauge32, MODULE-IDENTITY,
            OBJECT-TYPE, TEXTUAL-CONVENTION, OBJECT-IDENTITY,
            MODULE-COMPLIANCE, OBJECT-GROUP

        Used new Textual Conventions:
            TruthValue, DateAndTime, AutonomousType,
            InterfaceIndexOrZero

        Fixed typo in hrPrinterStatus.

        Added missing error bits to hrPrinterDetectedErrorState and
        clarified confusion resulting from suggested mappings to
        hrPrinterStatus.

        Clarified that size of objects of type
        InternationalDisplayString is number of octets, not number
        of encoded symbols.

        Clarified the use of the following objects based on
        implementation experience:
            hrSystemInitialLoadDevice, hrSystemInitialLoadParameters,
            hrMemorySize, hrStorageSize, hrStorageAllocationFailures,
            hrDeviceErrors, hrProcessorLoad, hrNetworkIfIndex,
            hrDiskStorageCapacity, hrSWRunStatus, hrSWRunPerfCPU,
            and hrSWInstalledDate.

        Clarified implementation technique for hrSWInstalledTable.

        Used new AUGMENTS clause for hrSWRunPerfTable.

        Added Internationalization Considerations section.

        This revision published as RFC2790."

    REVISION "9910202200Z"    -- 20 October, 1999
    DESCRIPTION
        "The original version of this MIB, published as
        RFC1514."
    ::= { hrMIBAdminInfo 1 }

host     OBJECT IDENTIFIER ::= { mib-2 25 }

hrSystem        OBJECT IDENTIFIER ::= { host 1 }
hrStorage       OBJECT IDENTIFIER ::= { host 2 }
hrDevice        OBJECT IDENTIFIER ::= { host 3 }
hrSWRun         OBJECT IDENTIFIER ::= { host 4 }
hrSWRunPerf     OBJECT IDENTIFIER ::= { host 5 }
hrSWInstalled   OBJECT IDENTIFIER ::= { host 6 }
hrMIBAdminInfo  OBJECT IDENTIFIER ::= { host 7 }

-- textual conventions

KBytes ::= TEXTUAL-CONVENTION
    STATUS current
    DESCRIPTION
        "Storage size, expressed in units of 1024 bytes."
    SYNTAX Integer32 (0..2147483647)

ProductID ::= TEXTUAL-CONVENTION
    STATUS current
    DESCRIPTION
        "This textual convention is intended to identify the
        manufacturer, model, and version of a specific
        hardware or software product.  It is suggested that
        these OBJECT IDENTIFIERs are allocated such that all
        products from a particular manufacturer are registered
        under a subtree distinct to that manufacturer.  In
        addition, all versions of a product should be
        registered under a subtree distinct to that product.
        With this strategy, a management station may uniquely
        determine the manufacturer and/or model of a product
        whose productID is unknown to the management station.
        Objects of this type may be useful for inventory
        purposes or for automatically detecting
        incompatibilities or version mismatches between
        various hardware and software components on a system.

        For example, the product ID for the ACME 4860 66MHz
        clock doubled processor might be:
        enterprises.acme.acmeProcessors.a4860DX2.MHz66

        A software product might be registered as:
        enterprises.acme.acmeOperatingSystems.acmeDOS.six(6).one(1)
        "
    SYNTAX OBJECT IDENTIFIER

-- unknownProduct will be used for any unknown ProductID
-- unknownProduct OBJECT IDENTIFIER ::= { 0 0 }

InternationalDisplayString ::= TEXTUAL-CONVENTION
    STATUS current
    DESCRIPTION
        "This data type is used to model textual information
        in some character set.  A network management station
        should use a local algorithm to determine which
        character set is in use and how it should be
        displayed.  Note that this character set may be
        encoded with more than one octet per symbol, but will
        most often be NVT ASCII. When a size clause is
        specified for an object of this type, the size refers
        to the length in octets, not the number of symbols."
    SYNTAX OCTET STRING

-- The Host Resources System Group

hrSystemUptime OBJECT-TYPE
    SYNTAX     TimeTicks
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The amount of time since this host was last
        initialized.  Note that this is different from
        sysUpTime in the SNMPv2-MIB [RFC1907] because
        sysUpTime is the uptime of the network management
        portion of the system."
    ::= { hrSystem 1 }

hrSystemDate OBJECT-TYPE
    SYNTAX     DateAndTime
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The host's notion of the local date and time of day."
    ::= { hrSystem 2 }

hrSystemInitialLoadDevice OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The index of the hrDeviceEntry for the device from
        which this host is configured to load its initial
        operating system configuration (i.e., which operating
        system code and/or boot parameters).

        Note that writing to this object just changes the
        configuration that will be used the next time the
        operating system is loaded and does not actually cause
        the reload to occur."
    ::= { hrSystem 3 }

hrSystemInitialLoadParameters OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE (0..128))
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "This object contains the parameters (e.g. a pathname
        and parameter) supplied to the load device when
        requesting the initial operating system configuration
        from that device.

     Note that writing to this object just changes the
     configuration that will be used the next time the
     operating system is loaded and does not actually cause
     the reload to occur."
    ::= { hrSystem 4 }

hrSystemNumUsers OBJECT-TYPE
    SYNTAX     Gauge32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of user sessions for which this host is
        storing state information.  A session is a collection
        of processes requiring a single act of user
        authentication and possibly subject to collective job
        control."
    ::= { hrSystem 5 }

hrSystemProcesses OBJECT-TYPE
    SYNTAX     Gauge32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of process contexts currently loaded or
        running on this system."
    ::= { hrSystem 6 }

hrSystemMaxProcesses OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The maximum number of process contexts this system
        can support.  If there is no fixed maximum, the value
        should be zero.  On systems that have a fixed maximum,
        this object can help diagnose failures that occur when
        this maximum is reached."
    ::= { hrSystem 7 }

-- The Host Resources Storage Group

-- Registration point for storage types, for use with hrStorageType.
-- These are defined in the HOST-RESOURCES-TYPES module.
hrStorageTypes          OBJECT IDENTIFIER ::= { hrStorage 1 }

hrMemorySize OBJECT-TYPE
    SYNTAX     KBytes
    UNITS      "KBytes"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The amount of physical read-write main memory,
        typically RAM, contained by the host."
    ::= { hrStorage 2 }

hrStorageTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrStorageEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of logical storage areas on
        the host.

        An entry shall be placed in the storage table for each
        logical area of storage that is allocated and has
        fixed resource limits.  The amount of storage
        represented in an entity is the amount actually usable
        by the requesting entity, and excludes loss due to
        formatting or file system reference information.

        These entries are associated with logical storage
        areas, as might be seen by an application, rather than
        physical storage entities which are typically seen by
        an operating system.  Storage such as tapes and
        floppies without file systems on them are typically
        not allocated in chunks by the operating system to
        requesting applications, and therefore shouldn't
        appear in this table.  Examples of valid storage for
        this table include disk partitions, file systems, ram
        (for some architectures this is further segmented into
        regular memory, extended memory, and so on), backing
        store for virtual memory (`swap space').

        This table is intended to be a useful diagnostic for
        `out of memory' and `out of buffers' types of
        failures.  In addition, it can be a useful performance
        monitoring tool for tracking memory, disk, or buffer
        usage."
    ::= { hrStorage 3 }

hrStorageEntry OBJECT-TYPE
    SYNTAX     HrStorageEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one logical storage area on
        the host.  As an example, an instance of the
        hrStorageType object might be named hrStorageType.3"
    INDEX { hrStorageIndex }
    ::= { hrStorageTable 1 }

HrStorageEntry ::= SEQUENCE {
        hrStorageIndex               Integer32,
        hrStorageType                AutonomousType,
        hrStorageDescr               DisplayString,
        hrStorageAllocationUnits     Integer32,
        hrStorageSize                Integer32,
        hrStorageUsed                Integer32,
        hrStorageAllocationFailures  Counter32
    }

hrStorageIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each logical storage area
        contained by the host."
    ::= { hrStorageEntry 1 }

hrStorageType OBJECT-TYPE
    SYNTAX     AutonomousType
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The type of storage represented by this entry."
    ::= { hrStorageEntry 2 }

hrStorageDescr OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A description of the type and instance of the storage
        described by this entry."
    ::= { hrStorageEntry 3 }

hrStorageAllocationUnits OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    UNITS      "Bytes"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The size, in bytes, of the data objects allocated
        from this pool.  If this entry is monitoring sectors,
        blocks, buffers, or packets, for example, this number
        will commonly be greater than one.  Otherwise this
        number will typically be one."
    ::= { hrStorageEntry 4 }

hrStorageSize OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The size of the storage represented by this entry, in
        units of hrStorageAllocationUnits. This object is
        writable to allow remote configuration of the size of
        the storage area in those cases where such an
        operation makes sense and is possible on the
        underlying system. For example, the amount of main
        memory allocated to a buffer pool might be modified or
        the amount of disk space allocated to virtual memory
        might be modified."
    ::= { hrStorageEntry 5 }

hrStorageUsed OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The amount of the storage represented by this entry
        that is allocated, in units of
        hrStorageAllocationUnits."
    ::= { hrStorageEntry 6 }

hrStorageAllocationFailures OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of requests for storage represented by
        this entry that could not be honored due to not enough
        storage.  It should be noted that as this object has a
        SYNTAX of Counter32, that it does not have a defined
        initial value.  However, it is recommended that this
        object be initialized to zero, even though management
        stations must not depend on such an initialization."
    ::= { hrStorageEntry 7 }

-- The Host Resources Device Group
--
-- The device group is useful for identifying and diagnosing the
-- devices on a system.  The hrDeviceTable contains common
-- information for any type of device.  In addition, some devices
-- have device-specific tables for more detailed information.  More
-- such tables may be defined in the future for other device types.

-- Registration point for device types, for use with hrDeviceType.
-- These are defined in the HOST-RESOURCES-TYPES module.
hrDeviceTypes             OBJECT IDENTIFIER ::= { hrDevice 1 }

hrDeviceTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrDeviceEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of devices contained by the
        host."
    ::= { hrDevice 2 }

hrDeviceEntry OBJECT-TYPE
    SYNTAX     HrDeviceEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one device contained by the
        host.  As an example, an instance of the hrDeviceType
        object might be named hrDeviceType.3"
    INDEX { hrDeviceIndex }
    ::= { hrDeviceTable 1 }

HrDeviceEntry ::= SEQUENCE {
        hrDeviceIndex           Integer32,
        hrDeviceType            AutonomousType,
        hrDeviceDescr           DisplayString,
        hrDeviceID              ProductID,
        hrDeviceStatus          INTEGER,
        hrDeviceErrors          Counter32
    }

hrDeviceIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each device contained by the host.
        The value for each device must remain constant at
        least from one re-initialization of the agent to the
        next re-initialization."
    ::= { hrDeviceEntry 1 }

hrDeviceType OBJECT-TYPE
    SYNTAX     AutonomousType
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "An indication of the type of device.

        If this value is
        `hrDeviceProcessor { hrDeviceTypes 3 }' then an entry
        exists in the hrProcessorTable which corresponds to
        this device.

        If this value is
        `hrDeviceNetwork { hrDeviceTypes 4 }', then an entry
        exists in the hrNetworkTable which corresponds to this
        device.

        If this value is
        `hrDevicePrinter { hrDeviceTypes 5 }', then an entry
        exists in the hrPrinterTable which corresponds to this
        device.

        If this value is
        `hrDeviceDiskStorage { hrDeviceTypes 6 }', then an
        entry exists in the hrDiskStorageTable which
        corresponds to this device."
    ::= { hrDeviceEntry 2 }

hrDeviceDescr OBJECT-TYPE
    SYNTAX     DisplayString (SIZE (0..64))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of this device, including the
        device's manufacturer and revision, and optionally,
        its serial number."
    ::= { hrDeviceEntry 3 }

hrDeviceID OBJECT-TYPE
    SYNTAX     ProductID
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The product ID for this device."
    ::= { hrDeviceEntry 4 }

hrDeviceStatus OBJECT-TYPE
    SYNTAX     INTEGER {
                   unknown(1),
                   running(2),
                   warning(3),
                   testing(4),
                   down(5)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The current operational state of the device described
        by this row of the table.  A value unknown(1)
        indicates that the current state of the device is
        unknown.  running(2) indicates that the device is up
        and running and that no unusual error conditions are
        known.  The warning(3) state indicates that agent has
        been informed of an unusual error condition by the
        operational software (e.g., a disk device driver) but
        that the device is still 'operational'.  An example
        would be a high number of soft errors on a disk.  A
        value of testing(4), indicates that the device is not
        available for use because it is in the testing state.
        The state of down(5) is used only when the agent has
        been informed that the device is not available for any
        use."
    ::= { hrDeviceEntry 5 }

hrDeviceErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of errors detected on this device.  It
        should be noted that as this object has a SYNTAX of
        Counter32, that it does not have a defined initial
        value.  However, it is recommended that this object be
        initialized to zero, even though management stations
        must not depend on such an initialization."
    ::= { hrDeviceEntry 6 }

hrProcessorTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrProcessorEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of processors contained by the
        host.

        Note that this table is potentially sparse: a
        (conceptual) entry exists only if the correspondent
        value of the hrDeviceType object is
        `hrDeviceProcessor'."
    ::= { hrDevice 3 }

hrProcessorEntry OBJECT-TYPE
    SYNTAX     HrProcessorEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one processor contained by
        the host.  The hrDeviceIndex in the index represents
        the entry in the hrDeviceTable that corresponds to the
        hrProcessorEntry.

        As an example of how objects in this table are named,
        an instance of the hrProcessorFrwID object might be
        named hrProcessorFrwID.3"
    INDEX { hrDeviceIndex }
    ::= { hrProcessorTable 1 }

HrProcessorEntry ::= SEQUENCE {
        hrProcessorFrwID            ProductID,
        hrProcessorLoad             Integer32
    }

hrProcessorFrwID OBJECT-TYPE
    SYNTAX     ProductID
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The product ID of the firmware associated with the
        processor."
    ::= { hrProcessorEntry 1 }

hrProcessorLoad OBJECT-TYPE
    SYNTAX     Integer32 (0..100)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The average, over the last minute, of the percentage
        of time that this processor was not idle.
        Implementations may approximate this one minute
        smoothing period if necessary."
    ::= { hrProcessorEntry 2 }

hrNetworkTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrNetworkEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of network devices contained
        by the host.

        Note that this table is potentially sparse: a
        (conceptual) entry exists only if the correspondent
        value of the hrDeviceType object is
        `hrDeviceNetwork'."
    ::= { hrDevice 4 }

hrNetworkEntry OBJECT-TYPE
    SYNTAX     HrNetworkEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one network device contained
        by the host.  The hrDeviceIndex in the index
        represents the entry in the hrDeviceTable that
        corresponds to the hrNetworkEntry.

        As an example of how objects in this table are named,
        an instance of the hrNetworkIfIndex object might be
        named hrNetworkIfIndex.3"
    INDEX { hrDeviceIndex }
    ::= { hrNetworkTable 1 }

HrNetworkEntry ::= SEQUENCE {
        hrNetworkIfIndex    InterfaceIndexOrZero
    }

hrNetworkIfIndex OBJECT-TYPE
    SYNTAX     InterfaceIndexOrZero
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of ifIndex which corresponds to this
        network device. If this device is not represented in
        the ifTable, then this value shall be zero."
    ::= { hrNetworkEntry 1 }

hrPrinterTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrPrinterEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of printers local to the host.

        Note that this table is potentially sparse: a
        (conceptual) entry exists only if the correspondent
        value of the hrDeviceType object is
        `hrDevicePrinter'."
    ::= { hrDevice 5 }

hrPrinterEntry OBJECT-TYPE
    SYNTAX     HrPrinterEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one printer local to the
        host.  The hrDeviceIndex in the index represents the
        entry in the hrDeviceTable that corresponds to the
        hrPrinterEntry.

        As an example of how objects in this table are named,
        an instance of the hrPrinterStatus object might be
        named hrPrinterStatus.3"
    INDEX { hrDeviceIndex }
    ::= { hrPrinterTable 1 }

HrPrinterEntry ::= SEQUENCE {
        hrPrinterStatus             INTEGER,
        hrPrinterDetectedErrorState OCTET STRING
    }

hrPrinterStatus OBJECT-TYPE
    SYNTAX     INTEGER {
                   other(1),
                   unknown(2),
                   idle(3),
                   printing(4),
                   warmup(5)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The current status of this printer device."
    ::= { hrPrinterEntry 1 }

hrPrinterDetectedErrorState OBJECT-TYPE
    SYNTAX     OCTET STRING
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "This object represents any error conditions detected
        by the printer.  The error conditions are encoded as
        bits in an octet string, with the following
        definitions:

             Condition         Bit #

             lowPaper              0
             noPaper               1
             lowToner              2
             noToner               3
             doorOpen              4
             jammed                5
             offline               6
             serviceRequested      7
             inputTrayMissing      8
             outputTrayMissing     9
             markerSupplyMissing  10
             outputNearFull       11
             outputFull           12
             inputTrayEmpty       13
             overduePreventMaint  14

        Bits are numbered starting with the most significant
        bit of the first byte being bit 0, the least
        significant bit of the first byte being bit 7, the
        most significant bit of the second byte being bit 8,
        and so on.  A one bit encodes that the condition was
        detected, while a zero bit encodes that the condition
        was not detected.

        This object is useful for alerting an operator to
        specific warning or error conditions that may occur,
        especially those requiring human intervention."
    ::= { hrPrinterEntry 2 }

hrDiskStorageTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrDiskStorageEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of long-term storage devices
        contained by the host.  In particular, disk devices
        accessed remotely over a network are not included
        here.

        Note that this table is potentially sparse: a
        (conceptual) entry exists only if the correspondent
        value of the hrDeviceType object is
        `hrDeviceDiskStorage'."
    ::= { hrDevice 6 }

hrDiskStorageEntry OBJECT-TYPE
    SYNTAX     HrDiskStorageEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one long-term storage device
        contained by the host.  The hrDeviceIndex in the index
        represents the entry in the hrDeviceTable that
        corresponds to the hrDiskStorageEntry. As an example,
        an instance of the hrDiskStorageCapacity object might
        be named hrDiskStorageCapacity.3"
    INDEX { hrDeviceIndex }
    ::= { hrDiskStorageTable 1 }

HrDiskStorageEntry ::= SEQUENCE {
        hrDiskStorageAccess         INTEGER,
        hrDiskStorageMedia          INTEGER,
        hrDiskStorageRemoveble      TruthValue,
        hrDiskStorageCapacity       KBytes
    }

hrDiskStorageAccess OBJECT-TYPE
    SYNTAX     INTEGER {
                   readWrite(1),
                   readOnly(2)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "An indication if this long-term storage device is
        readable and writable or only readable.  This should
        reflect the media type, any write-protect mechanism,
        and any device configuration that affects the entire
        device."
    ::= { hrDiskStorageEntry 1 }

hrDiskStorageMedia OBJECT-TYPE
    SYNTAX     INTEGER {
                   other(1),
                   unknown(2),
                   hardDisk(3),
                   floppyDisk(4),
                   opticalDiskROM(5),
                   opticalDiskWORM(6),     -- Write Once Read Many
                   opticalDiskRW(7),
                   ramDisk(8)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "An indication of the type of media used in this long-
        term storage device."
    ::= { hrDiskStorageEntry 2 }

hrDiskStorageRemoveble OBJECT-TYPE
    SYNTAX     TruthValue
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "Denotes whether or not the disk media may be removed
        from the drive."
    ::= { hrDiskStorageEntry 3 }

hrDiskStorageCapacity OBJECT-TYPE
    SYNTAX     KBytes
    UNITS      "KBytes"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total size for this long-term storage device. If
        the media is removable and is currently removed, this
        value should be zero."
    ::= { hrDiskStorageEntry 4 }

hrPartitionTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrPartitionEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of partitions for long-term
        storage devices contained by the host.  In particular,
        partitions accessed remotely over a network are not
        included here."
    ::= { hrDevice 7 }

hrPartitionEntry OBJECT-TYPE
    SYNTAX     HrPartitionEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one partition.  The
        hrDeviceIndex in the index represents the entry in the
        hrDeviceTable that corresponds to the
        hrPartitionEntry.

        As an example of how objects in this table are named,
        an instance of the hrPartitionSize object might be
        named hrPartitionSize.3.1"
    INDEX { hrDeviceIndex, hrPartitionIndex }
    ::= { hrPartitionTable 1 }

HrPartitionEntry ::= SEQUENCE {
        hrPartitionIndex                Integer32,
        hrPartitionLabel                InternationalDisplayString,
        hrPartitionID                   OCTET STRING,
        hrPartitionSize                 KBytes,
        hrPartitionFSIndex              Integer32
    }

hrPartitionIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each partition on this long-term
        storage device.  The value for each long-term storage
        device must remain constant at least from one re-
        initialization of the agent to the next re-
        initialization."
    ::= { hrPartitionEntry 1 }

hrPartitionLabel OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE (0..128))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of this partition."
    ::= { hrPartitionEntry 2 }

hrPartitionID OBJECT-TYPE
    SYNTAX     OCTET STRING
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A descriptor which uniquely represents this partition
        to the responsible operating system.  On some systems,
        this might take on a binary representation."
    ::= { hrPartitionEntry 3 }

hrPartitionSize OBJECT-TYPE
    SYNTAX     KBytes
    UNITS      "KBytes"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The size of this partition."
    ::= { hrPartitionEntry 4 }

hrPartitionFSIndex OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The index of the file system mounted on this
        partition.  If no file system is mounted on this
        partition, then this value shall be zero.  Note that
        multiple partitions may point to one file system,
        denoting that that file system resides on those
        partitions.  Multiple file systems may not reside on
        one partition."
    ::= { hrPartitionEntry 5 }

-- The File System Table

-- Registration point for popular File System types,
-- for use with hrFSType. These are defined in the
-- HOST-RESOURCES-TYPES module.
hrFSTypes               OBJECT IDENTIFIER ::= { hrDevice 9 }

hrFSTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrFSEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of file systems local to this
        host or remotely mounted from a file server.  File
        systems that are in only one user's environment on a
        multi-user system will not be included in this table."
    ::= { hrDevice 8 }

hrFSEntry OBJECT-TYPE
    SYNTAX     HrFSEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one file system local to
        this host or remotely mounted from a file server.
        File systems that are in only one user's environment
        on a multi-user system will not be included in this
        table.

        As an example of how objects in this table are named,
        an instance of the hrFSMountPoint object might be
        named hrFSMountPoint.3"
    INDEX { hrFSIndex }
    ::= { hrFSTable 1 }

HrFSEntry ::= SEQUENCE {
        hrFSIndex                   Integer32,
        hrFSMountPoint              InternationalDisplayString,
        hrFSRemoteMountPoint        InternationalDisplayString,
        hrFSType                    AutonomousType,
        hrFSAccess                  INTEGER,
        hrFSBootable                TruthValue,
        hrFSStorageIndex            Integer32,
        hrFSLastFullBackupDate      DateAndTime,
        hrFSLastPartialBackupDate   DateAndTime
    }

hrFSIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each file system local to this
        host.  The value for each file system must remain
        constant at least from one re-initialization of the
        agent to the next re-initialization."
    ::= { hrFSEntry 1 }

hrFSMountPoint OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE(0..128))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The path name of the root of this file system."
    ::= { hrFSEntry 2 }

hrFSRemoteMountPoint OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE(0..128))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A description of the name and/or address of the
        server that this file system is mounted from.  This
        may also include parameters such as the mount point on
        the remote file system.  If this is not a remote file
        system, this string should have a length of zero."
    ::= { hrFSEntry 3 }

hrFSType OBJECT-TYPE
    SYNTAX     AutonomousType
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of this object identifies the type of this
        file system."
    ::= { hrFSEntry 4 }

hrFSAccess OBJECT-TYPE
    SYNTAX     INTEGER {
                   readWrite(1),
                   readOnly(2)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "An indication if this file system is logically
        configured by the operating system to be readable and
        writable or only readable.  This does not represent
        any local access-control policy, except one that is
        applied to the file system as a whole."
    ::= { hrFSEntry 5 }

hrFSBootable OBJECT-TYPE
    SYNTAX     TruthValue
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A flag indicating whether this file system is
        bootable."
    ::= { hrFSEntry 6 }

hrFSStorageIndex OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The index of the hrStorageEntry that represents
        information about this file system.  If there is no
        such information available, then this value shall be
        zero.  The relevant storage entry will be useful in
        tracking the percent usage of this file system and
        diagnosing errors that may occur when it runs out of
        space."
    ::= { hrFSEntry 7 }

hrFSLastFullBackupDate OBJECT-TYPE
    SYNTAX     DateAndTime
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The last date at which this complete file system was
        copied to another storage device for backup.  This
        information is useful for ensuring that backups are
        being performed regularly.

        If this information is not known, then this variable
        shall have the value corresponding to January 1, year
        0000, 00:00:00.0, which is encoded as
        (hex)'00 00 01 01 00 00 00 00'."
    ::= { hrFSEntry 8 }

hrFSLastPartialBackupDate OBJECT-TYPE
    SYNTAX     DateAndTime
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The last date at which a portion of this file system
        was copied to another storage device for backup.  This
        information is useful for ensuring that backups are
        being performed regularly.

        If this information is not known, then this variable
        shall have the value corresponding to January 1, year
        0000, 00:00:00.0, which is encoded as
        (hex)'00 00 01 01 00 00 00 00'."
    ::= { hrFSEntry 9 }

-- The Host Resources Running Software Group
--
-- The hrSWRunTable contains an entry for each distinct piece of
-- software that is running or loaded into physical or virtual
-- memory in preparation for running.  This includes the host's
-- operating system, device drivers, and applications.

hrSWOSIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of the hrSWRunIndex for the hrSWRunEntry
        that represents the primary operating system running
        on this host.  This object is useful for quickly and
        uniquely identifying that primary operating system."
    ::= { hrSWRun 1 }

hrSWRunTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrSWRunEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of software running on the
        host."
    ::= { hrSWRun 2 }

hrSWRunEntry OBJECT-TYPE
    SYNTAX     HrSWRunEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for one piece of software
        running on the host Note that because the installed
        software table only contains information for software
        stored locally on this host, not every piece of
        running software will be found in the installed
        software table.  This is true of software that was
        loaded and run from a non-local source, such as a
        network-mounted file system.

        As an example of how objects in this table are named,
        an instance of the hrSWRunName object might be named
        hrSWRunName.1287"
    INDEX { hrSWRunIndex }
    ::= { hrSWRunTable 1 }

HrSWRunEntry ::= SEQUENCE {
        hrSWRunIndex       Integer32,
        hrSWRunName        InternationalDisplayString,
        hrSWRunID          ProductID,
        hrSWRunPath        InternationalDisplayString,
        hrSWRunParameters  InternationalDisplayString,
        hrSWRunType        INTEGER,
        hrSWRunStatus      INTEGER
    }

hrSWRunIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each piece of software running on
        the host.  Wherever possible, this should be the
        system's native, unique identification number."
    ::= { hrSWRunEntry 1 }

hrSWRunName OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE (0..64))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of this running piece of
        software, including the manufacturer, revision,  and
        the name by which it is commonly known.  If this
        software was installed locally, this should be the
        same string as used in the corresponding
        hrSWInstalledName."
    ::= { hrSWRunEntry 2 }

hrSWRunID OBJECT-TYPE
    SYNTAX     ProductID
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The product ID of this running piece of software."
    ::= { hrSWRunEntry 3 }

hrSWRunPath OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE(0..128))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A description of the location on long-term storage
        (e.g. a disk drive) from which this software was
        loaded."
    ::= { hrSWRunEntry 4 }

hrSWRunParameters OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE(0..128))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A description of the parameters supplied to this
        software when it was initially loaded."
    ::= { hrSWRunEntry 5 }

hrSWRunType OBJECT-TYPE
    SYNTAX     INTEGER {
                   unknown(1),
                   operatingSystem(2),
                   deviceDriver(3),
                   application(4)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The type of this software."
    ::= { hrSWRunEntry 6 }

hrSWRunStatus OBJECT-TYPE
    SYNTAX     INTEGER {
                   running(1),
                   runnable(2),    -- waiting for resource
                                   -- (i.e., CPU, memory, IO)
                   notRunnable(3), -- loaded but waiting for event
                   invalid(4)      -- not loaded
               }
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The status of this running piece of software.
        Setting this value to invalid(4) shall cause this
        software to stop running and to be unloaded. Sets to
        other values are not valid."
    ::= { hrSWRunEntry 7 }

-- The Host Resources Running Software Performance Group
--
-- The hrSWRunPerfTable contains an entry corresponding to
-- each entry in the hrSWRunTable.

hrSWRunPerfTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrSWRunPerfEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of running software
        performance metrics."
    ::= { hrSWRunPerf 1 }

hrSWRunPerfEntry OBJECT-TYPE
    SYNTAX     HrSWRunPerfEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry containing software performance
        metrics.  As an example, an instance of the
        hrSWRunPerfCPU object might be named
        hrSWRunPerfCPU.1287"
    AUGMENTS { hrSWRunEntry }  -- This table augments information in
                               -- the hrSWRunTable.
    ::= { hrSWRunPerfTable 1 }

HrSWRunPerfEntry ::= SEQUENCE {
        hrSWRunPerfCPU          Integer32,
        hrSWRunPerfMem          KBytes
    }

hrSWRunPerfCPU OBJECT-TYPE
    SYNTAX     Integer32 (0..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of centi-seconds of the total system's CPU
        resources consumed by this process.  Note that on a
        multi-processor system, this value may increment by
        more than one centi-second in one centi-second of real
        (wall clock) time."
    ::= { hrSWRunPerfEntry 1 }

hrSWRunPerfMem OBJECT-TYPE
    SYNTAX     KBytes
    UNITS      "KBytes"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total amount of real system memory allocated to
        this process."
    ::= { hrSWRunPerfEntry 2 }

-- The Host Resources Installed Software Group
--
-- The hrSWInstalledTable contains an entry for each piece
-- of software installed in long-term storage (e.g. a disk
-- drive) locally on this host.  Note that this does not
-- include software loadable remotely from a network
-- server.
--
-- Different implementations may track software in varying
-- ways. For example, while some implementations may track
-- executable files as distinct pieces of software, other
-- implementations may use other strategies such as keeping
-- track of software "packages" (e.g., related groups of files)
-- or keeping track of system or application "patches".
--
-- This table is useful for identifying and inventorying
-- software on a host and for diagnosing incompatibility
-- and version mismatch problems between various pieces
-- of hardware and software.

hrSWInstalledLastChange OBJECT-TYPE
    SYNTAX     TimeTicks
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of sysUpTime when an entry in the
        hrSWInstalledTable was last added, renamed, or
        deleted.  Because this table is likely to contain many
        entries, polling of this object allows a management
        station to determine when re-downloading of the table
        might be useful."
    ::= { hrSWInstalled 1 }

hrSWInstalledLastUpdateTime OBJECT-TYPE
    SYNTAX     TimeTicks
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of sysUpTime when the hrSWInstalledTable
        was last completely updated.  Because caching of this
        data will be a popular implementation strategy,
        retrieval of this object allows a management station
        to obtain a guarantee that no data in this table is
        older than the indicated time."
    ::= { hrSWInstalled 2 }

hrSWInstalledTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF HrSWInstalledEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table of software installed on this
        host."
    ::= { hrSWInstalled 3 }

hrSWInstalledEntry OBJECT-TYPE
    SYNTAX     HrSWInstalledEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A (conceptual) entry for a piece of software
        installed on this host.

        As an example of how objects in this table are named,
        an instance of the hrSWInstalledName object might be
        named hrSWInstalledName.96"
    INDEX { hrSWInstalledIndex }
    ::= { hrSWInstalledTable 1 }

HrSWInstalledEntry ::= SEQUENCE {
        hrSWInstalledIndex       Integer32,
        hrSWInstalledName        InternationalDisplayString,
        hrSWInstalledID          ProductID,
        hrSWInstalledType        INTEGER,
        hrSWInstalledDate        DateAndTime
    }

hrSWInstalledIndex OBJECT-TYPE
    SYNTAX     Integer32 (1..2147483647)
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A unique value for each piece of software installed
        on the host.  This value shall be in the range from 1
        to the number of pieces of software installed on the
        host."
    ::= { hrSWInstalledEntry 1 }

hrSWInstalledName OBJECT-TYPE
    SYNTAX     InternationalDisplayString (SIZE (0..64))
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of this installed piece of
        software, including the manufacturer, revision, the
        name by which it is commonly known, and optionally,
        its serial number."
    ::= { hrSWInstalledEntry 2 }

hrSWInstalledID OBJECT-TYPE
    SYNTAX     ProductID
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The product ID of this installed piece of software."
    ::= { hrSWInstalledEntry 3 }

hrSWInstalledType OBJECT-TYPE
    SYNTAX     INTEGER {
                   unknown(1),
                   operatingSystem(2),
                   deviceDriver(3),
                   application(4)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The type of this software."
    ::= { hrSWInstalledEntry 4 }

hrSWInstalledDate OBJECT-TYPE
    SYNTAX     DateAndTime
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The last-modification date of this application as it
        would appear in a directory listing.

        If this information is not known, then this variable
        shall have the value corresponding to January 1, year
        0000, 00:00:00.0, which is encoded as
        (hex)'00 00 01 01 00 00 00 00'."
    ::= { hrSWInstalledEntry 5 }

-- Conformance information

hrMIBCompliances OBJECT IDENTIFIER ::= { hrMIBAdminInfo 2 }
hrMIBGroups      OBJECT IDENTIFIER ::= { hrMIBAdminInfo 3 }

-- Compliance Statements
hrMIBCompliance MODULE-COMPLIANCE
    STATUS current
    DESCRIPTION
        "The requirements for conformance to the Host Resources MIB."
    MODULE -- this module
      MANDATORY-GROUPS { hrSystemGroup, hrStorageGroup,
                         hrDeviceGroup }

      OBJECT hrSystemDate
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      OBJECT hrSystemInitialLoadDevice
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      OBJECT hrSystemInitialLoadParameters
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      OBJECT hrStorageSize
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      OBJECT hrFSLastFullBackupDate
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      OBJECT hrFSLastPartialBackupDate
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      GROUP hrSWRunGroup
          DESCRIPTION
              "The Running Software Group. Implementation
              of this group is mandatory only when the
              hrSWRunPerfGroup is implemented."

      OBJECT hrSWRunStatus
          MIN-ACCESS read-only
          DESCRIPTION
              "Write access is not required."

      GROUP hrSWRunPerfGroup
          DESCRIPTION
              "The Running Software Performance Group.
              Implementation of this group is at the discretion
              of the implementor."

      GROUP hrSWInstalledGroup
          DESCRIPTION
              "The Installed Software Group.
              Implementation of this group is at the discretion
              of the implementor."

    ::= { hrMIBCompliances 1 }

    hrSystemGroup OBJECT-GROUP
        OBJECTS {
            hrSystemUptime, hrSystemDate,
            hrSystemInitialLoadDevice,
            hrSystemInitialLoadParameters,
            hrSystemNumUsers, hrSystemProcesses,
            hrSystemMaxProcesses
        }
        STATUS current
        DESCRIPTION
            "The Host Resources System Group."
        ::= { hrMIBGroups 1 }

    hrStorageGroup OBJECT-GROUP
        OBJECTS {
            hrMemorySize, hrStorageIndex, hrStorageType,
            hrStorageDescr, hrStorageAllocationUnits,
            hrStorageSize, hrStorageUsed,
            hrStorageAllocationFailures
        }
        STATUS current
        DESCRIPTION
            "The Host Resources Storage Group."
        ::= { hrMIBGroups 2 }

    hrDeviceGroup OBJECT-GROUP
        OBJECTS {
            hrDeviceIndex, hrDeviceType, hrDeviceDescr,
            hrDeviceID, hrDeviceStatus, hrDeviceErrors,
            hrProcessorFrwID, hrProcessorLoad,
            hrNetworkIfIndex, hrPrinterStatus,
            hrPrinterDetectedErrorState,
            hrDiskStorageAccess, hrDiskStorageMedia,
            hrDiskStorageRemoveble, hrDiskStorageCapacity,
            hrPartitionIndex, hrPartitionLabel,
            hrPartitionID, hrPartitionSize,
            hrPartitionFSIndex, hrFSIndex, hrFSMountPoint,
            hrFSRemoteMountPoint, hrFSType, hrFSAccess,
            hrFSBootable, hrFSStorageIndex,
            hrFSLastFullBackupDate,
            hrFSLastPartialBackupDate
        }
        STATUS current
        DESCRIPTION
            "The Host Resources Device Group."
        ::= { hrMIBGroups 3 }

    hrSWRunGroup OBJECT-GROUP
        OBJECTS {
            hrSWOSIndex, hrSWRunIndex, hrSWRunName,
            hrSWRunID, hrSWRunPath, hrSWRunParameters,
            hrSWRunType, hrSWRunStatus
        }
        STATUS current
        DESCRIPTION
            "The Host Resources Running Software Group."
        ::= { hrMIBGroups 4 }

    hrSWRunPerfGroup OBJECT-GROUP
        OBJECTS { hrSWRunPerfCPU, hrSWRunPerfMem }
        STATUS current
        DESCRIPTION
            "The Host Resources Running Software
            Performance Group."
        ::= { hrMIBGroups 5 }

    hrSWInstalledGroup OBJECT-GROUP
        OBJECTS {
            hrSWInstalledLastChange,
            hrSWInstalledLastUpdateTime,
            hrSWInstalledIndex, hrSWInstalledName,
            hrSWInstalledID, hrSWInstalledType,
            hrSWInstalledDate
        }
        STATUS current
        DESCRIPTION
            "The Host Resources Installed Software Group."
        ::= { hrMIBGroups 6 }

END


HOST-RESOURCES-TYPES DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-IDENTITY        FROM SNMPv2-SMI
    hrMIBAdminInfo, hrStorage, hrDevice     FROM HOST-RESOURCES-MIB;

hostResourcesTypesModule MODULE-IDENTITY
    LAST-UPDATED "200003060000Z"    -- 6 March, 2000
    ORGANIZATION "IETF Host Resources MIB Working Group"
    CONTACT-INFO
        "Steve Waldbusser
        Postal: Lucent Technologies, Inc.
                1213 Innsbruck Dr.
                Sunnyvale, CA 94089
                USA
        Phone: 650-318-1251
        Fax:   650-318-1633
        Email: waldbusser@ins.com

        In addition, the Host Resources MIB mailing list is dedicated
        to discussion of this MIB. To join the mailing list, send a
        request message to hostmib-request@andrew.cmu.edu. The mailing
        list address is hostmib@andrew.cmu.edu."
    DESCRIPTION
        "This MIB module registers type definitions for
        storage types, device types, and file system types.

        After the initial revision, this module will be
        maintained by IANA."
    REVISION "200003060000Z"    -- 6 March 2000
    DESCRIPTION
        "The original version of this module, published as RFC
        2790."
    ::= { hrMIBAdminInfo 4 }

-- Registrations for some storage types, for use with hrStorageType
hrStorageTypes          OBJECT IDENTIFIER ::= { hrStorage 1 }

hrStorageOther OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used when no other defined
        type is appropriate."
    ::= { hrStorageTypes 1 }

hrStorageRam OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for RAM."
    ::= { hrStorageTypes 2 }

hrStorageVirtualMemory OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for virtual memory,
        temporary storage of swapped or paged memory."
    ::= { hrStorageTypes 3 }

hrStorageFixedDisk OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for non-removable
        rigid rotating magnetic storage devices."
    ::= { hrStorageTypes 4 }

hrStorageRemovableDisk OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for removable rigid
        rotating magnetic storage devices."
    ::= { hrStorageTypes 5 }

hrStorageFloppyDisk OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for non-rigid rotating
        magnetic storage devices."
    ::= { hrStorageTypes 6 }

hrStorageCompactDisc OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for read-only rotating
        optical storage devices."
    ::= { hrStorageTypes 7 }

hrStorageRamDisk OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for a file system that
        is stored in RAM."
    ::= { hrStorageTypes 8 }

hrStorageFlashMemory OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for flash memory."
    ::= { hrStorageTypes 9 }

hrStorageNetworkDisk OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The storage type identifier used for a
        networked file system."
    ::= { hrStorageTypes 10 }

-- Registrations for some device types, for use with hrDeviceType
hrDeviceTypes             OBJECT IDENTIFIER ::= { hrDevice 1 }

hrDeviceOther OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used when no other defined
        type is appropriate."
    ::= { hrDeviceTypes 1 }

hrDeviceUnknown OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used when the device type is
        unknown."
    ::= { hrDeviceTypes 2 }

hrDeviceProcessor OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a CPU."
    ::= { hrDeviceTypes 3 }

hrDeviceNetwork OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a network interface."
    ::= { hrDeviceTypes 4 }

hrDevicePrinter OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a printer."
    ::= { hrDeviceTypes 5 }

hrDeviceDiskStorage OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a disk drive."
    ::= { hrDeviceTypes 6 }

hrDeviceVideo OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a video device."
    ::= { hrDeviceTypes 10 }

hrDeviceAudio OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for an audio device."
    ::= { hrDeviceTypes 11 }

hrDeviceCoprocessor OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a co-processor."
    ::= { hrDeviceTypes 12 }

hrDeviceKeyboard OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a keyboard device."
    ::= { hrDeviceTypes 13 }

hrDeviceModem OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a modem."
    ::= { hrDeviceTypes 14 }

hrDeviceParallelPort OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a parallel port."
    ::= { hrDeviceTypes 15 }

hrDevicePointing OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a pointing device
        (e.g., a mouse)."
    ::= { hrDeviceTypes 16 }

hrDeviceSerialPort OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a serial port."
    ::= { hrDeviceTypes 17 }

hrDeviceTape OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a tape storage device."
    ::= { hrDeviceTypes 18 }

hrDeviceClock OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a clock device."
    ::= { hrDeviceTypes 19 }

hrDeviceVolatileMemory OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a volatile memory
        storage device."
    ::= { hrDeviceTypes 20 }

hrDeviceNonVolatileMemory OBJECT-IDENTITY
    STATUS current
    DESCRIPTION
        "The device type identifier used for a non-volatile memory
        storage device."
    ::= { hrDeviceTypes 21 }

-- Registrations for some popular File System types,
-- for use with hrFSType.
hrFSTypes               OBJECT IDENTIFIER ::= { hrDevice 9 }

hrFSOther OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used when no other
        defined type is appropriate."
    ::= { hrFSTypes 1 }

hrFSUnknown OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used when the type of
        file system is unknown."
    ::= { hrFSTypes 2 }

hrFSBerkeleyFFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Berkeley Fast File System."
    ::= { hrFSTypes 3 }

hrFSSys5FS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        System V File System."
    ::= { hrFSTypes 4 }

hrFSFat OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for
        DOS's FAT file system."
    ::= { hrFSTypes 5 }

hrFSHPFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for OS/2's
        High Performance File System."
    ::= { hrFSTypes 6 }

hrFSHFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Macintosh Hierarchical File System."
    ::= { hrFSTypes 7 }

hrFSMFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Macintosh File System."
    ::= { hrFSTypes 8 }

hrFSNTFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Windows NT File System."
    ::= { hrFSTypes 9 }

hrFSVNode OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        VNode File System."
    ::= { hrFSTypes 10 }

hrFSJournaled OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Journaled File System."
    ::= { hrFSTypes 11 }

hrFSiso9660 OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        ISO 9660 File System for CD's."
    ::= { hrFSTypes 12 }

hrFSRockRidge OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        RockRidge File System for CD's."
    ::= { hrFSTypes 13 }

hrFSNFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        NFS File System."
    ::= { hrFSTypes 14 }

hrFSNetware OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Netware File System."
    ::= { hrFSTypes 15 }

hrFSAFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Andrew File System."
    ::= { hrFSTypes 16 }

hrFSDFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        OSF DCE Distributed File System."
    ::= { hrFSTypes 17 }

hrFSAppleshare OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        AppleShare File System."
    ::= { hrFSTypes 18 }

hrFSRFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        RFS File System."
    ::= { hrFSTypes 19 }

hrFSDGCFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Data General DGCFS."
    ::= { hrFSTypes 20 }

hrFSBFS OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        SVR4 Boot File System."
    ::= { hrFSTypes 21 }

hrFSFAT32 OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Windows FAT32 File System."
    ::= { hrFSTypes 22 }

hrFSLinuxExt2 OBJECT-IDENTITY
    STATUS  current
    DESCRIPTION
        "The file system type identifier used for the
        Linux EXT2 File System."
    ::= { hrFSTypes 23 }

END


   IANAifType-MIB DEFINITIONS ::= BEGIN

   IMPORTS
       MODULE-IDENTITY,
       mib-2				   FROM SNMPv2-SMI
       TEXTUAL-CONVENTION                  FROM SNMPv2-TC;

   ianaifType MODULE-IDENTITY
       LAST-UPDATED "9910081430Z"  --  October 8, 1999
       ORGANIZATION "IANA"
       CONTACT-INFO

                  "        Internet Assigned Numbers Authority

                   Postal: ICANN
                           4676 Admiralty Way, Suite 330
               Marina del Rey, CA 90292

                   Tel:    +1 310 823 9358 x20
                   E-Mail: iana@iana.org"
       DESCRIPTION
               "The MIB module which defines the IANAifType textual
               convention, and thus the enumerated values of the
               ifType object defined in MIB-II's ifTable."
       REVISION "9910081430Z"  -- August 31, 1999
       DESCRIPTION
               "Updated to include new name assignments up to cnr(85).
               This is the first version available via the WWW."
       ::= { mib-2 30 }

   IANAifType ::= TEXTUAL-CONVENTION
       STATUS       current
       DESCRIPTION
               "This data type is used as the syntax of the ifType
               object in the (updated) definition of MIB-II's
               ifTable.

               The definition of this textual convention with the
               addition of newly assigned values is published
               periodically by the IANA, in either the Assigned
               Numbers RFC, or some derivative of it specific to
               Internet Network Management number assignments.  (The
               latest arrangements can be obtained by contacting the
               IANA.)

               Requests for new values should be made to IANA via
               email (iana@iana.org).

               The relationship between the assignment of ifType
               values and of OIDs to particular media-specific MIBs
               is solely the purview of IANA and is subject to change
               without notice.  Quite often, a media-specific MIB's
               OID-subtree assignment within MIB-II's 'transmission'
               subtree will be the same as its ifType value.
               However, in some circumstances this will not be the
               case, and implementors must not pre-assume any
               specific relationship between ifType values and
               transmission subtree OIDs."
       SYNTAX  INTEGER {
                   other(1),          -- none of the following
                   regular1822(2),
                   hdh1822(3),
                   ddnX25(4),
                   rfc877x25(5),
                   ethernetCsmacd(6),
                   iso88023Csmacd(7),
                   iso88024TokenBus(8),
                   iso88025TokenRing(9),
                   iso88026Man(10),
                   starLan(11),
                   proteon10Mbit(12),
                   proteon80Mbit(13),
                   hyperchannel(14),
                   fddi(15),
                   lapb(16),
                   sdlc(17),
                   ds1(18),            -- DS1-MIB
                   e1(19),             -- Obsolete see DS1-MIB
                   basicISDN(20),
                   primaryISDN(21),
                   propPointToPointSerial(22), -- proprietary serial
                   ppp(23),
                   softwareLoopback(24),
                   eon(25),            -- CLNP over IP
                   ethernet3Mbit(26),
                   nsip(27),           -- XNS over IP
                   slip(28),           -- generic SLIP
                   ultra(29),          -- ULTRA technologies
                   ds3(30),            -- DS3-MIB
                   sip(31),            -- SMDS, coffee
                   frameRelay(32),     -- DTE only.
                   rs232(33),
                   para(34),           -- parallel-port
                   arcnet(35),         -- arcnet
                   arcnetPlus(36),     -- arcnet plus
                   atm(37),            -- ATM cells
                   miox25(38),
                   sonet(39),          -- SONET or SDH
                   x25ple(40),
                   iso88022llc(41),
                   localTalk(42),
                   smdsDxi(43),
                   frameRelayService(44),  -- FRNETSERV-MIB
                   v35(45),
                   hssi(46),
                   hippi(47),
                   modem(48),          -- Generic modem
                   aal5(49),           -- AAL5 over ATM
                   sonetPath(50),
                   sonetVT(51),
                   smdsIcip(52),       -- SMDS InterCarrier Interface
                   propVirtual(53),    -- proprietary virtual/internal
                   propMultiplexor(54),-- proprietary multiplexing
                   ieee80212(55),      -- 100BaseVG
                   fibreChannel(56),   -- Fibre Channel
                   hippiInterface(57), -- HIPPI interfaces
                   frameRelayInterconnect(58), -- Obsolete use either
                                       -- frameRelay(32) or
                                       -- frameRelayService(44).
                   aflane8023(59),     -- ATM Emulated LAN for 802.3
                   aflane8025(60),     -- ATM Emulated LAN for 802.5
                   cctEmul(61),        -- ATM Emulated circuit
                   fastEther(62),      -- Fast Ethernet (100BaseT)
                   isdn(63),           -- ISDN and X.25
                   v11(64),            -- CCITT V.11/X.21
                   v36(65),            -- CCITT V.36
                   g703at64k(66),      -- CCITT G703 at 64Kbps
                   g703at2mb(67),      -- Obsolete see DS1-MIB
                   qllc(68),           -- SNA QLLC
                   fastEtherFX(69),    -- Fast Ethernet (100BaseFX)
                   channel(70),        -- channel
                   ieee80211(71),      -- radio spread spectrum
               ibm370parChan(72),  -- IBM System 360/370 OEMI Channel
                   escon(73),          -- IBM Enterprise Systems Connection
                   dlsw(74),           -- Data Link Switching
                   isdns(75),          -- ISDN S/T interface
                   isdnu(76),          -- ISDN U interface
                   lapd(77),           -- Link Access Protocol D
                   ipSwitch(78),       -- IP Switching Objects
                   rsrb(79),           -- Remote Source Route Bridging
                   atmLogical(80),     -- ATM Logical Port
                   ds0(81),            -- Digital Signal Level 0
                   ds0Bundle(82),      -- group of ds0s on the same ds1
                   bsc(83),            -- Bisynchronous Protocol
                   async(84),          -- Asynchronous Protocol
                   cnr(85),            -- Combat Net Radio
                   iso88025Dtr(86),    -- ISO 802.5r DTR
                   eplrs(87),          -- Ext Pos Loc Report Sys
                   arap(88),           -- Appletalk Remote Access Protocol
                   propCnls(89),       -- Proprietary Connectionless Protocol
                   hostPad(90),        -- CCITT-ITU X.29 PAD Protocol
                   termPad(91),        -- CCITT-ITU X.3 PAD Facility
                   frameRelayMPI(92),  -- Multiproto Interconnect over FR
                   x213(93),           -- CCITT-ITU X213
                   adsl(94),           -- Asymmetric Digital Subscriber Loop
                   radsl(95),          -- Rate-Adapt. Digital Subscriber Loop
                   sdsl(96),           -- Symmetric Digital Subscriber Loop
                   vdsl(97),           -- Very H-Speed Digital Subscrib. Loop
                   iso88025CRFPInt(98), -- ISO 802.5 CRFP
                   myrinet(99),        -- Myricom Myrinet
                   voiceEM(100),       -- voice recEive and transMit
                   voiceFXO(101),      -- voice Foreign Exchange Office
                   voiceFXS(102),      -- voice Foreign Exchange Station
                   voiceEncap(103),    -- voice encapsulation
                   voiceOverIp(104),   -- voice over IP encapsulation
                   atmDxi(105),        -- ATM DXI
                   atmFuni(106),       -- ATM FUNI
           atmIma (107),       -- ATM IMA
                   pppMultilinkBundle(108), -- PPP Multilink Bundle
                   ipOverCdlc (109),   -- IBM ipOverCdlc
           ipOverClaw (110),   -- IBM Common Link Access to Workstn
                   stackToStack (111), -- IBM stackToStack
                   virtualIpAddress (112), -- IBM VIPA
           mpc (113),          -- IBM multi-protocol channel support
           ipOverAtm (114),    -- IBM ipOverAtm
           iso88025Fiber (115), -- ISO 802.5j Fiber Token Ring
           tdlc (116),	       -- IBM twinaxial data link control
           gigabitEthernet (117), -- Gigabit Ethernet
           hdlc (118),         -- HDLC
           lapf (119),	       -- LAP F
           v37 (120),	       -- V.37
           x25mlp (121),       -- Multi-Link Protocol
           x25huntGroup (122), -- X25 Hunt Group
           trasnpHdlc (123),   -- Transp HDLC
           interleave (124),   -- Interleave channel
           fast (125),         -- Fast channel
           ip (126),	       -- IP (for APPN HPR in IP networks)
           docsCableMaclayer (127),  -- CATV Mac Layer
           docsCableDownstream (128), -- CATV Downstream interface
           docsCableUpstream (129),  -- CATV Upstream interface
           a12MppSwitch (130), -- Avalon Parallel Processor
           tunnel (131),       -- Encapsulation interface
           coffee (132),       -- coffee pot
           ces (133),          -- Circuit Emulation Service
           atmSubInterface (134), -- ATM Sub Interface
           l2vlan (135),       -- Layer 2 Virtual LAN using 802.1Q
           l3ipvlan (136),     -- Layer 3 Virtual LAN using IP
           l3ipxvlan (137),    -- Layer 3 Virtual LAN using IPX
           digitalPowerline (138), -- IP over Power Lines
           mediaMailOverIp (139), -- Multimedia Mail over IP
           dtm (140),        -- Dynamic syncronous Transfer Mode
           dcn (141),    -- Data Communications Network
           ipForward (142),    -- IP Forwarding Interface
           msdsl (143),       -- Multi-rate Symmetric DSL
           ieee1394 (144), -- IEEE1394 High Performance Serial Bus
           if-gsn (145),       --   HIPPI-6400
           dvbRccMacLayer (146), -- DVB-RCC MAC Layer
           dvbRccDownstream (147),  -- DVB-RCC Downstream Channel
           dvbRccUpstream (148),  -- DVB-RCC Upstream Channel
           atmVirtual (149),   -- ATM Virtual Interface
           mplsTunnel (150),   -- MPLS Tunnel Virtual Interface
           srp (151),	-- Spatial Reuse Protocol
           voiceOverAtm (152),  -- Voice Over ATM
           voiceOverFrameRelay (153),   -- Voice Over Frame Relay
           idsl (154),		-- Digital Subscriber Loop over ISDN
           compositeLink (155),  -- Avici Composite Link Interface
           ss7SigLink (156),     -- SS7 Signaling Link
           propWirelessP2P (157),  --  Prop. P2P wireless interface
           frForward (158),    -- Frame Forward Interface
           rfc1483 (159),	-- Multiprotocol over ATM AAL5
           usb (160),		-- USB Interface
           ieee8023adLag(161)  -- IEEE 802.3ad Link Aggregate
}

   END


IF-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, Counter32, Gauge32, Counter64,
    Integer32, TimeTicks, mib-2,
    NOTIFICATION-TYPE                        FROM SNMPv2-SMI
    TEXTUAL-CONVENTION, DisplayString,
    PhysAddress, TruthValue, RowStatus,
    TimeStamp, AutonomousType, TestAndIncr   FROM SNMPv2-TC
    MODULE-COMPLIANCE, OBJECT-GROUP          FROM SNMPv2-CONF
    snmpTraps                                FROM SNMPv2-MIB
    IANAifType                               FROM IANAifType-MIB;

ifMIB MODULE-IDENTITY
    LAST-UPDATED "9611031355Z"
    ORGANIZATION "IETF Interfaces MIB Working Group"
    CONTACT-INFO
        "   Keith McCloghrie
        Cisco Systems, Inc.
        170 West Tasman Drive
        San Jose, CA  95134-1706
        US

        408-526-5260
        kzm@cisco.com"
    DESCRIPTION
        "The MIB module to describe generic objects for
        network interface sub-layers.  This MIB is an updated
        version of MIB-II's ifTable, and incorporates the
        extensions defined in RFC 1229."
    REVISION      "9602282155Z"
    DESCRIPTION
        "Revisions made by the Interfaces MIB WG."
    REVISION      "9311082155Z"
    DESCRIPTION
        "Initial revision, published as part of RFC 1573."
    ::= { mib-2 31 }

ifMIBObjects OBJECT IDENTIFIER ::= { ifMIB 1 }

interfaces   OBJECT IDENTIFIER ::= { mib-2 2 }

OwnerString ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "255a"
    STATUS       current
    DESCRIPTION
        "This data type is used to model an administratively
        assigned name of the owner of a resource.  This
        information is taken from the NVT ASCII character set.
        It is suggested that this name contain one or more of
        the following: ASCII form of the manager station's
        transport address, management station name (e.g.,
        domain name), network management personnel's name,
        location, or phone number.  In some cases the agent
        itself will be the owner of an entry.  In these cases,
        this string shall be set to a string starting with
        'agent'."
    SYNTAX       OCTET STRING (SIZE(0..255))

-- InterfaceIndex contains the semantics of ifIndex and
-- should be used for any objects defined on other mib
-- modules that need these semantics.

InterfaceIndex ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "d"
    STATUS       current
    DESCRIPTION
        "A unique value, greater than zero, for each interface
        or interface sub-layer in the managed system.  It is
        recommended that values are assigned contiguously
        starting from 1.  The value for each interface sub-
        layer must remain constant at least from one re-
        initialization of the entity's network management
        system to the next re-initialization."
    SYNTAX       Integer32 (1..2147483647)

InterfaceIndexOrZero ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "d"
    STATUS       current
    DESCRIPTION
        "This textual convention is an extension of the
        InterfaceIndex convention.  The latter defines a
        greater than zero value used to identify an interface
        or interface sub-layer in the managed system.  This
        extension permits the additional value of zero.  the
        value zero is object-specific and must therefore be
        defined as part of the description of any object which
        uses this syntax.  Examples of the usage of zero might
        include situations where interface was unknown, or
        when none or all interfaces need to be referenced."
    SYNTAX       Integer32 (0..2147483647)

ifNumber  OBJECT-TYPE
    SYNTAX      Integer32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of network interfaces (regardless of their
        current state) present on this system."
    ::= { interfaces 1 }

ifTableLastChange  OBJECT-TYPE
    SYNTAX      TimeTicks
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of sysUpTime at the time of the last
        creation or deletion of an entry in the ifTable.  If
        the number of entries has been unchanged since the
        last re-initialization of the local network management
        subsystem, then this object contains a zero value."
    ::= { ifMIBObjects 5 }

-- the Interfaces table

-- The Interfaces table contains information on the entity's
-- interfaces.  Each sub-layer below the internetwork-layer
-- of a network interface is considered to be an interface.

ifTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF IfEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "A list of interface entries.  The number of entries
        is given by the value of ifNumber."
    ::= { interfaces 2 }

ifEntry OBJECT-TYPE
    SYNTAX      IfEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry containing management information applicable
        to a particular interface."
    INDEX   { ifIndex }
    ::= { ifTable 1 }

IfEntry ::=
    SEQUENCE {
    ifIndex                 InterfaceIndex,
    ifDescr                 DisplayString,
    ifType                  IANAifType,
    ifMtu                   Integer32,
    ifSpeed                 Gauge32,
    ifPhysAddress           PhysAddress,
    ifAdminStatus           INTEGER,
    ifOperStatus            INTEGER,
    ifLastChange            TimeTicks,
    ifInOctets              Counter32,
    ifInUcastPkts           Counter32,
    ifInNUcastPkts          Counter32,  -- deprecated
    ifInDiscards            Counter32,
    ifInErrors              Counter32,
    ifInUnknownProtos       Counter32,
    ifOutOctets             Counter32,
    ifOutUcastPkts          Counter32,
    ifOutNUcastPkts         Counter32,  -- deprecated
    ifOutDiscards           Counter32,
    ifOutErrors             Counter32,
    ifOutQLen               Gauge32,    -- deprecated
    ifSpecific              OBJECT IDENTIFIER -- deprecated
    }

ifIndex OBJECT-TYPE
    SYNTAX      InterfaceIndex
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "A unique value, greater than zero, for each
        interface.  It is recommended that values are assigned
        contiguously starting from 1.  The value for each
        interface sub-layer must remain constant at least from
        one re-initialization of the entity's network
        management system to the next re-initialization."
    ::= { ifEntry 1 }

ifDescr OBJECT-TYPE
    SYNTAX      DisplayString (SIZE (0..255))
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "A textual string containing information about the
        interface.  This string should include the name of the
        manufacturer, the product name and the version of the
        interface hardware/software."
    ::= { ifEntry 2 }

ifType OBJECT-TYPE
    SYNTAX      IANAifType
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The type of interface.  Additional values for ifType
        are assigned by the Internet Assigned Numbers
        Authority (IANA), through updating the syntax of the
        IANAifType textual convention."
    ::= { ifEntry 3 }

ifMtu OBJECT-TYPE
    SYNTAX      Integer32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The size of the largest packet which can be
        sent/received on the interface, specified in octets.
        For interfaces that are used for transmitting network
        datagrams, this is the size of the largest network
        datagram that can be sent on the interface."
    ::= { ifEntry 4 }

ifSpeed OBJECT-TYPE
    SYNTAX      Gauge32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "An estimate of the interface's current bandwidth in
        bits per second.  For interfaces which do not vary in
        bandwidth or for those where no accurate estimation
        can be made, this object should contain the nominal
        bandwidth.  If the bandwidth of the interface is
        greater than the maximum value reportable by this
        object then this object should report its maximum
        value (4,294,967,295) and ifHighSpeed must be used to
        report the interace's speed.  For a sub-layer which
        has no concept of bandwidth, this object should be
        zero."
    ::= { ifEntry 5 }

ifPhysAddress OBJECT-TYPE
    SYNTAX      PhysAddress
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The interface's address at its protocol sub-layer.
        For example, for an 802.x interface, this object
        normally contains a MAC address.  The interface's
        media-specific MIB must define the bit and byte
        ordering and the format of the value of this object.
        For interfaces which do not have such an address
        (e.g., a serial line), this object should contain an
        octet string of zero length."
    ::= { ifEntry 6 }

ifAdminStatus OBJECT-TYPE
    SYNTAX  INTEGER {
        up(1),       -- ready to pass packets
        down(2),
        testing(3)   -- in some test mode
        }
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "The desired state of the interface.  The testing(3)
        state indicates that no operational packets can be
        passed.  When a managed system initializes, all
        interfaces start with ifAdminStatus in the down(2)
        state.  As a result of either explicit management
        action or per configuration information retained by
        the managed system, ifAdminStatus is then changed to
        either the up(1) or testing(3) states (or remains in
        the down(2) state)."
    ::= { ifEntry 7 }

ifOperStatus OBJECT-TYPE
    SYNTAX  INTEGER {
        up(1),        -- ready to pass packets
        down(2),
        testing(3),   -- in some test mode
        unknown(4),   -- status can not be determined
                  -- for some reason.
        dormant(5),
        notPresent(6),    -- some component is missing
        lowerLayerDown(7) -- down due to state of
                  -- lower-layer interface(s)
        }
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The current operational state of the interface.  The
        testing(3) state indicates that no operational packets
        can be passed.  If ifAdminStatus is down(2) then
        ifOperStatus should be down(2).  If ifAdminStatus is
        changed to up(1) then ifOperStatus should change to
        up(1) if the interface is ready to transmit and
        receive network traffic; it should change to
        dormant(5) if the interface is waiting for external
        actions (such as a serial line waiting for an incoming
        connection); it should remain in the down(2) state if
        and only if there is a fault that prevents it from
        going to the up(1) state; it should remain in the
        notPresent(6) state if the interface has missing
        (typically, hardware) components."
    ::= { ifEntry 8 }

ifLastChange OBJECT-TYPE
    SYNTAX      TimeTicks
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of sysUpTime at the time the interface
        entered its current operational state.  If the current
        state was entered prior to the last re-initialization
        of the local network management subsystem, then this
        object contains a zero value."
    ::= { ifEntry 9 }

ifInOctets OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of octets received on the interface,
        including framing characters.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 10 }

ifInUcastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were not addressed to a
        multicast or broadcast address at this sub-layer.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 11 }

ifInNUcastPkts OBJECT-TYPE
    SYNTAX  Counter32
    MAX-ACCESS  read-only
    STATUS      deprecated
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were addressed to a
        multicast or broadcast address at this sub-layer.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime.

        This object is deprecated in favour of
        ifInMulticastPkts and ifInBroadcastPkts."
    ::= { ifEntry 12 }

ifInDiscards OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of inbound packets which were chosen to be
        discarded even though no errors had been detected to
        prevent their being deliverable to a higher-layer
        protocol.  One possible reason for discarding such a
        packet could be to free up buffer space.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 13 }

ifInErrors OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "For packet-oriented interfaces, the number of inbound
        packets that contained errors preventing them from
        being deliverable to a higher-layer protocol.  For
        character-oriented or fixed-length interfaces, the
        number of inbound transmission units that contained
        errors preventing them from being deliverable to a
        higher-layer protocol.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 14 }

ifInUnknownProtos OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "For packet-oriented interfaces, the number of packets
        received via the interface which were discarded
        because of an unknown or unsupported protocol.  For
        character-oriented or fixed-length interfaces that
        support protocol multiplexing the number of
        transmission units received via the interface which
        were discarded because of an unknown or unsupported
        protocol.  For any interface that does not support
        protocol multiplexing, this counter will always be 0.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 15 }

ifOutOctets OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of octets transmitted out of the
        interface, including framing characters.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 16 }

ifOutUcastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were not
        addressed to a multicast or broadcast address at this
        sub-layer, including those that were discarded or not
        sent.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 17 }

ifOutNUcastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      deprecated
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were
        addressed to a multicast or broadcast address at this
        sub-layer, including those that were discarded or not
        sent.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime.
        This object is deprecated in favour of
        ifOutMulticastPkts and ifOutBroadcastPkts."
    ::= { ifEntry 18 }

ifOutDiscards OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of outbound packets which were chosen to
        be discarded even though no errors had been detected
        to prevent their being transmitted.  One possible
        reason for discarding such a packet could be to free
        up buffer space.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 19 }

ifOutErrors OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "For packet-oriented interfaces, the number of
        outbound packets that could not be transmitted because
        of errors.  For character-oriented or fixed-length
        interfaces, the number of outbound transmission units
        that could not be transmitted because of errors.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifEntry 20 }

ifOutQLen OBJECT-TYPE
    SYNTAX      Gauge32
    MAX-ACCESS  read-only
    STATUS      deprecated
    DESCRIPTION
        "The length of the output packet queue (in packets)."
    ::= { ifEntry 21 }

ifSpecific OBJECT-TYPE
    SYNTAX      OBJECT IDENTIFIER
    MAX-ACCESS  read-only
    STATUS      deprecated
    DESCRIPTION
        "A reference to MIB definitions specific to the
        particular media being used to realize the interface.
        It is recommended that this value point to an instance
        of a MIB object in the media-specific MIB, i.e., that
        this object have the semantics associated with the
        InstancePointer textual convention defined in RFC
        1903.  In fact, it is recommended that the media-
        specific MIB specify what value ifSpecific should/can
        take for values of ifType.  If no MIB definitions
        specific to the particular media are available, the
        value should be set to the OBJECT IDENTIFIER { 0 0 }."
    ::= { ifEntry 22 }

--
--   Extension to the interface table
--
-- This table replaces the ifExtnsTable table.
--

ifXTable        OBJECT-TYPE
    SYNTAX      SEQUENCE OF IfXEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "A list of interface entries.  The number of entries
        is given by the value of ifNumber.  This table
        contains additional objects for the interface table."
    ::= { ifMIBObjects 1 }

ifXEntry        OBJECT-TYPE
    SYNTAX      IfXEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry containing additional management information
        applicable to a particular interface."
    AUGMENTS    { ifEntry }
    ::= { ifXTable 1 }

IfXEntry ::=
    SEQUENCE {
    ifName                  DisplayString,
    ifInMulticastPkts       Counter32,
    ifInBroadcastPkts       Counter32,
    ifOutMulticastPkts      Counter32,
    ifOutBroadcastPkts      Counter32,
    ifHCInOctets            Counter64,
    ifHCInUcastPkts         Counter64,
    ifHCInMulticastPkts     Counter64,
    ifHCInBroadcastPkts     Counter64,
    ifHCOutOctets           Counter64,
    ifHCOutUcastPkts        Counter64,
    ifHCOutMulticastPkts    Counter64,
    ifHCOutBroadcastPkts    Counter64,
    ifLinkUpDownTrapEnable  INTEGER,
    ifHighSpeed             Gauge32,
    ifPromiscuousMode       TruthValue,
    ifConnectorPresent      TruthValue,
    ifAlias                 DisplayString,
    ifCounterDiscontinuityTime TimeStamp
    }

ifName OBJECT-TYPE
    SYNTAX      DisplayString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The textual name of the interface.  The value of this
        object should be the name of the interface as assigned
        by the local device and should be suitable for use in
        commands entered at the device's `console'.  This
        might be a text name, such as `le0' or a simple port
        number, such as `1', depending on the interface naming
        syntax of the device.  If several entries in the
        ifTable together represent a single interface as named
        by the device, then each will have the same value of
        ifName.  Note that for an agent which responds to SNMP
        queries concerning an interface on some other
        (proxied) device, then the value of ifName for such an
        interface is the proxied device's local name for it.

        If there is no local name, or this object is otherwise
        not applicable, then this object contains a zero-
        length string."
    ::= { ifXEntry 1 }

ifInMulticastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were addressed to a
        multicast address at this sub-layer.  For a MAC layer
        protocol, this includes both Group and Functional
        addresses.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 2 }

ifInBroadcastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were addressed to a
        broadcast address at this sub-layer.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 3 }

ifOutMulticastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were
        addressed to a multicast address at this sub-layer,
        including those that were discarded or not sent.  For
        a MAC layer protocol, this includes both Group and
        Functional addresses.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 4 }

ifOutBroadcastPkts OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were
        addressed to a broadcast address at this sub-layer,
        including those that were discarded or not sent.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 5 }

--
-- High Capacity Counter objects.  These objects are all
-- 64 bit versions of the "basic" ifTable counters.  These
-- objects all have the same basic semantics as their 32-bit
-- counterparts, however, their syntax has been extended
-- to 64 bits.
--

ifHCInOctets OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of octets received on the interface,
        including framing characters.  This object is a 64-bit
        version of ifInOctets.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 6 }

ifHCInUcastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were not addressed to a
        multicast or broadcast address at this sub-layer.
        This object is a 64-bit version of ifInUcastPkts.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 7 }

ifHCInMulticastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were addressed to a
        multicast address at this sub-layer.  For a MAC layer
        protocol, this includes both Group and Functional
        addresses.  This object is a 64-bit version of
        ifInMulticastPkts.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 8 }

ifHCInBroadcastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of packets, delivered by this sub-layer to
        a higher (sub-)layer, which were addressed to a
        broadcast address at this sub-layer.  This object is a
        64-bit version of ifInBroadcastPkts.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 9 }

ifHCOutOctets OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of octets transmitted out of the
        interface, including framing characters.  This object
        is a 64-bit version of ifOutOctets.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 10 }

ifHCOutUcastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were not
        addressed to a multicast or broadcast address at this
        sub-layer, including those that were discarded or not
        sent.  This object is a 64-bit version of
        ifOutUcastPkts.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 11 }

ifHCOutMulticastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were
        addressed to a multicast address at this sub-layer,
        including those that were discarded or not sent.  For
        a MAC layer protocol, this includes both Group and
        Functional addresses.  This object is a 64-bit version
        of ifOutMulticastPkts.
        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 12 }

ifHCOutBroadcastPkts OBJECT-TYPE
    SYNTAX      Counter64
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The total number of packets that higher-level
        protocols requested be transmitted, and which were
        addressed to a broadcast address at this sub-layer,
        including those that were discarded or not sent.  This
        object is a 64-bit version of ifOutBroadcastPkts.

        Discontinuities in the value of this counter can occur
        at re-initialization of the management system, and at
        other times as indicated by the value of
        ifCounterDiscontinuityTime."
    ::= { ifXEntry 13 }

ifLinkUpDownTrapEnable  OBJECT-TYPE
    SYNTAX      INTEGER { enabled(1), disabled(2) }
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "Indicates whether linkUp/linkDown traps should be
        generated for this interface.

        By default, this object should have the value
        enabled(1) for interfaces which do not operate on
        'top' of any other interface (as defined in the
        ifStackTable), and disabled(2) otherwise."
    ::= { ifXEntry 14 }

ifHighSpeed OBJECT-TYPE
    SYNTAX      Gauge32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "An estimate of the interface's current bandwidth in
        units of 1,000,000 bits per second.  If this object
        reports a value of `n' then the speed of the interface
        is somewhere in the range of `n-500,000' to
        `n+499,999'.  For interfaces which do not vary in
        bandwidth or for those where no accurate estimation
        can be made, this object should contain the nominal
        bandwidth.  For a sub-layer which has no concept of
        bandwidth, this object should be zero."
    ::= { ifXEntry 15 }

ifPromiscuousMode  OBJECT-TYPE
    SYNTAX      TruthValue
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "This object has a value of false(2) if this interface
        only accepts packets/frames that are addressed to this
        station.  This object has a value of true(1) when the
        station accepts all packets/frames transmitted on the
        media.  The value true(1) is only legal on certain
        types of media.  If legal, setting this object to a
        value of true(1) may require the interface to be reset
        before becoming effective.

        The value of ifPromiscuousMode does not affect the
        reception of broadcast and multicast packets/frames by
        the interface."
    ::= { ifXEntry 16 }

ifConnectorPresent   OBJECT-TYPE
    SYNTAX      TruthValue
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "This object has the value 'true(1)' if the interface
        sublayer has a physical connector and the value
        'false(2)' otherwise."
    ::= { ifXEntry 17 }

ifAlias   OBJECT-TYPE
    SYNTAX      DisplayString (SIZE(0..64))
    MAX-ACCESS  read-write
    STATUS      current
    DESCRIPTION
        "This object is an 'alias' name for the interface as
        specified by a network manager, and provides a non-
        volatile 'handle' for the interface.

        On the first instantiation of an interface, the value
        of ifAlias associated with that interface is the
        zero-length string.  As and when a value is written
        into an instance of ifAlias through a network
        management set operation, then the agent must retain
        the supplied value in the ifAlias instance associated
        with the same interface for as long as that interface
        remains instantiated, including across all re-
        initializations/reboots of the network management
        system, including those which result in a change of
        the interface's ifIndex value.

        An example of the value which a network manager might
        store in this object for a WAN interface is the
        (Telco's) circuit number/identifier of the interface.

        Some agents may support write-access only for
        interfaces having particular values of ifType.  An
        agent which supports write access to this object is
        required to keep the value in non-volatile storage,
        but it may limit the length of new values depending on
        how much storage is already occupied by the current
        values for other interfaces."
    ::= { ifXEntry 18 }

ifCounterDiscontinuityTime OBJECT-TYPE
    SYNTAX      TimeStamp
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The value of sysUpTime on the most recent occasion at
        which any one or more of this interface's counters
        suffered a discontinuity.  The relevant counters are
        the specific instances associated with this interface
        of any Counter32 or Counter64 object contained in the
        ifTable or ifXTable.  If no such discontinuities have
        occurred since the last re-initialization of the local
        management subsystem, then this object contains a zero
        value."
    ::= { ifXEntry 19 }

--           The Interface Stack Group
--
-- Implementation of this group is mandatory for all systems
--

ifStackTable  OBJECT-TYPE
     SYNTAX        SEQUENCE OF IfStackEntry
     MAX-ACCESS    not-accessible
     STATUS        current
     DESCRIPTION
        "The table containing information on the relationships
        between the multiple sub-layers of network interfaces.
        In particular, it contains information on which sub-
        layers run 'on top of' which other sub-layers, where
        each sub-layer corresponds to a conceptual row in the
        ifTable.  For example, when the sub-layer with ifIndex
        value x runs over the sub-layer with ifIndex value y,
        then this table contains:

          ifStackStatus.x.y=active

        For each ifIndex value, I, which identifies an active
        interface, there are always at least two instantiated
        rows in this table associated with I.  For one of
        these rows, I is the value of ifStackHigherLayer; for
        the other, I is the value of ifStackLowerLayer.  (If I
        is not involved in multiplexing, then these are the
        only two rows associated with I.)

        For example, two rows exist even for an interface
        which has no others stacked on top or below it:

          ifStackStatus.0.x=active
          ifStackStatus.x.0=active "
     ::= { ifMIBObjects 2 }

ifStackEntry  OBJECT-TYPE
     SYNTAX        IfStackEntry
     MAX-ACCESS    not-accessible
     STATUS        current
     DESCRIPTION
        "Information on a particular relationship between two
        sub-layers, specifying that one sub-layer runs on
        'top' of the other sub-layer.  Each sub-layer
        corresponds to a conceptual row in the ifTable."
     INDEX { ifStackHigherLayer, ifStackLowerLayer }
     ::= { ifStackTable 1 }

IfStackEntry ::=
    SEQUENCE {
    ifStackHigherLayer  Integer32,
    ifStackLowerLayer   Integer32,
    ifStackStatus       RowStatus
     }

ifStackHigherLayer  OBJECT-TYPE
     SYNTAX        Integer32
     MAX-ACCESS    not-accessible
     STATUS        current
     DESCRIPTION
        "The value of ifIndex corresponding to the higher
        sub-layer of the relationship, i.e., the sub-layer
        which runs on 'top' of the sub-layer identified by the
        corresponding instance of ifStackLowerLayer.  If there
        is no higher sub-layer (below the internetwork layer),
        then this object has the value 0."
     ::= { ifStackEntry 1 }

ifStackLowerLayer  OBJECT-TYPE
     SYNTAX        Integer32
     MAX-ACCESS    not-accessible
     STATUS        current
     DESCRIPTION
        "The value of ifIndex corresponding to the lower sub-
        layer of the relationship, i.e., the sub-layer which
        runs 'below' the sub-layer identified by the
        corresponding instance of ifStackHigherLayer.  If
        there is no lower sub-layer, then this object has the
        value 0."
     ::= { ifStackEntry 2 }

ifStackStatus  OBJECT-TYPE
    SYNTAX         RowStatus
    MAX-ACCESS     read-create
    STATUS         current
    DESCRIPTION
        "The status of the relationship between two sub-
        layers.

        Changing the value of this object from 'active' to
        'notInService' or 'destroy' will likely have
        consequences up and down the interface stack.  Thus,
        write access to this object is likely to be
        inappropriate for some types of interfaces, and many
        implementations will choose not to support write-
        access for any type of interface."
    ::= { ifStackEntry 3 }

ifStackLastChange OBJECT-TYPE
    SYNTAX         TimeTicks
    MAX-ACCESS     read-only
    STATUS         current
    DESCRIPTION
        "The value of sysUpTime at the time of the last change
        of the (whole) interface stack.  A change of the
        interface stack is defined to be any creation,
        deletion, or change in value of any instance of
        ifStackStatus.  If the interface stack has been
        unchanged since the last re-initialization of the
        local network management subsystem, then this object
        contains a zero value."
    ::= { ifMIBObjects 6 }

--   Generic Receive Address Table
--
-- This group of objects is mandatory for all types of
-- interfaces which can receive packets/frames addressed to
-- more than one address.
--
-- This table replaces the ifExtnsRcvAddr table.  The main
-- difference is that this table makes use of the RowStatus
-- textual convention, while ifExtnsRcvAddr did not.

ifRcvAddressTable  OBJECT-TYPE
    SYNTAX      SEQUENCE OF IfRcvAddressEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "This table contains an entry for each address
        (broadcast, multicast, or uni-cast) for which the
        system will receive packets/frames on a particular
        interface, except as follows:

        - for an interface operating in promiscuous mode,
        entries are only required for those addresses for
        which the system would receive frames were it not
        operating in promiscuous mode.

        - for 802.5 functional addresses, only one entry is
        required, for the address which has the functional
        address bit ANDed with the bit mask of all functional
        addresses for which the interface will accept frames.

        A system is normally able to use any unicast address
        which corresponds to an entry in this table as a
        source address."
    ::= { ifMIBObjects 4 }

ifRcvAddressEntry  OBJECT-TYPE
    SYNTAX      IfRcvAddressEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "A list of objects identifying an address for which
        the system will accept packets/frames on the
        particular interface identified by the index value
        ifIndex."
    INDEX  { ifIndex, ifRcvAddressAddress }
    ::= { ifRcvAddressTable 1 }

IfRcvAddressEntry ::=
    SEQUENCE {
    ifRcvAddressAddress   PhysAddress,
    ifRcvAddressStatus    RowStatus,
    ifRcvAddressType      INTEGER
    }

ifRcvAddressAddress OBJECT-TYPE
    SYNTAX      PhysAddress
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An address for which the system will accept
        packets/frames on this entry's interface."

    ::= { ifRcvAddressEntry 1 }

ifRcvAddressStatus OBJECT-TYPE
    SYNTAX      RowStatus
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object is used to create and delete rows in the
        ifRcvAddressTable."
    ::= { ifRcvAddressEntry 2 }

ifRcvAddressType OBJECT-TYPE
    SYNTAX      INTEGER {
            other(1),
            volatile(2),
            nonVolatile(3)
        }

    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
        "This object has the value nonVolatile(3) for those
        entries in the table which are valid and will not be
        deleted by the next restart of the managed system.
        Entries having the value volatile(2) are valid and
        exist, but have not been saved, so that will not exist
        after the next restart of the managed system.  Entries
        having the value other(1) are valid and exist but are
        not classified as to whether they will continue to
        exist after the next restart."
    DEFVAL  { volatile }
    ::= { ifRcvAddressEntry 3 }

-- definition of interface-related traps.

linkDown NOTIFICATION-TYPE
    OBJECTS { ifIndex, ifAdminStatus, ifOperStatus }
    STATUS  current
    DESCRIPTION
        "A linkDown trap signifies that the SNMPv2 entity,
        acting in an agent role, has detected that the
        ifOperStatus object for one of its communication links
        is about to enter the down state from some other state
        (but not from the notPresent state).  This other state
        is indicated by the included value of ifOperStatus."
    ::= { snmpTraps 3 }

linkUp NOTIFICATION-TYPE
    OBJECTS { ifIndex, ifAdminStatus, ifOperStatus }
    STATUS  current
    DESCRIPTION
        "A linkDown trap signifies that the SNMPv2 entity,
        acting in an agent role, has detected that the
        ifOperStatus object for one of its communication links
        left the down state and transitioned into some other
        state (but not into the notPresent state).  This other
        state is indicated by the included value of
        ifOperStatus."
    ::= { snmpTraps 4 }

-- conformance information

ifConformance OBJECT IDENTIFIER ::= { ifMIB 2 }

ifGroups      OBJECT IDENTIFIER ::= { ifConformance 1 }
ifCompliances OBJECT IDENTIFIER ::= { ifConformance 2 }

-- compliance statements

ifCompliance2 MODULE-COMPLIANCE
    STATUS  current
    DESCRIPTION
        "The compliance statement for SNMPv2 entities which
        have network interfaces."

    MODULE  -- this module
    MANDATORY-GROUPS { ifGeneralInformationGroup, ifStackGroup2,
               ifCounterDiscontinuityGroup }

    GROUP       ifFixedLengthGroup
    DESCRIPTION
        "This group is mandatory for all network interfaces
        which are character-oriented or transmit data in
        fixed-length transmission units."

    GROUP       ifHCFixedLengthGroup
    DESCRIPTION
        "This group is mandatory only for those network
        interfaces which are character-oriented or transmit
        data in fixed-length transmission units, and for which
        the value of the corresponding instance of ifSpeed is
        greater than 20,000,000 bits/second."

    GROUP       ifPacketGroup
    DESCRIPTION
        "This group is mandatory for all network interfaces
        which are packet-oriented."

    GROUP       ifHCPacketGroup
    DESCRIPTION
        "This group is mandatory only for those network
        interfaces which are packet-oriented and for which the
        value of the corresponding instance of ifSpeed is
        greater than 650,000,000 bits/second."

    GROUP       ifRcvAddressGroup
    DESCRIPTION
        "The applicability of this group MUST be defined by
        the media-specific MIBs.  Media-specific MIBs must
        define the exact meaning, use, and semantics of the
        addresses in this group."

    OBJECT      ifLinkUpDownTrapEnable
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required."

    OBJECT      ifPromiscuousMode
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required."

    OBJECT      ifStackStatus
    SYNTAX      INTEGER { active(1) } -- subset of RowStatus
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required, and only one of the six
        enumerated values for the RowStatus textual convention
        need be supported, specifically: active(1)."

    OBJECT       ifAdminStatus
    SYNTAX       INTEGER { up(1), down(2) }
    MIN-ACCESS   read-only
    DESCRIPTION
        "Write access is not required, nor is support for the
        value testing(3)."

    OBJECT       ifAlias
    MIN-ACCESS   read-only
    DESCRIPTION
        "Write access is not required."

    ::= { ifCompliances 2 }

-- units of conformance

ifGeneralInformationGroup    OBJECT-GROUP
    OBJECTS { ifIndex, ifDescr, ifType, ifSpeed, ifPhysAddress,
          ifAdminStatus, ifOperStatus, ifLastChange,
          ifLinkUpDownTrapEnable, ifConnectorPresent,
          ifHighSpeed, ifName, ifNumber, ifAlias,
          ifTableLastChange }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        applicable to all network interfaces."
    ::= { ifGroups 10 }

-- the following five groups are mutually exclusive; at most
-- one of these groups is implemented for any interface

ifFixedLengthGroup    OBJECT-GROUP
    OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos,
          ifInErrors, ifOutErrors }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to non-high speed (non-high speed interfaces
        transmit and receive at speeds less than or equal to
        20,000,000 bits/second) character-oriented or fixed-
        length-transmission network interfaces."
    ::= { ifGroups 2 }

ifHCFixedLengthGroup    OBJECT-GROUP
    OBJECTS { ifHCInOctets, ifHCOutOctets,
          ifInOctets, ifOutOctets, ifInUnknownProtos,
          ifInErrors, ifOutErrors }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to high speed (greater than 20,000,000
        bits/second) character-oriented or fixed-length-
        transmission network interfaces."
    ::= { ifGroups 3 }

ifPacketGroup    OBJECT-GROUP
    OBJECTS { ifInOctets, ifOutOctets, ifInUnknownProtos,
          ifInErrors, ifOutErrors,
          ifMtu, ifInUcastPkts, ifInMulticastPkts,
          ifInBroadcastPkts, ifInDiscards,
          ifOutUcastPkts, ifOutMulticastPkts,
          ifOutBroadcastPkts, ifOutDiscards,
          ifPromiscuousMode }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to non-high speed (non-high speed interfaces
        transmit and receive at speeds less than or equal to
        20,000,000 bits/second) packet-oriented network
        interfaces."
    ::= { ifGroups 4 }

ifHCPacketGroup    OBJECT-GROUP
    OBJECTS { ifHCInOctets, ifHCOutOctets,
          ifInOctets, ifOutOctets, ifInUnknownProtos,
          ifInErrors, ifOutErrors,
          ifMtu, ifInUcastPkts, ifInMulticastPkts,
          ifInBroadcastPkts, ifInDiscards,
          ifOutUcastPkts, ifOutMulticastPkts,
          ifOutBroadcastPkts, ifOutDiscards,
          ifPromiscuousMode }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to high speed (greater than 20,000,000
        bits/second but less than or equal to 650,000,000
        bits/second) packet-oriented network interfaces."
    ::= { ifGroups 5 }

ifVHCPacketGroup    OBJECT-GROUP
    OBJECTS { ifHCInUcastPkts, ifHCInMulticastPkts,
          ifHCInBroadcastPkts, ifHCOutUcastPkts,
          ifHCOutMulticastPkts, ifHCOutBroadcastPkts,
          ifHCInOctets, ifHCOutOctets,
          ifInOctets, ifOutOctets, ifInUnknownProtos,
          ifInErrors, ifOutErrors,
          ifMtu, ifInUcastPkts, ifInMulticastPkts,
          ifInBroadcastPkts, ifInDiscards,
          ifOutUcastPkts, ifOutMulticastPkts,
          ifOutBroadcastPkts, ifOutDiscards,
          ifPromiscuousMode }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to higher speed (greater than 650,000,000
        bits/second) packet-oriented network interfaces."
    ::= { ifGroups 6 }

ifRcvAddressGroup    OBJECT-GROUP
    OBJECTS { ifRcvAddressStatus, ifRcvAddressType }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information on the
        multiple addresses which an interface receives."
    ::= { ifGroups 7 }

ifStackGroup2    OBJECT-GROUP
    OBJECTS { ifStackStatus, ifStackLastChange }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information on the
        layering of MIB-II interfaces."
    ::= { ifGroups 11 }

ifCounterDiscontinuityGroup  OBJECT-GROUP
    OBJECTS { ifCounterDiscontinuityTime }
    STATUS  current
    DESCRIPTION
        "A collection of objects providing information
        specific to interface counter discontinuities."
    ::= { ifGroups 13 }

-- Deprecated Definitions - Objects

--
--    The Interface Test Table
--
-- This group of objects is optional.  However, a media-specific
-- MIB may make implementation of this group mandatory.
--
-- This table replaces the ifExtnsTestTable
--

ifTestTable   OBJECT-TYPE
    SYNTAX      SEQUENCE OF IfTestEntry
    MAX-ACCESS  not-accessible
    STATUS      deprecated
    DESCRIPTION
        "This table contains one entry per interface.  It
        defines objects which allow a network manager to
        instruct an agent to test an interface for various
        faults.  Tests for an interface are defined in the
        media-specific MIB for that interface.  After invoking
        a test, the object ifTestResult can be read to
        determine the outcome.  If an agent can not perform
        the test, ifTestResult is set to so indicate.  The
        object ifTestCode can be used to provide further
        test-specific or interface-specific (or even
        enterprise-specific) information concerning the
        outcome of the test.  Only one test can be in progress
        on each interface at any one time.  If one test is in
        progress when another test is invoked, the second test
        is rejected.  Some agents may reject a test when a
        prior test is active on another interface.

        Before starting a test, a manager-station must first
        obtain 'ownership' of the entry in the ifTestTable for
        the interface to be tested.  This is accomplished with
        the ifTestId and ifTestStatus objects as follows:

     try_again:
         get (ifTestId, ifTestStatus)
         while (ifTestStatus != notInUse)
         /*
          * Loop while a test is running or some other
          * manager is configuring a test.
          */
         short delay
         get (ifTestId, ifTestStatus)
         }

         /*
          * Is not being used right now -- let's compete
          * to see who gets it.
          */
         lock_value = ifTestId

         if ( set(ifTestId = lock_value, ifTestStatus = inUse,
              ifTestOwner = 'my-IP-address') == FAILURE)
         /*
          * Another manager got the ifTestEntry -- go
          * try again
          */
         goto try_again;

         /*
          * I have the lock
          */
         set up any test parameters.

         /*
          * This starts the test
          */
         set(ifTestType = test_to_run);

         wait for test completion by polling ifTestResult

         when test completes, agent sets ifTestResult
          agent also sets ifTestStatus = 'notInUse'

         retrieve any additional test results, and ifTestId

         if (ifTestId == lock_value+1) results are valid

       A manager station first retrieves the value of the
       appropriate ifTestId and ifTestStatus objects,
       periodically repeating the retrieval if necessary,
       until the value of ifTestStatus is 'notInUse'.  The
       manager station then tries to set the same ifTestId
       object to the value it just retrieved, the same
       ifTestStatus object to 'inUse', and the corresponding
       ifTestOwner object to a value indicating itself.  If
       the set operation succeeds then the manager has
       obtained ownership of the ifTestEntry, and the value of
       the ifTestId object is incremented by the agent (per
       the semantics of TestAndIncr).  Failure of the set
       operation indicates that some other manager has
       obtained ownership of the ifTestEntry.

       Once ownership is obtained, any test parameters can be
       setup, and then the test is initiated by setting
       ifTestType.  On completion of the test, the agent sets
       ifTestStatus to 'notInUse'.  Once this occurs, the
       manager can retrieve the results.  In the (rare) event
       that the invocation of tests by two network managers
       were to overlap, then there would be a possibility that
       the first test's results might be overwritten by the
       second test's results prior to the first results being
       read.  This unlikely circumstance can be detected by a
       network manager retrieving ifTestId at the same time as
       retrieving the test results, and ensuring that the
       results are for the desired request.

       If ifTestType is not set within an abnormally long
       period of time after ownership is obtained, the agent
       should time-out the manager, and reset the value of the
       ifTestStatus object back to 'notInUse'.  It is
       suggested that this time-out period be 5 minutes.

       In general, a management station must not retransmit a
       request to invoke a test for which it does not receive
       a response; instead, it properly inspects an agent's
       MIB to determine if the invocation was successful.
       Only if the invocation was unsuccessful, is the
       invocation request retransmitted.

       Some tests may require the interface to be taken off-
       line in order to execute them, or may even require the
       agent to reboot after completion of the test.  In these
       circumstances, communication with the management
       station invoking the test may be lost until after
       completion of the test.  An agent is not required to
       support such tests.  However, if such tests are
       supported, then the agent should make every effort to
       transmit a response to the request which invoked the
       test prior to losing communication.  When the agent is
       restored to normal service, the results of the test are
       properly made available in the appropriate objects.
       Note that this requires that the ifIndex value assigned
       to an interface must be unchanged even if the test
       causes a reboot.  An agent must reject any test for
       which it cannot, perhaps due to resource constraints,
       make available at least the minimum amount of
       information after that test completes."
    ::= { ifMIBObjects 3 }

ifTestEntry OBJECT-TYPE
    SYNTAX       IfTestEntry
    MAX-ACCESS   not-accessible
    STATUS       deprecated
    DESCRIPTION
        "An entry containing objects for invoking tests on an
        interface."
    AUGMENTS  { ifEntry }
    ::= { ifTestTable 1 }

IfTestEntry ::=
    SEQUENCE {
    ifTestId           TestAndIncr,
    ifTestStatus       INTEGER,
    ifTestType         AutonomousType,
    ifTestResult       INTEGER,
    ifTestCode         OBJECT IDENTIFIER,
    ifTestOwner        OwnerString
    }

ifTestId         OBJECT-TYPE
    SYNTAX       TestAndIncr
    MAX-ACCESS   read-write
    STATUS       deprecated
    DESCRIPTION
        "This object identifies the current invocation of the
        interface's test."
    ::= { ifTestEntry 1 }

ifTestStatus     OBJECT-TYPE
    SYNTAX       INTEGER { notInUse(1), inUse(2) }
    MAX-ACCESS   read-write
    STATUS       deprecated
    DESCRIPTION
        "This object indicates whether or not some manager
        currently has the necessary 'ownership' required to
        invoke a test on this interface.  A write to this
        object is only successful when it changes its value
        from 'notInUse(1)' to 'inUse(2)'.  After completion of
        a test, the agent resets the value back to
        'notInUse(1)'."
    ::= { ifTestEntry 2 }

ifTestType       OBJECT-TYPE
    SYNTAX       AutonomousType
    MAX-ACCESS   read-write
    STATUS       deprecated
    DESCRIPTION
        "A control variable used to start and stop operator-
        initiated interface tests.  Most OBJECT IDENTIFIER
        values assigned to tests are defined elsewhere, in
        association with specific types of interface.
        However, this document assigns a value for a full-
        duplex loopback test, and defines the special meanings
        of the subject identifier:

        noTest  OBJECT IDENTIFIER ::= { 0 0 }

        When the value noTest is written to this object, no
        action is taken unless a test is in progress, in which
        case the test is aborted.  Writing any other value to
        this object is only valid when no test is currently in
        progress, in which case the indicated test is
        initiated.

        When read, this object always returns the most recent
        value that ifTestType was set to.  If it has not been
        set since the last initialization of the network
        management subsystem on the agent, a value of noTest
        is returned."
    ::= { ifTestEntry 3 }

ifTestResult  OBJECT-TYPE
    SYNTAX       INTEGER {
             none(1),          -- no test yet requested
             success(2),
             inProgress(3),
             notSupported(4),
             unAbleToRun(5),   -- due to state of system
             aborted(6),
             failed(7)
         }
    MAX-ACCESS   read-only
    STATUS       deprecated
    DESCRIPTION
        "This object contains the result of the most recently
        requested test, or the value none(1) if no tests have
        been requested since the last reset.  Note that this
        facility provides no provision for saving the results
        of one test when starting another, as could be
        required if used by multiple managers concurrently."
    ::= { ifTestEntry 4 }

ifTestCode  OBJECT-TYPE
    SYNTAX       OBJECT IDENTIFIER
    MAX-ACCESS   read-only
    STATUS       deprecated
    DESCRIPTION
        "This object contains a code which contains more
        specific information on the test result, for example
        an error-code after a failed test.  Error codes and
        other values this object may take are specific to the
        type of interface and/or test.  The value may have the
        semantics of either the AutonomousType or
        InstancePointer textual conventions as defined in RFC
        1903.  The identifier:

        testCodeUnknown  OBJECT IDENTIFIER ::= { 0 0 }

        is defined for use if no additional result code is
        available."
    ::= { ifTestEntry 5 }

ifTestOwner      OBJECT-TYPE
    SYNTAX       OwnerString
    MAX-ACCESS   read-write
    STATUS       deprecated
    DESCRIPTION
        "The entity which currently has the 'ownership'
        required to invoke a test on this interface."
    ::= { ifTestEntry 6 }

-- Deprecated Definitions - Groups

ifGeneralGroup    OBJECT-GROUP
    OBJECTS { ifDescr, ifType, ifSpeed, ifPhysAddress,
          ifAdminStatus, ifOperStatus, ifLastChange,
          ifLinkUpDownTrapEnable, ifConnectorPresent,
          ifHighSpeed, ifName }
    STATUS  deprecated
    DESCRIPTION
        "A collection of objects deprecated in favour of
        ifGeneralInformationGroup."
    ::= { ifGroups 1 }

ifTestGroup    OBJECT-GROUP
    OBJECTS { ifTestId, ifTestStatus, ifTestType,
          ifTestResult, ifTestCode, ifTestOwner }
    STATUS  deprecated
    DESCRIPTION
        "A collection of objects providing the ability to
        invoke tests on an interface."
    ::= { ifGroups 8 }

ifStackGroup    OBJECT-GROUP
    OBJECTS { ifStackStatus }
    STATUS  deprecated
    DESCRIPTION
        "The previous collection of objects providing
        information on the layering of MIB-II interfaces."
    ::= { ifGroups 9 }

ifOldObjectsGroup    OBJECT-GROUP
    OBJECTS { ifInNUcastPkts, ifOutNUcastPkts,
          ifOutQLen, ifSpecific }
    STATUS  deprecated
    DESCRIPTION
        "The collection of objects deprecated from the
        original MIB-II interfaces group."
    ::= { ifGroups 12 }

-- Deprecated Definitions - Compliance

ifCompliance MODULE-COMPLIANCE
    STATUS  deprecated
    DESCRIPTION
        "The previous compliance statement for SNMPv2 entities
        which have network interfaces."

    MODULE  -- this module
    MANDATORY-GROUPS { ifGeneralGroup, ifStackGroup }

    GROUP       ifFixedLengthGroup
    DESCRIPTION
        "This group is mandatory for all network interfaces
        which are character-oriented or transmit data in
        fixed-length transmission units."

    GROUP       ifHCFixedLengthGroup
    DESCRIPTION
        "This group is mandatory only for those network
        interfaces which are character-oriented or transmit
        data in fixed-length transmission units, and for which
        the value of the corresponding instance of ifSpeed is
        greater than 20,000,000 bits/second."

    GROUP       ifPacketGroup
    DESCRIPTION
        "This group is mandatory for all network interfaces
        which are packet-oriented."

    GROUP       ifHCPacketGroup
    DESCRIPTION
        "This group is mandatory only for those network
        interfaces which are packet-oriented and for which the
        value of the corresponding instance of ifSpeed is
        greater than 650,000,000 bits/second."

    GROUP       ifTestGroup
    DESCRIPTION
        "This group is optional.  Media-specific MIBs which
        require interface tests are strongly encouraged to use
        this group for invoking tests and reporting results.
        A medium specific MIB which has mandatory tests may
        make implementation of this group mandatory."

    GROUP       ifRcvAddressGroup
    DESCRIPTION
        "The applicability of this group MUST be defined by
        the media-specific MIBs.  Media-specific MIBs must
        define the exact meaning, use, and semantics of the
        addresses in this group."

    OBJECT      ifLinkUpDownTrapEnable
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required."

    OBJECT      ifPromiscuousMode
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required."

    OBJECT      ifStackStatus
    SYNTAX      INTEGER { active(1) } -- subset of RowStatus
    MIN-ACCESS  read-only
    DESCRIPTION
        "Write access is not required, and only one of the six
        enumerated values for the RowStatus textual convention
        need be supported, specifically: active(1)."
    OBJECT       ifAdminStatus
    SYNTAX       INTEGER { up(1), down(2) }
    MIN-ACCESS   read-only
    DESCRIPTION
        "Write access is not required, nor is support for the
        value testing(3)."
    ::= { ifCompliances 1 }

END


IP-MIB DEFINITIONS ::= BEGIN

IMPORTS
    OBJECT-GROUP, MODULE-COMPLIANCE
        FROM SNMPv2-CONF
    PhysAddress
        FROM SNMPv2-TC
    mib-2, IpAddress, Counter32, Integer32, OBJECT-TYPE, MODULE-IDENTITY
        FROM SNMPv2-SMI;

ipMIB MODULE-IDENTITY
    LAST-UPDATED "9411010000Z"
    ORGANIZATION "IETF SNMPv2 Working Group"
    CONTACT-INFO
                 "Keith McCloghrie

          Postal: Cisco Systems, Inc.
                  170 West Tasman Drive
                  San Jose, CA  95134-1706
                  US

          Phone:  +1 408 526 5260
          Email:  kzm@cisco.com"
    DESCRIPTION
        "The MIB module for managing IP and ICMP implementations,
         but excluding their management of IP routes."
    REVISION     "9103310000Z"
    DESCRIPTION
        "The initial revision of this MIB module was part of MIB-II."
    ::= { mib-2  48 }

ip OBJECT IDENTIFIER ::= { mib-2  4 }

ipForwarding OBJECT-TYPE
    SYNTAX     INTEGER {
                 forwarding(1),
                 notForwarding(2)
               }
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The indication of whether this entity is acting as an IP
         router in respect to the forwarding of datagrams received
         by, but not addressed to, this entity.  IP routers forward
         datagrams.  IP hosts do not (except those source-routed via
         the host)."
    ::= { ip  1 }

ipDefaultTTL OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The default value inserted into the Time-To-Live field of
         the IP header of datagrams originated at this entity,
         whenever a TTL value is not supplied by the transport layer
         protocol."
    ::= { ip  2 }

ipInReceives OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of input datagrams received from
         interfaces, including those received in error."
    ::= { ip  3 }

ipInHdrErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of input datagrams discarded due to errors in
         their IP headers, including bad checksums, version number
         mismatch, other format errors, time-to-live exceeded, errors
         discovered in processing their IP options, etc."
    ::= { ip  4 }

ipInAddrErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of input datagrams discarded because the IP
         address in their IP header's destination field was not a
         valid address to be received at this entity.  This count
         includes invalid addresses (e.g., 0.0.0.0) and addresses of
         unsupported Classes (e.g., Class E).  For entities which are
         not IP routers and therefore do not forward datagrams, this
         counter includes datagrams discarded because the destination
         address was not a local address."
    ::= { ip  5 }

ipForwDatagrams OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of input datagrams for which this entity was not
         their final IP destination, as a result of which an attempt
         was made to find a route to forward them to that final
         destination.  In entities which do not act as IP routers,
         this counter will include only those packets which were
         Source-Routed via this entity, and the Source-Route option
         processing was successful."
    ::= { ip  6 }

ipInUnknownProtos OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of locally-addressed datagrams received
         successfully but discarded because of an unknown or
         unsupported protocol."
    ::= { ip  7 }

ipInDiscards OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of input IP datagrams for which no problems were
         encountered to prevent their continued processing, but which
         were discarded (e.g., for lack of buffer space).  Note that
         this counter does not include any datagrams discarded while
         awaiting re-assembly."
    ::= { ip  8 }

ipInDelivers OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of input datagrams successfully delivered
         to IP user-protocols (including ICMP)."
    ::= { ip  9 }

ipOutRequests OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of IP datagrams which local IP user-
         protocols (including ICMP) supplied to IP in requests for
         transmission.  Note that this counter does not include any
         datagrams counted in ipForwDatagrams."
    ::= { ip  10 }

ipOutDiscards OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of output IP datagrams for which no problem was
         encountered to prevent their transmission to their
         destination, but which were discarded (e.g., for lack of
         buffer space).  Note that this counter would include
         datagrams counted in ipForwDatagrams if any such packets met
         this (discretionary) discard criterion."
    ::= { ip  11 }

ipOutNoRoutes OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP datagrams discarded because no route could
         be found to transmit them to their destination.  Note that
         this counter includes any packets counted in ipForwDatagrams
         which meet this `no-route' criterion.  Note that this
         includes any datagrams which a host cannot route because all
         of its default routers are down."
    ::= { ip  12 }

ipReasmTimeout OBJECT-TYPE
    SYNTAX     Integer32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The maximum number of seconds which received fragments are
         held while they are awaiting reassembly at this entity."
    ::= { ip  13 }

ipReasmReqds OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP fragments received which needed to be
         reassembled at this entity."
    ::= { ip  14 }

ipReasmOKs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP datagrams successfully re-assembled."
    ::= { ip  15 }

ipReasmFails OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of failures detected by the IP re-assembly
         algorithm (for whatever reason: timed out, errors, etc).
         Note that this is not necessarily a count of discarded IP
         fragments since some algorithms (notably the algorithm in
         RFC 815) can lose track of the number of fragments by
         combining them as they are received."
    ::= { ip  16 }

ipFragOKs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP datagrams that have been successfully
         fragmented at this entity."
    ::= { ip  17 }

ipFragFails OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP datagrams that have been discarded because
         they needed to be fragmented at this entity but could not
         be, e.g., because their Don't Fragment flag was set."
    ::= { ip  18 }

ipFragCreates OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of IP datagram fragments that have been
         generated as a result of fragmentation at this entity."
    ::= { ip  19 }

ipAddrTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF IpAddrEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The table of addressing information relevant to this
         entity's IP addresses."
    ::= { ip  20 }

ipAddrEntry OBJECT-TYPE
    SYNTAX     IpAddrEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The addressing information for one of this entity's IP
         addresses."
    INDEX      { ipAdEntAddr }
    ::= { ipAddrTable  1 }

IpAddrEntry ::=
    SEQUENCE {
        ipAdEntAddr
            IpAddress,

        ipAdEntIfIndex
            INTEGER,

        ipAdEntNetMask
            IpAddress,

        ipAdEntBcastAddr
            INTEGER,

        ipAdEntReasmMaxSize
            INTEGER
    }

ipAdEntAddr OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The IP address to which this entry's addressing information
         pertains."
    ::= { ipAddrEntry  1 }

ipAdEntIfIndex OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The index value which uniquely identifies the interface to
         which this entry is applicable.  The interface identified by
         a particular value of this index is the same interface as
         identified by the same value of RFC 1573's ifIndex."
    ::= { ipAddrEntry  2 }

ipAdEntNetMask OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The subnet mask associated with the IP address of this
         entry.  The value of the mask is an IP address with all the
         network bits set to 1 and all the hosts bits set to 0."
    ::= { ipAddrEntry  3 }

ipAdEntBcastAddr OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of the least-significant bit in the IP broadcast
         address used for sending datagrams on the (logical)
         interface associated with the IP address of this entry.  For
         example, when the Internet standard all-ones broadcast
         address is used, the value will be 1.  This value applies to
         both the subnet and network broadcasts addresses used by the
         entity on this (logical) interface."
    ::= { ipAddrEntry  4 }

ipAdEntReasmMaxSize OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The size of the largest IP datagram which this entity can
         re-assemble from incoming IP fragmented datagrams received
         on this interface."
    ::= { ipAddrEntry  5 }

ipNetToMediaTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF IpNetToMediaEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The IP Address Translation table used for mapping from IP
         addresses to physical addresses."
    ::= { ip  22 }

ipNetToMediaEntry OBJECT-TYPE
    SYNTAX     IpNetToMediaEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "Each entry contains one IpAddress to `physical' address
         equivalence."
    INDEX      { ipNetToMediaIfIndex,  ipNetToMediaNetAddress }
    ::= { ipNetToMediaTable  1 }

IpNetToMediaEntry ::=
    SEQUENCE {
        ipNetToMediaIfIndex
            INTEGER,

        ipNetToMediaPhysAddress
            PhysAddress,

        ipNetToMediaNetAddress
            IpAddress,

        ipNetToMediaType
            INTEGER
    }

ipNetToMediaIfIndex OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-create
    STATUS     current
    DESCRIPTION
        "The interface on which this entry's equivalence is
         effective.  The interface identified by a particular value
         of this index is the same interface as identified by the
         same value of RFC 1573's ifIndex."
    ::= { ipNetToMediaEntry  1 }

ipNetToMediaPhysAddress OBJECT-TYPE
    SYNTAX     PhysAddress
    MAX-ACCESS read-create
    STATUS     current
    DESCRIPTION
        "The media-dependent `physical' address."
    ::= { ipNetToMediaEntry  2 }

ipNetToMediaNetAddress OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-create
    STATUS     current
    DESCRIPTION
        "The IpAddress corresponding to the media-dependent
         `physical' address."
    ::= { ipNetToMediaEntry  3 }

ipNetToMediaType OBJECT-TYPE
    SYNTAX     INTEGER {
                 other(1),
                 invalid(2),
                 dynamic(3),
                 static(4)
               }
    MAX-ACCESS read-create
    STATUS     current
    DESCRIPTION
        "The type of mapping.
         Setting this object to the value invalid(2) has the effect
         of invalidating the corresponding entry in the
         ipNetToMediaTable.  That is, it effectively disassociates
         the interface identified with said entry from the mapping
         identified with said entry.  It is an implementation-
         specific matter as to whether the agent removes an
         invalidated entry from the table.  Accordingly, management
         stations must be prepared to receive tabular information
         from agents that corresponds to entries not currently in
         use.  Proper interpretation of such entries requires
         examination of the relevant ipNetToMediaType object."
    ::= { ipNetToMediaEntry  4 }

ipRoutingDiscards OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of routing entries which were chosen to be
         discarded even though they are valid.  One possible reason
         for discarding such an entry could be to free-up buffer
         space for other routing entries."
    ::= { ip  23 }

icmp OBJECT IDENTIFIER ::= { mib-2  5 }

icmpInMsgs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of ICMP messages which the entity
         received.  Note that this counter includes all those counted
         by icmpInErrors."
    ::= { icmp  1 }

icmpInErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP messages which the entity received but
         determined as having ICMP-specific errors (bad ICMP
         checksums, bad length, etc.)."
    ::= { icmp  2 }

icmpInDestUnreachs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Destination Unreachable messages
         received."
    ::= { icmp  3 }

icmpInTimeExcds OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Time Exceeded messages received."
    ::= { icmp  4 }

icmpInParmProbs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Parameter Problem messages received."
    ::= { icmp  5 }

icmpInSrcQuenchs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Source Quench messages received."
    ::= { icmp  6 }

icmpInRedirects OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Redirect messages received."
    ::= { icmp  7 }

icmpInEchos OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Echo (request) messages received."
    ::= { icmp  8 }

icmpInEchoReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Echo Reply messages received."
    ::= { icmp  9 }

icmpInTimestamps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Timestamp (request) messages received."
    ::= { icmp  10 }

icmpInTimestampReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Timestamp Reply messages received."
    ::= { icmp  11 }

icmpInAddrMasks OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Address Mask Request messages received."
    ::= { icmp  12 }

icmpInAddrMaskReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Address Mask Reply messages received."
    ::= { icmp  13 }

icmpOutMsgs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of ICMP messages which this entity
         attempted to send.  Note that this counter includes all
         those counted by icmpOutErrors."
    ::= { icmp  14 }

icmpOutErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP messages which this entity did not send
         due to problems discovered within ICMP such as a lack of
         buffers.  This value should not include errors discovered
         outside the ICMP layer such as the inability of IP to route
         the resultant datagram.  In some implementations there may
         be no types of error which contribute to this counter's
         value."
    ::= { icmp  15 }

icmpOutDestUnreachs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Destination Unreachable messages sent."
    ::= { icmp  16 }

icmpOutTimeExcds OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Time Exceeded messages sent."
    ::= { icmp  17 }

icmpOutParmProbs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Parameter Problem messages sent."
    ::= { icmp  18 }

icmpOutSrcQuenchs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Source Quench messages sent."
    ::= { icmp  19 }

icmpOutRedirects OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Redirect messages sent.  For a host,
         this object will always be zero, since hosts do not send
         redirects."
    ::= { icmp  20 }

icmpOutEchos OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Echo (request) messages sent."
    ::= { icmp  21 }

icmpOutEchoReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Echo Reply messages sent."
    ::= { icmp  22 }

icmpOutTimestamps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Timestamp (request) messages sent."
    ::= { icmp  23 }

icmpOutTimestampReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Timestamp Reply messages sent."
    ::= { icmp  24 }

icmpOutAddrMasks OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Address Mask Request messages sent."
    ::= { icmp  25 }

icmpOutAddrMaskReps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of ICMP Address Mask Reply messages sent."
    ::= { icmp  26 }

ipMIBConformance OBJECT IDENTIFIER ::= { ipMIB  2 }

ipMIBCompliances OBJECT IDENTIFIER ::= { ipMIBConformance  1 }

ipMIBGroups OBJECT IDENTIFIER ::= { ipMIBConformance  2 }

ipMIBCompliance MODULE-COMPLIANCE
    STATUS     current
    DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement IP."
    MODULE           -- this module
    MANDATORY-GROUPS { ipGroup,  icmpGroup }
    ::= { ipMIBCompliances  1 }

ipGroup OBJECT-GROUP
    OBJECTS    {
                 ipForwarding,
                 ipDefaultTTL,
                 ipInReceives,
                 ipInHdrErrors,
                 ipInAddrErrors,
                 ipForwDatagrams,
                 ipInUnknownProtos,
                 ipInDiscards,
                 ipInDelivers,
                 ipOutRequests,
                 ipOutDiscards,
                 ipOutNoRoutes,
                 ipReasmTimeout,
                 ipReasmReqds,
                 ipReasmOKs,
                 ipReasmFails,
                 ipFragOKs,
                 ipFragFails,
                 ipFragCreates,
                 ipAdEntAddr,
                 ipAdEntIfIndex,
                 ipAdEntNetMask,
                 ipAdEntBcastAddr,
                 ipAdEntReasmMaxSize,
                 ipNetToMediaIfIndex,
                 ipNetToMediaPhysAddress,
                 ipNetToMediaNetAddress,
                 ipNetToMediaType,
                 ipRoutingDiscards
               }
    STATUS     current
    DESCRIPTION
        "The ip group of objects providing for basic management of
         IP entities, exclusive of the management of IP routes."
    ::= { ipMIBGroups  1 }

icmpGroup OBJECT-GROUP
    OBJECTS    {
                 icmpInMsgs,
                 icmpInErrors,
                 icmpInDestUnreachs,
                 icmpInTimeExcds,
                 icmpInParmProbs,
                 icmpInSrcQuenchs,
                 icmpInRedirects,
                 icmpInEchos,
                 icmpInEchoReps,
                 icmpInTimestamps,
                 icmpInTimestampReps,
                 icmpInAddrMasks,
                 icmpInAddrMaskReps,
                 icmpOutMsgs,
                 icmpOutErrors,
                 icmpOutDestUnreachs,
                 icmpOutTimeExcds,
                 icmpOutParmProbs,
                 icmpOutSrcQuenchs,
                 icmpOutRedirects,
                 icmpOutEchos,
                 icmpOutEchoReps,
                 icmpOutTimestamps,
                 icmpOutTimestampReps,
                 icmpOutAddrMasks,
                 icmpOutAddrMaskReps
               }
    STATUS     current
    DESCRIPTION
        "The icmp group of objects providing ICMP statistics."
    ::= { ipMIBGroups  2 }

END


IPV6-ICMP-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE,
    Counter32, mib-2                 FROM SNMPv2-SMI
    MODULE-COMPLIANCE, OBJECT-GROUP  FROM SNMPv2-CONF
    ipv6IfEntry                      FROM IPV6-MIB;

ipv6IcmpMIB MODULE-IDENTITY
    LAST-UPDATED "9801082155Z"
    ORGANIZATION "IETF IPv6 Working Group"
    CONTACT-INFO
      "           Dimitry Haskin

       Postal: Bay Networks, Inc.
           660 Techology Park Drive.
           Billerica, MA  01821
           US

          Tel: +1-978-916-8124
       E-mail: dhaskin@baynetworks.com

           Steve Onishi

       Postal: Bay Networks, Inc.
           3 Federal Street
           Billerica, MA 01821
           US

          Tel: +1-978-916-3816
       E-mail: sonishi@baynetworks.com"
    DESCRIPTION
      "The MIB module for entities implementing
    the ICMPv6."
    ::= { mib-2 56 }

-- the ICMPv6 group

ipv6IcmpMIBObjects OBJECT IDENTIFIER ::= { ipv6IcmpMIB  1 }

-- Per-interface ICMPv6 statistics table

ipv6IfIcmpTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF Ipv6IfIcmpEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
     "IPv6 ICMP statistics. This table contains statistics
     of ICMPv6 messages that are received and sourced by
     the entity."
    ::= { ipv6IcmpMIBObjects 1 }

ipv6IfIcmpEntry OBJECT-TYPE
    SYNTAX     Ipv6IfIcmpEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
     "An ICMPv6 statistics entry containing
     objects at a particular IPv6 interface.

     Note that a receiving interface is
     the interface to which a given ICMPv6 message
     is addressed which may not be necessarily
     the input interface for the message.

     Similarly,  the sending interface is
     the interface that sources a given
     ICMP message which is usually but not
     necessarily the output interface for the message."
    AUGMENTS { ipv6IfEntry }
    ::= { ipv6IfIcmpTable 1 }

Ipv6IfIcmpEntry ::= SEQUENCE {
     ipv6IfIcmpInMsgs
           Counter32      ,
     ipv6IfIcmpInErrors
           Counter32      ,
     ipv6IfIcmpInDestUnreachs
           Counter32      ,
     ipv6IfIcmpInAdminProhibs
           Counter32      ,
     ipv6IfIcmpInTimeExcds
           Counter32      ,
     ipv6IfIcmpInParmProblems
           Counter32      ,
     ipv6IfIcmpInPktTooBigs
           Counter32      ,
     ipv6IfIcmpInEchos
           Counter32      ,
     ipv6IfIcmpInEchoReplies
           Counter32      ,
     ipv6IfIcmpInRouterSolicits
           Counter32      ,
     ipv6IfIcmpInRouterAdvertisements
           Counter32      ,
     ipv6IfIcmpInNeighborSolicits
           Counter32      ,
     ipv6IfIcmpInNeighborAdvertisements
           Counter32      ,
     ipv6IfIcmpInRedirects
           Counter32      ,
     ipv6IfIcmpInGroupMembQueries
           Counter32      ,
     ipv6IfIcmpInGroupMembResponses
           Counter32      ,
     ipv6IfIcmpInGroupMembReductions
           Counter32      ,
     ipv6IfIcmpOutMsgs
           Counter32      ,
     ipv6IfIcmpOutErrors
           Counter32      ,
     ipv6IfIcmpOutDestUnreachs
           Counter32      ,
     ipv6IfIcmpOutAdminProhibs
           Counter32      ,
     ipv6IfIcmpOutTimeExcds
           Counter32      ,
     ipv6IfIcmpOutParmProblems
           Counter32      ,
     ipv6IfIcmpOutPktTooBigs
           Counter32      ,
     ipv6IfIcmpOutEchos
           Counter32      ,
     ipv6IfIcmpOutEchoReplies
           Counter32      ,
     ipv6IfIcmpOutRouterSolicits
           Counter32      ,
     ipv6IfIcmpOutRouterAdvertisements
           Counter32      ,
     ipv6IfIcmpOutNeighborSolicits
           Counter32      ,
     ipv6IfIcmpOutNeighborAdvertisements
           Counter32      ,
     ipv6IfIcmpOutRedirects
           Counter32      ,
     ipv6IfIcmpOutGroupMembQueries
           Counter32      ,
     ipv6IfIcmpOutGroupMembResponses
           Counter32      ,
     ipv6IfIcmpOutGroupMembReductions
           Counter32
    }

ipv6IfIcmpInMsgs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The total number of ICMP messages received
     by the interface which includes all those
     counted by ipv6IfIcmpInErrors. Note that this
     interface is the interface to which the
     ICMP messages were addressed which may not be
     necessarily the input interface for the messages."
    ::= { ipv6IfIcmpEntry 1 }

ipv6IfIcmpInErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP messages which the interface
     received but determined as having ICMP-specific
     errors (bad ICMP checksums, bad length, etc.)."
    ::= { ipv6IfIcmpEntry 2 }

ipv6IfIcmpInDestUnreachs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Destination Unreachable
     messages received by the interface."
    ::= { ipv6IfIcmpEntry 3 }

ipv6IfIcmpInAdminProhibs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP destination
     unreachable/communication administratively
     prohibited messages received by the interface."
    ::= { ipv6IfIcmpEntry 4 }

ipv6IfIcmpInTimeExcds OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Time Exceeded messages
      received by the interface."
    ::= { ipv6IfIcmpEntry 5 }

ipv6IfIcmpInParmProblems OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Parameter Problem messages
      received by the interface."
    ::= { ipv6IfIcmpEntry 6 }

ipv6IfIcmpInPktTooBigs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Packet Too Big messages
     received by the interface."
    ::= { ipv6IfIcmpEntry 7 }

ipv6IfIcmpInEchos OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Echo (request) messages
      received by the interface."
    ::= { ipv6IfIcmpEntry 8 }

ipv6IfIcmpInEchoReplies OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Echo Reply messages received
     by the interface."
    ::= { ipv6IfIcmpEntry 9 }

ipv6IfIcmpInRouterSolicits OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Router Solicit messages
      received by the interface."
    ::= { ipv6IfIcmpEntry 10 }

ipv6IfIcmpInRouterAdvertisements OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Router Advertisement messages
     received by the interface."
    ::= { ipv6IfIcmpEntry 11 }

ipv6IfIcmpInNeighborSolicits OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Neighbor Solicit messages
      received by the interface."
    ::= { ipv6IfIcmpEntry 12 }

ipv6IfIcmpInNeighborAdvertisements OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Neighbor Advertisement
     messages received by the interface."
    ::= { ipv6IfIcmpEntry 13 }

ipv6IfIcmpInRedirects OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of Redirect messages received
     by the interface."
    ::= { ipv6IfIcmpEntry 14 }

ipv6IfIcmpInGroupMembQueries OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Query
     messages received by the interface."
    ::= { ipv6IfIcmpEntry 15}

ipv6IfIcmpInGroupMembResponses OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Response messages
     received by the interface."
    ::= { ipv6IfIcmpEntry 16}

 ipv6IfIcmpInGroupMembReductions OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Reduction messages
     received by the interface."
    ::= { ipv6IfIcmpEntry 17}

ipv6IfIcmpOutMsgs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The total number of ICMP messages which this
     interface attempted to send.  Note that this counter
     includes all those counted by icmpOutErrors."
    ::= { ipv6IfIcmpEntry 18 }

ipv6IfIcmpOutErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP messages which this interface did
     not send due to problems discovered within ICMP
     such as a lack of buffers.  This value should not
     include errors discovered outside the ICMP layer
     such as the inability of IPv6 to route the resultant
     datagram.  In some implementations there may be no
     types of error which contribute to this counter's
     value."
    ::= { ipv6IfIcmpEntry 19 }

ipv6IfIcmpOutDestUnreachs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Destination Unreachable
     messages sent by the interface."
    ::= { ipv6IfIcmpEntry 20 }

ipv6IfIcmpOutAdminProhibs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
      "Number of ICMP dest unreachable/communication
      administratively prohibited messages sent."
    ::= { ipv6IfIcmpEntry 21 }

ipv6IfIcmpOutTimeExcds OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Time Exceeded messages sent
     by the interface."
    ::= { ipv6IfIcmpEntry 22 }

ipv6IfIcmpOutParmProblems OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Parameter Problem messages
     sent by the interface."
    ::= { ipv6IfIcmpEntry 23 }

ipv6IfIcmpOutPktTooBigs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Packet Too Big messages sent
     by the interface."
    ::= { ipv6IfIcmpEntry 24 }

ipv6IfIcmpOutEchos OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Echo (request) messages sent
     by the interface."
    ::= { ipv6IfIcmpEntry 25 }

ipv6IfIcmpOutEchoReplies OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Echo Reply messages sent
     by the interface."
    ::= { ipv6IfIcmpEntry 26 }

ipv6IfIcmpOutRouterSolicits OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Router Solicitation messages
      sent by the interface."
    ::= { ipv6IfIcmpEntry 27 }

ipv6IfIcmpOutRouterAdvertisements OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Router Advertisement messages
     sent by the interface."
    ::= { ipv6IfIcmpEntry 28 }

ipv6IfIcmpOutNeighborSolicits OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Neighbor Solicitation
      messages sent by the interface."
    ::= { ipv6IfIcmpEntry 29 }

ipv6IfIcmpOutNeighborAdvertisements OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMP Neighbor Advertisement
     messages sent by the interface."
    ::= { ipv6IfIcmpEntry 30 }

ipv6IfIcmpOutRedirects OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of Redirect messages sent. For
     a host, this object will always be zero,
     since hosts do not send redirects."
    ::= { ipv6IfIcmpEntry 31 }

ipv6IfIcmpOutGroupMembQueries OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Query
     messages sent."
    ::= { ipv6IfIcmpEntry 32}

ipv6IfIcmpOutGroupMembResponses OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Response
     messages sent."
    ::= { ipv6IfIcmpEntry 33}

ipv6IfIcmpOutGroupMembReductions OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The number of ICMPv6 Group Membership Reduction
     messages sent."
    ::= { ipv6IfIcmpEntry 34}

-- conformance information

ipv6IcmpConformance OBJECT IDENTIFIER ::= { ipv6IcmpMIB 2 }

ipv6IcmpCompliances
    OBJECT IDENTIFIER ::= { ipv6IcmpConformance 1 }
ipv6IcmpGroups
    OBJECT IDENTIFIER ::= { ipv6IcmpConformance 2 }

-- compliance statements

ipv6IcmpCompliance MODULE-COMPLIANCE
   STATUS  current
   DESCRIPTION
     "The compliance statement for SNMPv2 entities which
     implement ICMPv6."
   MODULE  -- this module
    MANDATORY-GROUPS { ipv6IcmpGroup }
   ::= { ipv6IcmpCompliances 1 }

ipv6IcmpGroup OBJECT-GROUP
   OBJECTS   {
        ipv6IfIcmpInMsgs,
        ipv6IfIcmpInErrors,
        ipv6IfIcmpInDestUnreachs,
        ipv6IfIcmpInAdminProhibs,
        ipv6IfIcmpInTimeExcds,
        ipv6IfIcmpInParmProblems,
        ipv6IfIcmpInPktTooBigs,
        ipv6IfIcmpInEchos,
        ipv6IfIcmpInEchoReplies,
        ipv6IfIcmpInRouterSolicits,
        ipv6IfIcmpInRouterAdvertisements,
        ipv6IfIcmpInNeighborSolicits,
        ipv6IfIcmpInNeighborAdvertisements,
        ipv6IfIcmpInRedirects,
        ipv6IfIcmpInGroupMembQueries,
        ipv6IfIcmpInGroupMembResponses,
        ipv6IfIcmpInGroupMembReductions,
        ipv6IfIcmpOutMsgs,
        ipv6IfIcmpOutErrors,
        ipv6IfIcmpOutDestUnreachs,
        ipv6IfIcmpOutAdminProhibs,
        ipv6IfIcmpOutTimeExcds,
        ipv6IfIcmpOutParmProblems,
        ipv6IfIcmpOutPktTooBigs,
        ipv6IfIcmpOutEchos,
        ipv6IfIcmpOutEchoReplies,
        ipv6IfIcmpOutRouterSolicits,
        ipv6IfIcmpOutRouterAdvertisements,
        ipv6IfIcmpOutNeighborSolicits,
        ipv6IfIcmpOutNeighborAdvertisements,
        ipv6IfIcmpOutRedirects,
        ipv6IfIcmpOutGroupMembQueries,
        ipv6IfIcmpOutGroupMembResponses,
        ipv6IfIcmpOutGroupMembReductions
          }
   STATUS    current
   DESCRIPTION
     "The ICMPv6 group of objects providing information
      specific to ICMPv6."
   ::= { ipv6IcmpGroups 1 }

END


IPV6-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
    mib-2, Counter32, Unsigned32, Integer32,
    Gauge32				  FROM SNMPv2-SMI
    DisplayString, PhysAddress, TruthValue, TimeStamp,
    VariablePointer, RowPointer		  FROM SNMPv2-TC
    MODULE-COMPLIANCE, OBJECT-GROUP,
    NOTIFICATION-GROUP			  FROM SNMPv2-CONF
    Ipv6IfIndex, Ipv6Address, Ipv6AddressPrefix,
    Ipv6AddressIfIdentifier,
    Ipv6IfIndexOrZero			  FROM IPV6-TC;

ipv6MIB MODULE-IDENTITY
    LAST-UPDATED "9802052155Z"
    ORGANIZATION "IETF IPv6 Working Group"
    CONTACT-INFO
      "		  Dimitry Haskin

       Postal: Bay Networks, Inc.
           660 Techology Park Drive.
           Billerica, MA  01821
           US

          Tel: +1-978-916-8124
       E-mail: dhaskin@baynetworks.com

           Steve Onishi

       Postal: Bay Networks, Inc.
           3 Federal Street
           Billerica, MA 01821
           US

          Tel: +1-978-916-3816
       E-mail: sonishi@baynetworks.com"
    DESCRIPTION
      "The MIB module for entities implementing the IPv6
    protocol."
    ::= { mib-2 55 }

-- the IPv6 general group

ipv6MIBObjects OBJECT IDENTIFIER   ::= { ipv6MIB 1 }

ipv6Forwarding OBJECT-TYPE
    SYNTAX	INTEGER {
          forwarding(1),    -- acting as a router

                    -- NOT acting as
          notForwarding(2)  -- a router
         }
     MAX-ACCESS read-write
     STATUS	current
     DESCRIPTION
    "The indication of whether this entity is acting
    as an IPv6 router in respect to the forwarding of
    datagrams received by, but not addressed to, this
    entity.	 IPv6 routers forward datagrams.  IPv6
    hosts do not (except those source-routed via the
    host).

    Note that for some managed nodes, this object may
    take on only a subset of the values possible.
    Accordingly, it is appropriate for an agent to
    return a `wrongValue' response if a management
    station attempts to change this object to an
    inappropriate value."
     ::= { ipv6MIBObjects 1 }

ipv6DefaultHopLimit OBJECT-TYPE
    SYNTAX	INTEGER(0..255)
    MAX-ACCESS	read-write
     STATUS	current
    DESCRIPTION
    "The default value inserted into the Hop Limit
    field of the IPv6 header of datagrams originated
    at this entity, whenever a Hop Limit value is not
    supplied by the transport layer protocol."
    DEFVAL  { 64 }
    ::= { ipv6MIBObjects 2 }

ipv6Interfaces OBJECT-TYPE
    SYNTAX	Unsigned32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The number of IPv6 interfaces (regardless of
    their current state) present on this system."
    ::= { ipv6MIBObjects 3 }

ipv6IfTableLastChange OBJECT-TYPE
    SYNTAX	TimeStamp
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The value of sysUpTime at the time of the last
      insertion or removal of an entry in the
      ipv6IfTable. If the number of entries has been
      unchanged since the last re-initialization of
      the local network management subsystem, then this
      object contains a zero value."
    ::= { ipv6MIBObjects 4 }

-- the IPv6 Interfaces table

ipv6IfTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF Ipv6IfEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "The IPv6 Interfaces table contains information
      on the entity's internetwork-layer interfaces.
      An IPv6 interface constitutes a logical network
      layer attachment to the layer immediately below
      IPv6 including internet layer 'tunnels', such as
      tunnels over IPv4 or IPv6 itself."
    ::= { ipv6MIBObjects 5 }

ipv6IfEntry OBJECT-TYPE
    SYNTAX     Ipv6IfEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "An interface entry containing objects
    about a particular IPv6 interface."
    INDEX   { ipv6IfIndex }
    ::= { ipv6IfTable 1 }

Ipv6IfEntry ::= SEQUENCE {
     ipv6IfIndex		  Ipv6IfIndex,
     ipv6IfDescr		  DisplayString,
     ipv6IfLowerLayer	  VariablePointer,
     ipv6IfEffectiveMtu	  Unsigned32,
     ipv6IfReasmMaxSize	  Unsigned32,
     ipv6IfIdentifier	  Ipv6AddressIfIdentifier,
     ipv6IfIdentifierLength	  INTEGER,
     ipv6IfPhysicalAddress	  PhysAddress,
     ipv6IfAdminStatus	  INTEGER,
     ipv6IfOperStatus	  INTEGER,
     ipv6IfLastChange	  TimeStamp
    }

ipv6IfIndex OBJECT-TYPE
    SYNTAX     Ipv6IfIndex
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "A unique non-zero value identifying
    the particular IPv6 interface."
    ::= { ipv6IfEntry 1 }

ipv6IfDescr OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
      "A textual string containing information about the
      interface.  This string may be set by the network
      management system."
    ::= { ipv6IfEntry 2 }

ipv6IfLowerLayer OBJECT-TYPE
   SYNTAX      VariablePointer
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "This object identifies the protocol layer over
      which this network interface operates.  If this
      network interface operates over the data-link
      layer, then the value of this object refers to an
      instance of ifIndex [6]. If this network interface
      operates over an IPv4 interface, the value of this
      object refers to an instance of ipAdEntAddr [3].
      If this network interface operates over another
      IPv6 interface, the value of this object refers to
      an instance of ipv6IfIndex.  If this network
      interface is not currently operating over an active
      protocol layer, then the value of this object
      should be set to the OBJECT ID { 0 0 }."
   ::= { ipv6IfEntry 3 }

ipv6IfEffectiveMtu OBJECT-TYPE
   SYNTAX      Unsigned32
   UNITS       "octets"
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "The size of the largest IPv6 packet which can be
     sent/received on the interface, specified in
     octets."
::= { ipv6IfEntry 4 }

ipv6IfReasmMaxSize OBJECT-TYPE
   SYNTAX      Unsigned32 (0..65535)
   UNITS       "octets"
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "The size of the largest IPv6 datagram which this
     entity can re-assemble from incoming IPv6 fragmented
     datagrams received on this interface."
::= { ipv6IfEntry 5 }

ipv6IfIdentifier OBJECT-TYPE
    SYNTAX	Ipv6AddressIfIdentifier
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "The Interface Identifier for this interface that
    is (at least) unique on the link this interface is
    attached to. The Interface Identifier is combined
    with an address prefix to form an interface address.

    By default, the Interface Identifier is autoconfigured
    according to the rules of the link type this
    interface is attached to."
    ::= { ipv6IfEntry 6 }

ipv6IfIdentifierLength OBJECT-TYPE
    SYNTAX	INTEGER (0..64)
    UNITS	"bits"
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
      "The length of the Interface Identifier in bits."
    ::= { ipv6IfEntry 7 }

ipv6IfPhysicalAddress OBJECT-TYPE
    SYNTAX	PhysAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The interface's physical address. For example, for
      an IPv6 interface attached to an 802.x link, this
      object normally contains a MAC address. Note that
      in some cases this address may differ from the
      address of the interface's protocol sub-layer.  The
      interface's media-specific MIB must define the bit
      and byte ordering and the format of the value of
      this object. For interfaces which do not have such
      an address (e.g., a serial line), this object should
      contain an octet string of zero length."
    ::= { ipv6IfEntry 8 }

ipv6IfAdminStatus OBJECT-TYPE
   SYNTAX  INTEGER {
         up(1),	  -- ready to pass packets
         down(2)
        }
   MAX-ACCESS  read-write
   STATUS      current
   DESCRIPTION
     "The desired state of the interface.  When a managed
     system initializes,  all IPv6 interfaces start with
     ipv6IfAdminStatus in the down(2) state.  As a result
     of either explicit management action or per
     configuration information retained by the managed
     system,  ipv6IfAdminStatus is then changed to
     the up(1) state (or remains in the down(2) state)."
   ::= { ipv6IfEntry 9 }

ipv6IfOperStatus OBJECT-TYPE
   SYNTAX  INTEGER {
         up(1),		-- ready to pass packets

         down(2),

         noIfIdentifier(3), -- no interface identifier

                -- status can not be
                -- determined for some
         unknown(4),	-- reason

                -- some component is
         notPresent(5)	-- missing
        }
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "The current operational state of the interface.
     The noIfIdentifier(3) state indicates that no valid
     Interface Identifier is assigned to the interface.
     This state usually indicates that the link-local
     interface address failed Duplicate Address Detection.
     If ipv6IfAdminStatus is down(2) then ipv6IfOperStatus
     should be down(2).	 If ipv6IfAdminStatus is changed
     to up(1) then ipv6IfOperStatus should change to up(1)
     if the interface is ready to transmit and receive
     network traffic; it should remain in the down(2) or
     noIfIdentifier(3) state if and only if there is a
     fault that prevents it from going to the up(1) state;
     it should remain in the notPresent(5) state if
     the interface has missing (typically, lower layer)
     components."
   ::= { ipv6IfEntry 10 }

ipv6IfLastChange OBJECT-TYPE
   SYNTAX      TimeStamp
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
    "The value of sysUpTime at the time the interface
    entered its current operational state.	If the
    current state was entered prior to the last
    re-initialization of the local network management
    subsystem, then this object contains a zero
    value."
   ::= { ipv6IfEntry 11 }

--  IPv6 Interface Statistics table

ipv6IfStatsTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF Ipv6IfStatsEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
     "IPv6 interface traffic statistics."
    ::= { ipv6MIBObjects 6 }

ipv6IfStatsEntry OBJECT-TYPE
    SYNTAX     Ipv6IfStatsEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
     "An interface statistics entry containing objects
     at a particular IPv6 interface."
    AUGMENTS { ipv6IfEntry }
    ::= { ipv6IfStatsTable 1 }

Ipv6IfStatsEntry ::= SEQUENCE {
     ipv6IfStatsInReceives
         Counter32,
     ipv6IfStatsInHdrErrors
         Counter32,
     ipv6IfStatsInTooBigErrors
         Counter32,
     ipv6IfStatsInNoRoutes
         Counter32,
     ipv6IfStatsInAddrErrors
         Counter32,
     ipv6IfStatsInUnknownProtos
         Counter32,
     ipv6IfStatsInTruncatedPkts
         Counter32,
     ipv6IfStatsInDiscards
         Counter32,
     ipv6IfStatsInDelivers
         Counter32,
     ipv6IfStatsOutForwDatagrams
         Counter32,
     ipv6IfStatsOutRequests
         Counter32,
     ipv6IfStatsOutDiscards
         Counter32,
     ipv6IfStatsOutFragOKs
         Counter32,
     ipv6IfStatsOutFragFails
         Counter32,
     ipv6IfStatsOutFragCreates
         Counter32,
     ipv6IfStatsReasmReqds
         Counter32,
     ipv6IfStatsReasmOKs
         Counter32,
     ipv6IfStatsReasmFails
         Counter32,
     ipv6IfStatsInMcastPkts
         Counter32,
     ipv6IfStatsOutMcastPkts
         Counter32
    }

ipv6IfStatsInReceives OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The total number of input datagrams received by
    the interface, including those received in error."
    ::= { ipv6IfStatsEntry 1 }

ipv6IfStatsInHdrErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The number of input datagrams discarded due to
    errors in their IPv6 headers, including version
    number mismatch, other format errors, hop count
    exceeded, errors discovered in processing their
    IPv6 options, etc."
    ::= { ipv6IfStatsEntry 2 }

ipv6IfStatsInTooBigErrors OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The number of input datagrams that could not be
      forwarded because their size exceeded the link MTU
      of outgoing interface."
    ::= { ipv6IfStatsEntry 3 }

ipv6IfStatsInNoRoutes OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of input datagrams discarded because no
     route could be found to transmit them to their
     destination."
    ::= { ipv6IfStatsEntry 4 }

ipv6IfStatsInAddrErrors OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of input datagrams discarded because
    the IPv6 address in their IPv6 header's destination
    field was not a valid address to be received at
    this entity.  This count includes invalid
    addresses (e.g., ::0) and unsupported addresses
    (e.g., addresses with unallocated prefixes).  For
    entities which are not IPv6 routers and therefore
    do not forward datagrams, this counter includes
    datagrams discarded because the destination address
    was not a local address."
    ::= { ipv6IfStatsEntry 5 }

ipv6IfStatsInUnknownProtos OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of locally-addressed datagrams
    received successfully but discarded because of an
    unknown or unsupported protocol. This counter is
    incremented at the interface to which these
    datagrams were addressed which might not be
    necessarily the input interface for some of
    the datagrams."
    ::= { ipv6IfStatsEntry 6 }

ipv6IfStatsInTruncatedPkts OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of input datagrams discarded because
     datagram frame didn't carry enough data."
    ::= { ipv6IfStatsEntry 7 }

ipv6IfStatsInDiscards OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of input IPv6 datagrams for which no
    problems were encountered to prevent their
    continued processing, but which were discarded
    (e.g., for lack of buffer space).  Note that this
    counter does not include any datagrams discarded
    while awaiting re-assembly."
    ::= { ipv6IfStatsEntry 8 }

ipv6IfStatsInDelivers OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
     "The total number of datagrams successfully
     delivered to IPv6 user-protocols (including ICMP).
     This counter is incremented at the interface to
     which these datagrams were addressed which might
     not be necessarily the input interface for some of
     the datagrams."
    ::= { ipv6IfStatsEntry 9 }

ipv6IfStatsOutForwDatagrams OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of output datagrams which this
    entity received and forwarded to their final
    destinations.  In entities which do not act
    as IPv6 routers, this counter will include
    only those packets which were Source-Routed
    via this entity, and the Source-Route
    processing was successful.  Note that for
    a successfully forwarded datagram the counter
    of the outgoing interface is incremented."
    ::= { ipv6IfStatsEntry 10 }

ipv6IfStatsOutRequests OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
     "The total number of IPv6 datagrams which local IPv6
     user-protocols (including ICMP) supplied to IPv6 in
     requests for transmission.	 Note that this counter
     does not include any datagrams counted in
     ipv6IfStatsOutForwDatagrams."
    ::= { ipv6IfStatsEntry 11 }

ipv6IfStatsOutDiscards OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
     "The number of output IPv6 datagrams for which no
     problem was encountered to prevent their
     transmission to their destination, but which were
     discarded (e.g., for lack of buffer space).  Note
     that this counter would include datagrams counted
     in ipv6IfStatsOutForwDatagrams if any such packets
     met this (discretionary) discard criterion."
    ::= { ipv6IfStatsEntry 12 }

ipv6IfStatsOutFragOKs OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of IPv6 datagrams that have been
     successfully fragmented at this output interface."
    ::= { ipv6IfStatsEntry 13 }

ipv6IfStatsOutFragFails OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of IPv6 datagrams that have been
     discarded because they needed to be fragmented
     at this output interface but could not be."
    ::= { ipv6IfStatsEntry 14 }

ipv6IfStatsOutFragCreates OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of output datagram fragments that have
     been generated as a result of fragmentation at
     this output interface."
    ::= { ipv6IfStatsEntry 15 }

ipv6IfStatsReasmReqds OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of IPv6 fragments received which needed
     to be reassembled at this interface.  Note that this
     counter is incremented at the interface to which
     these fragments were addressed which might not
     be necessarily the input interface for some of
     the fragments."
    ::= { ipv6IfStatsEntry 16 }

ipv6IfStatsReasmOKs OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The number of IPv6 datagrams successfully
      reassembled.  Note that this counter is incremented
      at the interface to which these datagrams were
      addressed which might not be necessarily the input
      interface for some of the fragments."
    ::= { ipv6IfStatsEntry 17 }

ipv6IfStatsReasmFails OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of failures detected by the IPv6 re-
    assembly algorithm (for whatever reason: timed
    out, errors, etc.).  Note that this is not
    necessarily a count of discarded IPv6 fragments
    since some algorithms (notably the algorithm in
    RFC 815) can lose track of the number of fragments
    by combining them as they are received.
    This counter is incremented at the interface to which
    these fragments were addressed which might not be
    necessarily the input interface for some of the
    fragments."
    ::= { ipv6IfStatsEntry 18 }

ipv6IfStatsInMcastPkts OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS     current
    DESCRIPTION
    "The number of multicast packets received
     by the interface"
    ::= { ipv6IfStatsEntry 19 }

ipv6IfStatsOutMcastPkts OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of multicast packets transmitted
     by the interface"
    ::= { ipv6IfStatsEntry 20 }

-- Address Prefix table

-- The IPv6 Address Prefix table contains information on
-- the entity's IPv6 Address Prefixes that are associated
-- with IPv6 interfaces.

ipv6AddrPrefixTable OBJECT-TYPE
    SYNTAX  SEQUENCE OF Ipv6AddrPrefixEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
     "The list of IPv6 address prefixes of
     IPv6 interfaces."
    ::= { ipv6MIBObjects 7 }

ipv6AddrPrefixEntry OBJECT-TYPE
    SYNTAX  Ipv6AddrPrefixEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
     "An interface entry containing objects of
     a particular IPv6 address prefix."
    INDEX   { ipv6IfIndex,
           ipv6AddrPrefix,
           ipv6AddrPrefixLength }
    ::= { ipv6AddrPrefixTable 1 }

Ipv6AddrPrefixEntry ::= SEQUENCE {
     ipv6AddrPrefix			Ipv6AddressPrefix,
     ipv6AddrPrefixLength		INTEGER (0..128),
     ipv6AddrPrefixOnLinkFlag		TruthValue,
     ipv6AddrPrefixAutonomousFlag	TruthValue,
     ipv6AddrPrefixAdvPreferredLifetime Unsigned32,
     ipv6AddrPrefixAdvValidLifetime	Unsigned32
    }

ipv6AddrPrefix OBJECT-TYPE
    SYNTAX	Ipv6AddressPrefix
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
      "The prefix associated with the this interface."
    ::= { ipv6AddrPrefixEntry 1 }

ipv6AddrPrefixLength OBJECT-TYPE
    SYNTAX	INTEGER (0..128)
    UNITS	"bits"
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
      "The length of the prefix (in bits)."
    ::= { ipv6AddrPrefixEntry 2 }

ipv6AddrPrefixOnLinkFlag OBJECT-TYPE
    SYNTAX	TruthValue
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "This object has the value 'true(1)', if this
      prefix can be used  for on-link determination
      and the value 'false(2)' otherwise."
    ::= { ipv6AddrPrefixEntry 3 }

ipv6AddrPrefixAutonomousFlag OBJECT-TYPE
    SYNTAX	TruthValue
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "Autonomous address configuration flag. When
      true(1), indicates that this prefix can be used
      for autonomous address configuration (i.e. can
      be used to form a local interface address).
      If false(2), it is not used to autoconfigure
      a local interface address."
    ::= { ipv6AddrPrefixEntry 4 }

ipv6AddrPrefixAdvPreferredLifetime OBJECT-TYPE
    SYNTAX	Unsigned32
    UNITS	"seconds"
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "It is the length of time in seconds that this
    prefix will remain preferred, i.e. time until
    deprecation.  A value of 4,294,967,295 represents
    infinity.

    The address generated from a deprecated prefix
    should no longer be used as a source address in
    new communications, but packets received on such
    an interface are processed as expected."
    ::= { ipv6AddrPrefixEntry 5 }

ipv6AddrPrefixAdvValidLifetime OBJECT-TYPE
    SYNTAX	Unsigned32
    UNITS	"seconds"
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "It is the length of time in seconds that this
      prefix will remain valid, i.e. time until
      invalidation.  A value of 4,294,967,295 represents
      infinity.

      The address generated from an invalidated prefix
      should not appear as the destination or source
      address of a packet."
    ::= { ipv6AddrPrefixEntry 6 }

-- the IPv6 Address table

-- The IPv6 address table contains this node's IPv6
-- addressing information.

ipv6AddrTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF Ipv6AddrEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
     "The table of addressing information relevant to
     this node's interface addresses."
   ::= { ipv6MIBObjects 8 }

ipv6AddrEntry OBJECT-TYPE
   SYNTAX      Ipv6AddrEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
    "The addressing information for one of this
    node's interface addresses."
   INDEX   { ipv6IfIndex, ipv6AddrAddress }
   ::= { ipv6AddrTable 1 }

Ipv6AddrEntry ::=
   SEQUENCE {
     ipv6AddrAddress	Ipv6Address,
     ipv6AddrPfxLength	INTEGER,
     ipv6AddrType		INTEGER,
     ipv6AddrAnycastFlag	TruthValue,
     ipv6AddrStatus		INTEGER
    }

ipv6AddrAddress OBJECT-TYPE
   SYNTAX      Ipv6Address
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
     "The IPv6 address to which this entry's addressing
     information pertains."
   ::= { ipv6AddrEntry 1 }

ipv6AddrPfxLength OBJECT-TYPE
   SYNTAX      INTEGER(0..128)
   UNITS       "bits"
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "The length of the prefix (in bits) associated with
     the IPv6 address of this entry."
   ::= { ipv6AddrEntry 2 }

ipv6AddrType OBJECT-TYPE
   SYNTAX      INTEGER {
            -- address has been formed
            -- using stateless
     stateless(1),	-- autoconfiguration

            -- address has been acquired
            -- by stateful means
            -- (e.g. DHCPv6, manual
     stateful(2),	-- configuration)

            -- type can not be determined
     unknown(3)	-- for some reason.
      }
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
      "The type of address. Note that 'stateless(1)'
      refers to an address that was statelessly
      autoconfigured; 'stateful(2)' refers to a address
      which was acquired by via a stateful protocol
      (e.g. DHCPv6, manual configuration)."
   ::= { ipv6AddrEntry 3 }

ipv6AddrAnycastFlag OBJECT-TYPE
    SYNTAX	TruthValue
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "This object has the value 'true(1)', if this
      address is an anycast address and the value
      'false(2)' otherwise."
    ::= { ipv6AddrEntry 4 }

ipv6AddrStatus OBJECT-TYPE
   SYNTAX      INTEGER {
         preferred(1),

         deprecated(2),

         invalid(3),

         inaccessible(4),

         unknown(5)	  -- status can not be determined
              -- for some reason.
        }
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
     "Address status.  The preferred(1) state indicates
     that this is a valid address that can appear as
     the destination or source address of a packet.
     The deprecated(2) state indicates that this is
     a valid but deprecated address that should no longer
     be used as a source address in new communications,
     but packets addressed to such an address are
     processed as expected. The invalid(3) state indicates
     that this is not valid address which should not
     appear as the destination or source address of
     a packet. The inaccessible(4) state indicates that
     the address is not accessible because the interface
     to which this address is assigned is not operational."
   ::= { ipv6AddrEntry 5 }

-- IPv6 Routing objects

ipv6RouteNumber OBJECT-TYPE
    SYNTAX	Gauge32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The number of current ipv6RouteTable entries.
      This is primarily to avoid having to read
      the table in order to determine this number."
    ::= { ipv6MIBObjects 9 }

ipv6DiscardedRoutes OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
      "The number of routing entries which were chosen
    to be discarded even though they are valid.  One
    possible reason for discarding such an entry could
    be to free-up buffer space for other routing
    entries."
    ::= { ipv6MIBObjects 10 }

-- IPv6 Routing table

ipv6RouteTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF Ipv6RouteEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "IPv6 Routing table. This table contains
      an entry for each valid IPv6 unicast route
      that can be used for packet forwarding
      determination."
    ::= { ipv6MIBObjects 11 }

ipv6RouteEntry OBJECT-TYPE
    SYNTAX     Ipv6RouteEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
         "A routing entry."
    INDEX   { ipv6RouteDest,
           ipv6RoutePfxLength,
           ipv6RouteIndex }
    ::= { ipv6RouteTable 1 }

Ipv6RouteEntry ::= SEQUENCE {
     ipv6RouteDest		 Ipv6Address,
     ipv6RoutePfxLength	 INTEGER,
     ipv6RouteIndex		 Unsigned32,
     ipv6RouteIfIndex	 Ipv6IfIndexOrZero,
     ipv6RouteNextHop	 Ipv6Address,
     ipv6RouteType		 INTEGER,
     ipv6RouteProtocol	 INTEGER,
     ipv6RoutePolicy	 Integer32,
     ipv6RouteAge		 Unsigned32,
     ipv6RouteNextHopRDI	 Unsigned32,
     ipv6RouteMetric	 Unsigned32,
     ipv6RouteWeight	 Unsigned32,
     ipv6RouteInfo		 RowPointer,
     ipv6RouteValid		 TruthValue
    }

ipv6RouteDest OBJECT-TYPE
    SYNTAX     Ipv6Address
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "The destination IPv6 address of this route.
      This object may not take a Multicast address
      value."
    ::= { ipv6RouteEntry 1 }

ipv6RoutePfxLength OBJECT-TYPE
    SYNTAX     INTEGER(0..128)
    UNITS      "bits"
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "Indicates the prefix length of the destination
      address."
    ::= { ipv6RouteEntry 2 }

ipv6RouteIndex OBJECT-TYPE
    SYNTAX     Unsigned32
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "The value which uniquely identifies the route
      among the routes to the same network layer
      destination.  The way this value is chosen is
      implementation specific but it must be unique for
      ipv6RouteDest/ipv6RoutePfxLength pair and remain
      constant for the life of the route."
    ::= { ipv6RouteEntry 3 }

ipv6RouteIfIndex OBJECT-TYPE
    SYNTAX     Ipv6IfIndexOrZero
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
      "The index value which uniquely identifies the local
      interface through which the next hop of this
      route should be reached.	The interface identified
      by a particular value of this index is the same
      interface as identified by the same value of
      ipv6IfIndex.  For routes of the discard type this
      value can be zero."
    ::= { ipv6RouteEntry 4 }

ipv6RouteNextHop OBJECT-TYPE
    SYNTAX     Ipv6Address
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
      "On remote routes, the address of the next
      system en route;	otherwise, ::0
      ('00000000000000000000000000000000'H in ASN.1
      string representation)."
    ::= { ipv6RouteEntry 5 }

ipv6RouteType OBJECT-TYPE
    SYNTAX     INTEGER {
    other(1),     -- none of the following

              -- an route indicating that
              -- packets to destinations
              -- matching this route are
    discard(2),   -- to be discarded

              -- route to directly
    local(3),     -- connected (sub-)network

              -- route to a remote
    remote(4)     -- destination

    }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The type of route. Note that 'local(3)' refers
    to a route for which the next hop is the final
    destination; 'remote(4)' refers to a route for
    which  the  next  hop is not the final
    destination; 'discard(2)' refers to a route
    indicating that packets to destinations matching
    this route are to be discarded (sometimes called
    black-hole route)."
    ::= { ipv6RouteEntry 6 }

ipv6RouteProtocol OBJECT-TYPE
    SYNTAX     INTEGER {
      other(1),	  -- none of the following

           -- non-protocol information,
           -- e.g., manually configured
      local(2),	  -- entries

      netmgmt(3), -- static route

           -- obtained via Neighbor
           -- Discovery protocol,
      ndisc(4),	  -- e.g., result of Redirect

           -- the following are all
           -- dynamic routing protocols
      rip(5),	  -- RIPng
      ospf(6),	  -- Open Shortest Path First
      bgp(7),	  -- Border Gateway Protocol
      idrp(8),	  -- InterDomain Routing Protocol
      igrp(9)	  -- InterGateway Routing Protocol
    }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
      "The routing mechanism via which this route was
      learned."
    ::= { ipv6RouteEntry 7 }

ipv6RoutePolicy OBJECT-TYPE
    SYNTAX     Integer32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
     "The general set of conditions that would cause the
     selection of one multipath route (set of next hops
     for a given destination) is referred to as 'policy'.
     Unless the mechanism indicated by ipv6RouteProtocol
     specified otherwise, the policy specifier is the
     8-bit Traffic Class field of the IPv6 packet header
     that is zero extended at the left to a 32-bit value.

     Protocols defining 'policy' otherwise must either
     define a set of values which are valid for
     this object or must implement an integer-
     instanced	policy table for which this object's
     value acts as an index."
    ::= { ipv6RouteEntry 8 }

ipv6RouteAge OBJECT-TYPE
    SYNTAX     Unsigned32
    UNITS      "seconds"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The number of seconds since this route was last
    updated or otherwise determined to be correct.
    Note that no semantics of `too old' can be implied
    except through knowledge of the routing protocol
    by which the route was learned."
    ::= { ipv6RouteEntry 9 }

ipv6RouteNextHopRDI OBJECT-TYPE
    SYNTAX     Unsigned32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The Routing Domain ID of the Next Hop.
    The  semantics of this object are determined by
    the routing-protocol specified in  the	route's
    ipv6RouteProtocol value.   When	 this object is
    unknown or not relevant its value should be set
    to zero."
    ::= { ipv6RouteEntry 10 }

ipv6RouteMetric OBJECT-TYPE
    SYNTAX     Unsigned32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The routing metric for this route. The
    semantics of this metric are determined by the
    routing protocol specified in the route's
    ipv6RouteProtocol value.  When this is unknown
    or not relevant to the protocol indicated by
    ipv6RouteProtocol, the object value should be
    set to its maximum value (4,294,967,295)."
    ::= { ipv6RouteEntry 11 }

ipv6RouteWeight OBJECT-TYPE
    SYNTAX     Unsigned32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "The system internal weight value for this route.
    The semantics of this value are determined by
    the implementation specific rules. Generally,
    within routes with the same ipv6RoutePolicy value,
    the lower the weight value the more preferred is
    the route."
    ::= { ipv6RouteEntry 12 }

ipv6RouteInfo OBJECT-TYPE
    SYNTAX     RowPointer
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
    "A reference to MIB definitions specific to the
    particular routing protocol which is responsible
    for this route, as determined by the  value
    specified  in the route's ipv6RouteProto value.
    If this information is not present,  its  value
    should be set to the OBJECT ID { 0 0 },
    which is a syntactically valid object  identifier,
    and any implementation conforming to ASN.1
    and the Basic Encoding Rules must  be  able  to
    generate and recognize this value."
    ::= { ipv6RouteEntry 13 }

ipv6RouteValid OBJECT-TYPE
    SYNTAX     TruthValue
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
    "Setting this object to the value 'false(2)' has
    the effect of invalidating the corresponding entry
    in the ipv6RouteTable object.  That is, it
    effectively disassociates the destination
    identified with said entry from the route
    identified with said entry.  It is an
    implementation-specific matter as to whether the
    agent removes an invalidated entry from the table.
    Accordingly, management stations must be prepared
    to receive tabular information from agents that
    corresponds to entries not currently in use.
    Proper interpretation of such entries requires
    examination of the relevant ipv6RouteValid
    object."
    DEFVAL  { true }
    ::= { ipv6RouteEntry 14 }

-- IPv6 Address Translation table

ipv6NetToMediaTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF Ipv6NetToMediaEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
      "The IPv6 Address Translation table used for
      mapping from IPv6 addresses to physical addresses.

      The IPv6 address translation table contain the
      Ipv6Address to `physical' address equivalencies.
      Some interfaces do not use translation tables
      for determining address equivalencies; if all
      interfaces are of this type, then the Address
      Translation table is empty, i.e., has zero
      entries."
    ::= { ipv6MIBObjects 12 }

ipv6NetToMediaEntry OBJECT-TYPE
    SYNTAX     Ipv6NetToMediaEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
      "Each entry contains one IPv6 address to `physical'
      address equivalence."
    INDEX   { ipv6IfIndex,
           ipv6NetToMediaNetAddress }
    ::= { ipv6NetToMediaTable 1 }

Ipv6NetToMediaEntry ::= SEQUENCE {
     ipv6NetToMediaNetAddress
         Ipv6Address,
     ipv6NetToMediaPhysAddress
         PhysAddress,
     ipv6NetToMediaType
         INTEGER,
     ipv6IfNetToMediaState
         INTEGER,
     ipv6IfNetToMediaLastUpdated
         TimeStamp,
     ipv6NetToMediaValid
         TruthValue
    }

ipv6NetToMediaNetAddress OBJECT-TYPE
    SYNTAX     Ipv6Address
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
    "The IPv6 Address corresponding to
    the media-dependent `physical' address."
    ::= { ipv6NetToMediaEntry 1 }

ipv6NetToMediaPhysAddress OBJECT-TYPE
    SYNTAX     PhysAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
      "The media-dependent `physical' address."
    ::= { ipv6NetToMediaEntry 2 }

ipv6NetToMediaType OBJECT-TYPE
    SYNTAX     INTEGER {
         other(1),    -- none of the following
         dynamic(2),  -- dynamically resolved
         static(3),   -- statically configured
         local(4)     -- local interface
        }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
         "The type of the mapping. The 'dynamic(2)' type
         indicates that the IPv6 address to physical
         addresses mapping has been dynamically
         resolved using the IPv6 Neighbor Discovery
         protocol. The static(3)' types indicates that
         the mapping has been statically configured.
         The local(4) indicates that the mapping is
         provided for an entity's own interface address."
    ::= { ipv6NetToMediaEntry 3 }

ipv6IfNetToMediaState OBJECT-TYPE
   SYNTAX      INTEGER {
         reachable(1), -- confirmed reachability

         stale(2),	   -- unconfirmed reachability

         delay(3),	   -- waiting for reachability
               -- confirmation before entering
               -- the probe state

         probe(4),	   -- actively probing

         invalid(5),   -- an invalidated mapping

         unknown(6)	   -- state can not be determined
               -- for some reason.
        }
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
    "The Neighbor Unreachability Detection [8] state
    for the interface when the address mapping in
    this entry is used."
   ::= { ipv6NetToMediaEntry 4 }

ipv6IfNetToMediaLastUpdated OBJECT-TYPE
   SYNTAX      TimeStamp
   MAX-ACCESS  read-only
   STATUS      current
   DESCRIPTION
    "The value of sysUpTime at the time this entry
    was last updated.  If this entry was updated prior
    to the last re-initialization of the local network
    management subsystem, then this object contains
    a zero value."
   ::= { ipv6NetToMediaEntry 5 }

ipv6NetToMediaValid OBJECT-TYPE
    SYNTAX     TruthValue
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
     "Setting this object to the value 'false(2)' has
     the effect of invalidating the corresponding entry
     in the ipv6NetToMediaTable.  That is, it effectively
     disassociates the interface identified with said
     entry from the mapping identified with said entry.
     It is an implementation-specific matter as to
     whether the agent removes an invalidated entry
     from the table.  Accordingly, management stations
     must be prepared to receive tabular information
     from agents that corresponds to entries not
     currently in use.	Proper interpretation of such
     entries requires examination of the relevant
     ipv6NetToMediaValid object."
    DEFVAL  { true }
    ::= { ipv6NetToMediaEntry 6 }

-- definition of IPv6-related notifications.
-- Note that we need ipv6NotificationPrefix with the 0
-- sub-identifier to make this MIB to translate to
-- an SNMPv1 format in a reversible way. For example
-- it is needed for proxies that convert SNMPv1 traps
-- to SNMPv2 notifications without MIB knowledge.

ipv6Notifications      OBJECT IDENTIFIER
    ::= { ipv6MIB 2 }
ipv6NotificationPrefix OBJECT IDENTIFIER
    ::= { ipv6Notifications 0 }

ipv6IfStateChange NOTIFICATION-TYPE
    OBJECTS {
          ipv6IfDescr,
          ipv6IfOperStatus -- the new state of the If.
         }
    STATUS	       current
    DESCRIPTION
    "An ipv6IfStateChange notification signifies
    that there has been a change in the state of
    an ipv6 interface.  This notification should
    be generated when the interface's operational
    status transitions to or from the up(1) state."
    ::= { ipv6NotificationPrefix 1 }

-- conformance information

ipv6Conformance OBJECT IDENTIFIER ::= { ipv6MIB 3 }

ipv6Compliances OBJECT IDENTIFIER ::= { ipv6Conformance 1 }
ipv6Groups	OBJECT IDENTIFIER ::= { ipv6Conformance 2 }

-- compliance statements

ipv6Compliance MODULE-COMPLIANCE
   STATUS  current
   DESCRIPTION
     "The compliance statement for SNMPv2 entities which
     implement ipv6 MIB."
   MODULE  -- this module
    MANDATORY-GROUPS { ipv6GeneralGroup,
               ipv6NotificationGroup }
      OBJECT    ipv6Forwarding
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6DefaultHopLimit
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6IfDescr
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6IfIdentifier
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6IfIdentifierLength
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6IfAdminStatus
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6RouteValid
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
      OBJECT    ipv6NetToMediaValid
        MIN-ACCESS	read-only
        DESCRIPTION
           "An agent is not required to provide write
        access to this object"
   ::= { ipv6Compliances 1 }

ipv6GeneralGroup OBJECT-GROUP
   OBJECTS { ipv6Forwarding,
          ipv6DefaultHopLimit,
          ipv6Interfaces,
          ipv6IfTableLastChange,
          ipv6IfDescr,
          ipv6IfLowerLayer,
          ipv6IfEffectiveMtu,
          ipv6IfReasmMaxSize,
          ipv6IfIdentifier,
          ipv6IfIdentifierLength,
          ipv6IfPhysicalAddress,
          ipv6IfAdminStatus,
          ipv6IfOperStatus,
          ipv6IfLastChange,
          ipv6IfStatsInReceives,
          ipv6IfStatsInHdrErrors,
          ipv6IfStatsInTooBigErrors,
          ipv6IfStatsInNoRoutes,
          ipv6IfStatsInAddrErrors,
          ipv6IfStatsInUnknownProtos,
          ipv6IfStatsInTruncatedPkts,
          ipv6IfStatsInDiscards,
          ipv6IfStatsInDelivers,
          ipv6IfStatsOutForwDatagrams,
          ipv6IfStatsOutRequests,
          ipv6IfStatsOutDiscards,
          ipv6IfStatsOutFragOKs,
          ipv6IfStatsOutFragFails,
          ipv6IfStatsOutFragCreates,
          ipv6IfStatsReasmReqds,
          ipv6IfStatsReasmOKs,
          ipv6IfStatsReasmFails,
          ipv6IfStatsInMcastPkts,
          ipv6IfStatsOutMcastPkts,
          ipv6AddrPrefixOnLinkFlag,
          ipv6AddrPrefixAutonomousFlag,
          ipv6AddrPrefixAdvPreferredLifetime,
          ipv6AddrPrefixAdvValidLifetime,
          ipv6AddrPfxLength,
          ipv6AddrType,
          ipv6AddrAnycastFlag,
          ipv6AddrStatus,
          ipv6RouteNumber,
          ipv6DiscardedRoutes,
          ipv6RouteIfIndex,
          ipv6RouteNextHop,
          ipv6RouteType,
          ipv6RouteProtocol,
          ipv6RoutePolicy,
          ipv6RouteAge,
          ipv6RouteNextHopRDI,
          ipv6RouteMetric,
          ipv6RouteWeight,
          ipv6RouteInfo,
          ipv6RouteValid,
          ipv6NetToMediaPhysAddress,
          ipv6NetToMediaType,
          ipv6IfNetToMediaState,
          ipv6IfNetToMediaLastUpdated,
          ipv6NetToMediaValid }
   STATUS    current
   DESCRIPTION
     "The IPv6 group of objects providing for basic
      management of IPv6 entities."
   ::= { ipv6Groups 1 }

ipv6NotificationGroup NOTIFICATION-GROUP
   NOTIFICATIONS { ipv6IfStateChange }
   STATUS    current
   DESCRIPTION
     "The notification that an IPv6 entity is required
      to implement."
   ::= { ipv6Groups 2 }

END


IPV6-TC DEFINITIONS ::= BEGIN

IMPORTS
     Integer32                FROM SNMPv2-SMI
     TEXTUAL-CONVENTION       FROM SNMPv2-TC;

-- definition of textual conventions
Ipv6Address ::= TEXTUAL-CONVENTION
     DISPLAY-HINT "2x:"
     STATUS       current
     DESCRIPTION
       "This data type is used to model IPv6 addresses.
    This is a binary string of 16 octets in network
    byte-order."
     SYNTAX       OCTET STRING (SIZE (16))

Ipv6AddressPrefix ::= TEXTUAL-CONVENTION
     DISPLAY-HINT "2x:"
     STATUS       current
     DESCRIPTION
       "This data type is used to model IPv6 address
       prefixes. This is a binary string of up to 16
       octets in network byte-order."
     SYNTAX       OCTET STRING (SIZE (0..16))

Ipv6AddressIfIdentifier ::= TEXTUAL-CONVENTION
     DISPLAY-HINT "2x:"
     STATUS       current
     DESCRIPTION
       "This data type is used to model IPv6 address
       interface identifiers. This is a binary string
    of up to 8 octets in network byte-order."
     SYNTAX      OCTET STRING (SIZE (0..8))

Ipv6IfIndex ::= TEXTUAL-CONVENTION
     DISPLAY-HINT "d"
     STATUS       current
     DESCRIPTION
       "A unique value, greater than zero for each
       internetwork-layer interface in the managed
       system. It is recommended that values are assigned
       contiguously starting from 1. The value for each
       internetwork-layer interface must remain constant
       at least from one re-initialization of the entity's
       network management system to the next
       re-initialization."
     SYNTAX       Integer32 (1..2147483647)

Ipv6IfIndexOrZero ::= TEXTUAL-CONVENTION
     DISPLAY-HINT "d"
     STATUS       current
     DESCRIPTION
     "This textual convention is an extension of the
     Ipv6IfIndex convention.  The latter defines
     a greater than zero value used to identify an IPv6
     interface in the managed system.  This extension
     permits the additional value of zero.  The value
     zero is object-specific and must therefore be
     defined as part of the description of any object
     which uses this syntax.  Examples of the usage of
     zero might include situations where interface was
     unknown, or when none or all interfaces need to be
     referenced."
     SYNTAX       Integer32 (0..2147483647)

END


IPV6-TCP-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-COMPLIANCE, OBJECT-GROUP      FROM SNMPv2-CONF
   MODULE-IDENTITY, OBJECT-TYPE,
   mib-2, experimental                  FROM SNMPv2-SMI
   Ipv6Address, Ipv6IfIndexOrZero       FROM IPV6-TC;

ipv6TcpMIB MODULE-IDENTITY
   LAST-UPDATED "9801290000Z"
   ORGANIZATION "IETF IPv6 MIB Working Group"
   CONTACT-INFO
        "       Mike Daniele

                Postal: Compaq Computer Corporation
                        110 Spitbrook Rd
                        Nashua, NH 03062.
                        US

                Phone:  +1 603 884 1423
                Email:  daniele@zk3.dec.com"
   DESCRIPTION
        "The MIB module for entities implementing TCP over IPv6."
   ::= { experimental 86 }

-- objects specific to TCP for IPv6

tcp      OBJECT IDENTIFIER ::= { mib-2 6 }

-- the TCP over IPv6 Connection table

-- This connection table contains information about this
-- entity's existing TCP connections between IPv6 endpoints.
-- Only connections between IPv6 addresses are contained in
-- this table.  This entity's connections between IPv4
-- endpoints are contained in tcpConnTable.

ipv6TcpConnTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF Ipv6TcpConnEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
        "A table containing TCP connection-specific information,
         for only those connections whose endpoints are IPv6 addresses."
   ::= { tcp 16 }

ipv6TcpConnEntry OBJECT-TYPE
   SYNTAX      Ipv6TcpConnEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
        "A conceptual row of the ipv6TcpConnTable containing
         information about a particular current TCP connection.
         Each row of this table is transient, in that it ceases to
         exist when (or soon after) the connection makes the transition
         to the CLOSED state.

         Note that conceptual rows in this table require an additional
         index object compared to tcpConnTable, since IPv6 addresses
         are not guaranteed to be unique on the managed node."
   INDEX   { ipv6TcpConnLocalAddress,
             ipv6TcpConnLocalPort,
             ipv6TcpConnRemAddress,
             ipv6TcpConnRemPort,
             ipv6TcpConnIfIndex }
   ::= { ipv6TcpConnTable 1 }

Ipv6TcpConnEntry ::=
   SEQUENCE { ipv6TcpConnLocalAddress    Ipv6Address,
              ipv6TcpConnLocalPort       INTEGER (0..65535),
              ipv6TcpConnRemAddress      Ipv6Address,
              ipv6TcpConnRemPort         INTEGER (0..65535),
              ipv6TcpConnIfIndex         Ipv6IfIndexOrZero,
              ipv6TcpConnState           INTEGER }

ipv6TcpConnLocalAddress OBJECT-TYPE
   SYNTAX     Ipv6Address
   MAX-ACCESS not-accessible
   STATUS     current
   DESCRIPTION
        "The local IPv6 address for this TCP connection. In
         the case of a connection in the listen state which
         is willing to accept connections for any IPv6
         address associated with the managed node, the value
         ::0 is used."
   ::= { ipv6TcpConnEntry 1 }

ipv6TcpConnLocalPort OBJECT-TYPE
   SYNTAX     INTEGER (0..65535)
   MAX-ACCESS not-accessible
   STATUS     current
   DESCRIPTION
        "The local port number for this TCP connection."
   ::= { ipv6TcpConnEntry 2 }

ipv6TcpConnRemAddress OBJECT-TYPE
   SYNTAX     Ipv6Address
   MAX-ACCESS not-accessible
   STATUS     current
   DESCRIPTION
        "The remote IPv6 address for this TCP connection."
   ::= { ipv6TcpConnEntry 3 }

ipv6TcpConnRemPort OBJECT-TYPE
   SYNTAX     INTEGER (0..65535)
   MAX-ACCESS not-accessible
   STATUS     current
   DESCRIPTION
        "The remote port number for this TCP connection."
   ::= { ipv6TcpConnEntry 4 }

ipv6TcpConnIfIndex OBJECT-TYPE
   SYNTAX     Ipv6IfIndexOrZero
   MAX-ACCESS not-accessible
   STATUS     current
   DESCRIPTION
        "An index object used to disambiguate conceptual rows in
         the table, since the connection 4-tuple may not be unique.

         If the connection's remote address (ipv6TcpConnRemAddress)
         is a link-local address and the connection's local address
         (ipv6TcpConnLocalAddress) is not a link-local address, this
         object identifies a local interface on the same link as
         the connection's remote link-local address.

         Otherwise, this object identifies the local interface that
         is associated with the ipv6TcpConnLocalAddress for this
         TCP connection.  If such a local interface cannot be determined,
         this object should take on the value 0.  (A possible example
         of this would be if the value of ipv6TcpConnLocalAddress is ::0.)

         The interface identified by a particular non-0 value of this
         index is the same interface as identified by the same value
         of ipv6IfIndex.

         The value of this object must remain constant during the life
         of the TCP connection."
   ::= { ipv6TcpConnEntry 5 }

ipv6TcpConnState OBJECT-TYPE
   SYNTAX     INTEGER {
        closed(1),
        listen(2),
        synSent(3),
        synReceived(4),
        established(5),
        finWait1(6),
        finWait2(7),
        closeWait(8),
        lastAck(9),
        closing(10),
        timeWait(11),
        deleteTCB(12) }
   MAX-ACCESS read-write
   STATUS     current
   DESCRIPTION
        "The state of this TCP connection.

         The only value which may be set by a management station is
         deleteTCB(12).  Accordingly, it is appropriate for an agent
         to return an error response (`badValue' for SNMPv1, 'wrongValue'
         for SNMPv2) if a management station attempts to set this
         object to any other value.

         If a management station sets this object to the value
         deleteTCB(12), then this has the effect of deleting the TCB
         (as defined in RFC 793) of the corresponding connection on
         the managed node, resulting in immediate termination of the
         connection.
         As an implementation-specific option, a RST segment may be
         sent from the managed node to the other TCP endpoint (note
         however that RST segments are not sent reliably)."
   ::= { ipv6TcpConnEntry 6 }

--
-- conformance information
--

ipv6TcpConformance OBJECT IDENTIFIER ::= { ipv6TcpMIB 2 }

ipv6TcpCompliances OBJECT IDENTIFIER ::= { ipv6TcpConformance 1 }
ipv6TcpGroups      OBJECT IDENTIFIER ::= { ipv6TcpConformance 2 }

-- compliance statements

ipv6TcpCompliance MODULE-COMPLIANCE
   STATUS  current
   DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement TCP over IPv6."
   MODULE  -- this module
   MANDATORY-GROUPS { ipv6TcpGroup }
   ::= { ipv6TcpCompliances 1 }

ipv6TcpGroup OBJECT-GROUP
   OBJECTS   { -- these are defined in this module
               -- ipv6TcpConnLocalAddress (not-accessible)
               -- ipv6TcpConnLocalPort (not-accessible)
               -- ipv6TcpConnRemAddress (not-accessible)
               -- ipv6TcpConnRemPort (not-accessible)
               -- ipv6TcpConnIfIndex (not-accessible)
               ipv6TcpConnState }
   STATUS    current
   DESCRIPTION
        "The group of objects providing management of
         TCP over IPv6."
   ::= { ipv6TcpGroups 1 }

END


IPV6-UDP-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-COMPLIANCE, OBJECT-GROUP      FROM SNMPv2-CONF
   MODULE-IDENTITY, OBJECT-TYPE,
   mib-2, experimental                  FROM SNMPv2-SMI
   Ipv6Address, Ipv6IfIndexOrZero       FROM IPV6-TC;

ipv6UdpMIB MODULE-IDENTITY
   LAST-UPDATED "9801290000Z"
   ORGANIZATION "IETF IPv6 MIB Working Group"
   CONTACT-INFO
        "               Mike Daniele

                Postal: Compaq Computer Corporation
                        110 Spitbrook Rd
                        Nashua, NH 03062.
                        US

                Phone:  +1 603 884 1423
                Email:  daniele@zk3.dec.com"
   DESCRIPTION
        "The MIB module for entities implementing UDP over IPv6."
   ::= { experimental 87 }

-- objects specific to UDP for IPv6

udp      OBJECT IDENTIFIER ::= { mib-2 7 }

-- the UDP over IPv6 Listener table

-- This table contains information about this entity's
-- UDP/IPv6 endpoints.  Only endpoints utilizing IPv6 addresses
-- are contained in this table.  This entity's UDP/IPv4 endpoints
-- are contained in udpTable.

ipv6UdpTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF Ipv6UdpEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
        "A table containing UDP listener information for
         UDP/IPv6 endpoints."
   ::= { udp 6 }

ipv6UdpEntry OBJECT-TYPE
   SYNTAX      Ipv6UdpEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
        "Information about a particular current UDP listener.

         Note that conceptual rows in this table require an
         additional index object compared to udpTable, since
         IPv6 addresses are not guaranteed to be unique on the
         managed node."
   INDEX   { ipv6UdpLocalAddress,
             ipv6UdpLocalPort,
             ipv6UdpIfIndex }
   ::= { ipv6UdpTable 1 }

Ipv6UdpEntry ::= SEQUENCE {
   ipv6UdpLocalAddress    Ipv6Address,
   ipv6UdpLocalPort       INTEGER (0..65535),
   ipv6UdpIfIndex         Ipv6IfIndexOrZero }

ipv6UdpLocalAddress OBJECT-TYPE
   SYNTAX       Ipv6Address
   MAX-ACCESS   not-accessible
   STATUS       current
   DESCRIPTION
        "The local IPv6 address for this UDP listener.
         In the case of a UDP listener which is willing
         to accept datagrams for any IPv6 address
         associated with the managed node, the value ::0
         is used."
   ::= { ipv6UdpEntry 1 }

ipv6UdpLocalPort OBJECT-TYPE
    SYNTAX     INTEGER (0..65535)
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The local port number for this UDP listener."
    ::= { ipv6UdpEntry 2 }

ipv6UdpIfIndex OBJECT-TYPE
   SYNTAX     Ipv6IfIndexOrZero
   MAX-ACCESS   read-only
   STATUS     current
   DESCRIPTION
        "An index object used to disambiguate conceptual rows in
         the table, since the ipv6UdpLocalAddress/ipv6UdpLocalPort
         pair may not be unique.

         This object identifies the local interface that is
         associated with ipv6UdpLocalAddress for this UDP listener.
         If such a local interface cannot be determined, this object
         should take on the value 0.  (A possible example of this
         would be if the value of ipv6UdpLocalAddress is ::0.)

         The interface identified by a particular non-0 value of
         this index is the same interface as identified by the same
         value of ipv6IfIndex.

         The value of this object must remain constant during
         the life of this UDP endpoint."
   ::= { ipv6UdpEntry 3 }

--
-- conformance information
--

ipv6UdpConformance OBJECT IDENTIFIER ::= { ipv6UdpMIB 2 }

ipv6UdpCompliances OBJECT IDENTIFIER ::= { ipv6UdpConformance 1 }
ipv6UdpGroups      OBJECT IDENTIFIER ::= { ipv6UdpConformance 2 }

-- compliance statements

ipv6UdpCompliance MODULE-COMPLIANCE
   STATUS  current
   DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement UDP over IPv6."
   MODULE  -- this module
   MANDATORY-GROUPS { ipv6UdpGroup }
   ::= { ipv6UdpCompliances 1 }

ipv6UdpGroup OBJECT-GROUP
   OBJECTS   { -- these are defined in this module
               -- ipv6UdpLocalAddress (not-accessible)
               -- ipv6UdpLocalPort (not-accessible)
               ipv6UdpIfIndex }
   STATUS    current
   DESCRIPTION
        "The group of objects providing management of
         UDP over IPv6."
   ::= { ipv6UdpGroups 1 }

END


RFC1155-SMI DEFINITIONS ::= BEGIN
    nullOID       OBJECT IDENTIFIER ::= { ccitt 0 }
    internet      OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 }
    directory     OBJECT IDENTIFIER ::= { internet 1 }
    mgmt          OBJECT IDENTIFIER ::= { internet 2 }
    experimental  OBJECT IDENTIFIER ::= { internet 3 }
    private       OBJECT IDENTIFIER ::= { internet 4 }
    enterprises   OBJECT IDENTIFIER ::= { private 1 }
END


RFC1213-MIB DEFINITIONS ::= BEGIN

          IMPORTS
                  mgmt, NetworkAddress, IpAddress, Counter, Gauge,
                          TimeTicks
                      FROM RFC1155-SMI
                  OBJECT-TYPE
                          FROM RFC-1212;

          --  This MIB module uses the extended OBJECT-TYPE macro as
          --  defined in [14];

          --  MIB-II (same prefix as MIB-I)

          mib-2      OBJECT IDENTIFIER ::= { mgmt 1 }

          -- textual conventions

          DisplayString ::=
              OCTET STRING
          -- This data type is used to model textual information taken
          -- from the NVT ASCII character set.  By convention, objects
          -- with this syntax are declared as having

          --
          --      SIZE (0..255)

          PhysAddress ::=
              OCTET STRING
          -- This data type is used to model media addresses.  For many
          -- types of media, this will be in a binary representation.
          -- For example, an ethernet address would be represented as
          -- a string of 6 octets.

          -- groups in MIB-II

          system       OBJECT IDENTIFIER ::= { mib-2 1 }

          interfaces   OBJECT IDENTIFIER ::= { mib-2 2 }

          at           OBJECT IDENTIFIER ::= { mib-2 3 }

          ip           OBJECT IDENTIFIER ::= { mib-2 4 }

          icmp         OBJECT IDENTIFIER ::= { mib-2 5 }

          tcp          OBJECT IDENTIFIER ::= { mib-2 6 }

          udp          OBJECT IDENTIFIER ::= { mib-2 7 }

          egp          OBJECT IDENTIFIER ::= { mib-2 8 }

          -- historical (some say hysterical)
          -- cmot      OBJECT IDENTIFIER ::= { mib-2 9 }

          transmission OBJECT IDENTIFIER ::= { mib-2 10 }

          snmp         OBJECT IDENTIFIER ::= { mib-2 11 }

          -- the System group

          -- Implementation of the System group is mandatory for all
          -- systems.  If an agent is not configured to have a value
          -- for any of these variables, a string of length 0 is
          -- returned.

          sysDescr OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "A textual description of the entity.  This value
                      should include the full name and version
                      identification of the system's hardware type,
                      software operating-system, and networking
                      software.  It is mandatory that this only contain
                      printable ASCII characters."
              ::= { system 1 }

          sysObjectID OBJECT-TYPE
              SYNTAX  OBJECT IDENTIFIER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The vendor's authoritative identification of the
                      network management subsystem contained in the
                      entity.  This value is allocated within the SMI
                      enterprises subtree (1.3.6.1.4.1) and provides an
                      easy and unambiguous means for determining `what
                      kind of box' is being managed.  For example, if
                      vendor `Flintstones, Inc.' was assigned the
                      subtree 1.3.6.1.4.1.4242, it could assign the
                      identifier 1.3.6.1.4.1.4242.1.1 to its `Fred
                      Router'."
              ::= { system 2 }

          sysUpTime OBJECT-TYPE
              SYNTAX  TimeTicks
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The time (in hundredths of a second) since the
                      network management portion of the system was last
                      re-initialized."
              ::= { system 3 }

          sysContact OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The textual identification of the contact person
                      for this managed node, together with information
                      on how to contact this person."
              ::= { system 4 }

          sysName OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))

              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "An administratively-assigned name for this
                      managed node.  By convention, this is the node's
                      fully-qualified domain name."
              ::= { system 5 }

          sysLocation OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The physical location of this node (e.g.,
                      `telephone closet, 3rd floor')."
              ::= { system 6 }

          sysServices OBJECT-TYPE
              SYNTAX  INTEGER (0..127)
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "A value which indicates the set of services that
                      this entity primarily offers.

                      The value is a sum.  This sum initially takes the
                      value zero, Then, for each layer, L, in the range
                      1 through 7, that this node performs transactions
                      for, 2 raised to (L - 1) is added to the sum.  For
                      example, a node which performs primarily routing
                      functions would have a value of 4 (2^(3-1)).  In
                      contrast, a node which is a host offering
                      application services would have a value of 72
                      (2^(4-1) + 2^(7-1)).  Note that in the context of
                      the Internet suite of protocols, values should be
                      calculated accordingly:

                           layer  functionality
                               1  physical (e.g., repeaters)
                               2  datalink/subnetwork (e.g., bridges)
                               3  internet (e.g., IP gateways)
                               4  end-to-end  (e.g., IP hosts)
                               7  applications (e.g., mail relays)

                      For systems including OSI protocols, layers 5 and
                      6 may also be counted."
              ::= { system 7 }

          -- the Interfaces group

          -- Implementation of the Interfaces group is mandatory for
          -- all systems.

          ifNumber OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of network interfaces (regardless of
                      their current state) present on this system."
              ::= { interfaces 1 }

          -- the Interfaces table

          -- The Interfaces table contains information on the entity's
          -- interfaces.  Each interface is thought of as being
          -- attached to a `subnetwork'.  Note that this term should
          -- not be confused with `subnet' which refers to an
          -- addressing partitioning scheme used in the Internet suite
          -- of protocols.

          ifTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF IfEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "A list of interface entries.  The number of
                      entries is given by the value of ifNumber."
              ::= { interfaces 2 }

          ifEntry OBJECT-TYPE
              SYNTAX  IfEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "An interface entry containing objects at the
                      subnetwork layer and below for a particular
                      interface."
              INDEX   { ifIndex }
              ::= { ifTable 1 }

          IfEntry ::=
              SEQUENCE {
                  ifIndex
                      INTEGER,

                  ifDescr
                      DisplayString,
                  ifType
                      INTEGER,
                  ifMtu
                      INTEGER,
                  ifSpeed
                      Gauge,
                  ifPhysAddress
                      PhysAddress,
                  ifAdminStatus
                      INTEGER,
                  ifOperStatus
                      INTEGER,
                  ifLastChange
                      TimeTicks,
                  ifInOctets
                      Counter,
                  ifInUcastPkts
                      Counter,
                  ifInNUcastPkts
                      Counter,
                  ifInDiscards
                      Counter,
                  ifInErrors
                      Counter,
                  ifInUnknownProtos
                      Counter,
                  ifOutOctets
                      Counter,
                  ifOutUcastPkts
                      Counter,
                  ifOutNUcastPkts
                      Counter,
                  ifOutDiscards
                      Counter,
                  ifOutErrors
                      Counter,
                  ifOutQLen
                      Gauge,
                  ifSpecific
                      OBJECT IDENTIFIER
              }

          ifIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "A unique value for each interface.  Its value
                      ranges between 1 and the value of ifNumber.  The
                      value for each interface must remain constant at
                      least from one re-initialization of the entity's
                      network management system to the next re-
                      initialization."
              ::= { ifEntry 1 }

          ifDescr OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "A textual string containing information about the
                      interface.  This string should include the name of
                      the manufacturer, the product name and the version
                      of the hardware interface."
              ::= { ifEntry 2 }

          ifType OBJECT-TYPE
              SYNTAX  INTEGER {
                          other(1),          -- none of the following
                          regular1822(2),
                          hdh1822(3),
                          ddn-x25(4),
                          rfc877-x25(5),
                          ethernet-csmacd(6),
                          iso88023-csmacd(7),
                          iso88024-tokenBus(8),
                          iso88025-tokenRing(9),
                          iso88026-man(10),
                          starLan(11),
                          proteon-10Mbit(12),
                          proteon-80Mbit(13),
                          hyperchannel(14),
                          fddi(15),
                          lapb(16),
                          sdlc(17),
                          ds1(18),           -- T-1
                          e1(19),            -- european equiv. of T-1
                          basicISDN(20),
                          primaryISDN(21),   -- proprietary serial
                          propPointToPointSerial(22),
                          ppp(23),
                          softwareLoopback(24),
                          eon(25),            -- CLNP over IP [11]
                          ethernet-3Mbit(26),

                          nsip(27),           -- XNS over IP
                          slip(28),           -- generic SLIP
                          ultra(29),          -- ULTRA technologies
                          ds3(30),            -- T-3
                          sip(31),            -- SMDS
                          frame-relay(32)
                      }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The type of interface, distinguished according to
                      the physical/link protocol(s) immediately `below'
                      the network layer in the protocol stack."
              ::= { ifEntry 3 }

          ifMtu OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The size of the largest datagram which can be
                      sent/received on the interface, specified in
                      octets.  For interfaces that are used for
                      transmitting network datagrams, this is the size
                      of the largest network datagram that can be sent
                      on the interface."
              ::= { ifEntry 4 }

          ifSpeed OBJECT-TYPE
              SYNTAX  Gauge
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "An estimate of the interface's current bandwidth
                      in bits per second.  For interfaces which do not
                      vary in bandwidth or for those where no accurate
                      estimation can be made, this object should contain
                      the nominal bandwidth."
              ::= { ifEntry 5 }

          ifPhysAddress OBJECT-TYPE
              SYNTAX  PhysAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The interface's address at the protocol layer
                      immediately `below' the network layer in the
                      protocol stack.  For interfaces which do not have

                      such an address (e.g., a serial line), this object
                      should contain an octet string of zero length."
              ::= { ifEntry 6 }

          ifAdminStatus OBJECT-TYPE
              SYNTAX  INTEGER {
                          up(1),       -- ready to pass packets
                          down(2),
                          testing(3)   -- in some test mode
                      }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The desired state of the interface.  The
                      testing(3) state indicates that no operational
                      packets can be passed."
              ::= { ifEntry 7 }

          ifOperStatus OBJECT-TYPE
              SYNTAX  INTEGER {
                          up(1),       -- ready to pass packets
                          down(2),
                          testing(3)   -- in some test mode
                      }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The current operational state of the interface.
                      The testing(3) state indicates that no operational
                      packets can be passed."
              ::= { ifEntry 8 }

          ifLastChange OBJECT-TYPE
              SYNTAX  TimeTicks
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The value of sysUpTime at the time the interface
                      entered its current operational state.  If the
                      current state was entered prior to the last re-
                      initialization of the local network management
                      subsystem, then this object contains a zero
                      value."
              ::= { ifEntry 9 }

          ifInOctets OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only

              STATUS  mandatory
              DESCRIPTION
                      "The total number of octets received on the
                      interface, including framing characters."
              ::= { ifEntry 10 }

          ifInUcastPkts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of subnetwork-unicast packets
                      delivered to a higher-layer protocol."
              ::= { ifEntry 11 }

          ifInNUcastPkts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of non-unicast (i.e., subnetwork-
                      broadcast or subnetwork-multicast) packets
                      delivered to a higher-layer protocol."
              ::= { ifEntry 12 }

          ifInDiscards OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of inbound packets which were chosen
                      to be discarded even though no errors had been
                      detected to prevent their being deliverable to a
                      higher-layer protocol.  One possible reason for
                      discarding such a packet could be to free up
                      buffer space."
              ::= { ifEntry 13 }

          ifInErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of inbound packets that contained
                      errors preventing them from being deliverable to a
                      higher-layer protocol."
              ::= { ifEntry 14 }

          ifInUnknownProtos OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of packets received via the interface
                      which were discarded because of an unknown or
                      unsupported protocol."
              ::= { ifEntry 15 }

          ifOutOctets OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of octets transmitted out of the
                      interface, including framing characters."
              ::= { ifEntry 16 }

          ifOutUcastPkts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of packets that higher-level
                      protocols requested be transmitted to a
                      subnetwork-unicast address, including those that
                      were discarded or not sent."
              ::= { ifEntry 17 }

          ifOutNUcastPkts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of packets that higher-level
                      protocols requested be transmitted to a non-
                      unicast (i.e., a subnetwork-broadcast or
                      subnetwork-multicast) address, including those
                      that were discarded or not sent."
              ::= { ifEntry 18 }

          ifOutDiscards OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of outbound packets which were chosen

                      to be discarded even though no errors had been
                      detected to prevent their being transmitted.  One
                      possible reason for discarding such a packet could
                      be to free up buffer space."
              ::= { ifEntry 19 }

          ifOutErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of outbound packets that could not be
                      transmitted because of errors."
              ::= { ifEntry 20 }

          ifOutQLen OBJECT-TYPE
              SYNTAX  Gauge
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The length of the output packet queue (in
                      packets)."
              ::= { ifEntry 21 }

          ifSpecific OBJECT-TYPE
              SYNTAX  OBJECT IDENTIFIER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "A reference to MIB definitions specific to the
                      particular media being used to realize the
                      interface.  For example, if the interface is
                      realized by an ethernet, then the value of this
                      object refers to a document defining objects
                      specific to ethernet.  If this information is not
                      present, its value should be set to the OBJECT
                      IDENTIFIER { 0 0 }, which is a syntatically valid
                      object identifier, and any conformant
                      implementation of ASN.1 and BER must be able to
                      generate and recognize this value."
              ::= { ifEntry 22 }

          -- the Address Translation group

          -- Implementation of the Address Translation group is
          -- mandatory for all systems.  Note however that this group
          -- is deprecated by MIB-II. That is, it is being included

          -- solely for compatibility with MIB-I nodes, and will most
          -- likely be excluded from MIB-III nodes.  From MIB-II and
          -- onwards, each network protocol group contains its own
          -- address translation tables.

          -- The Address Translation group contains one table which is
          -- the union across all interfaces of the translation tables
          -- for converting a NetworkAddress (e.g., an IP address) into
          -- a subnetwork-specific address.  For lack of a better term,
          -- this document refers to such a subnetwork-specific address
          -- as a `physical' address.

          -- Examples of such translation tables are: for broadcast
          -- media where ARP is in use, the translation table is
          -- equivalent to the ARP cache; or, on an X.25 network where
          -- non-algorithmic translation to X.121 addresses is
          -- required, the translation table contains the
          -- NetworkAddress to X.121 address equivalences.

          atTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF AtEntry
              ACCESS  not-accessible
              STATUS  deprecated
              DESCRIPTION
                      "The Address Translation tables contain the
                      NetworkAddress to `physical' address equivalences.
                      Some interfaces do not use translation tables for
                      determining address equivalences (e.g., DDN-X.25
                      has an algorithmic method); if all interfaces are
                      of this type, then the Address Translation table
                      is empty, i.e., has zero entries."
              ::= { at 1 }

          atEntry OBJECT-TYPE
              SYNTAX  AtEntry
              ACCESS  not-accessible
              STATUS  deprecated
              DESCRIPTION
                      "Each entry contains one NetworkAddress to
                      `physical' address equivalence."
              INDEX   { atIfIndex,
                        atNetAddress }
              ::= { atTable 1 }

          AtEntry ::=
              SEQUENCE {
                  atIfIndex
                      INTEGER,

                  atPhysAddress
                      PhysAddress,
                  atNetAddress
                      NetworkAddress
              }

          atIfIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  deprecated
              DESCRIPTION
                      "The interface on which this entry's equivalence
                      is effective.  The interface identified by a
                      particular value of this index is the same
                      interface as identified by the same value of
                      ifIndex."
              ::= { atEntry 1 }

          atPhysAddress OBJECT-TYPE
              SYNTAX  PhysAddress
              ACCESS  read-write
              STATUS  deprecated
              DESCRIPTION
                      "The media-dependent `physical' address.

                      Setting this object to a null string (one of zero
                      length) has the effect of invaliding the
                      corresponding entry in the atTable object.  That
                      is, it effectively dissasociates the interface
                      identified with said entry from the mapping
                      identified with said entry.  It is an
                      implementation-specific matter as to whether the
                      agent removes an invalidated entry from the table.
                      Accordingly, management stations must be prepared
                      to receive tabular information from agents that
                      corresponds to entries not currently in use.
                      Proper interpretation of such entries requires
                      examination of the relevant atPhysAddress object."
              ::= { atEntry 2 }

          atNetAddress OBJECT-TYPE
              SYNTAX  NetworkAddress
              ACCESS  read-write
              STATUS  deprecated
              DESCRIPTION
                      "The NetworkAddress (e.g., the IP address)
                      corresponding to the media-dependent `physical'
                      address."

              ::= { atEntry 3 }

          -- the IP group

          -- Implementation of the IP group is mandatory for all
          -- systems.

          ipForwarding OBJECT-TYPE
              SYNTAX  INTEGER {
                          forwarding(1),    -- acting as a gateway
                          not-forwarding(2) -- NOT acting as a gateway
                      }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The indication of whether this entity is acting
                      as an IP gateway in respect to the forwarding of
                      datagrams received by, but not addressed to, this
                      entity.  IP gateways forward datagrams.  IP hosts
                      do not (except those source-routed via the host).

                      Note that for some managed nodes, this object may
                      take on only a subset of the values possible.
                      Accordingly, it is appropriate for an agent to
                      return a `badValue' response if a management
                      station attempts to change this object to an
                      inappropriate value."
              ::= { ip 1 }

          ipDefaultTTL OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The default value inserted into the Time-To-Live
                      field of the IP header of datagrams originated at
                      this entity, whenever a TTL value is not supplied
                      by the transport layer protocol."
              ::= { ip 2 }

          ipInReceives OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of input datagrams received from
                      interfaces, including those received in error."

              ::= { ip 3 }

          ipInHdrErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of input datagrams discarded due to
                      errors in their IP headers, including bad
                      checksums, version number mismatch, other format
                      errors, time-to-live exceeded, errors discovered
                      in processing their IP options, etc."
              ::= { ip 4 }

          ipInAddrErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of input datagrams discarded because
                      the IP address in their IP header's destination
                      field was not a valid address to be received at
                      this entity.  This count includes invalid
                      addresses (e.g., 0.0.0.0) and addresses of
                      unsupported Classes (e.g., Class E).  For entities
                      which are not IP Gateways and therefore do not
                      forward datagrams, this counter includes datagrams
                      discarded because the destination address was not
                      a local address."
              ::= { ip 5 }

          ipForwDatagrams OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of input datagrams for which this
                      entity was not their final IP destination, as a
                      result of which an attempt was made to find a
                      route to forward them to that final destination.
                      In entities which do not act as IP Gateways, this
                      counter will include only those packets which were
                      Source-Routed via this entity, and the Source-
                      Route option processing was successful."
              ::= { ip 6 }

          ipInUnknownProtos OBJECT-TYPE
              SYNTAX  Counter

              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of locally-addressed datagrams
                      received successfully but discarded because of an
                      unknown or unsupported protocol."
              ::= { ip 7 }

          ipInDiscards OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of input IP datagrams for which no
                      problems were encountered to prevent their
                      continued processing, but which were discarded
                      (e.g., for lack of buffer space).  Note that this
                      counter does not include any datagrams discarded
                      while awaiting re-assembly."
              ::= { ip 8 }

          ipInDelivers OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of input datagrams successfully
                      delivered to IP user-protocols (including ICMP)."
              ::= { ip 9 }

          ipOutRequests OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of IP datagrams which local IP
                      user-protocols (including ICMP) supplied to IP in
                      requests for transmission.  Note that this counter
                      does not include any datagrams counted in
                      ipForwDatagrams."
              ::= { ip 10 }

          ipOutDiscards OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of output IP datagrams for which no

                      problem was encountered to prevent their
                      transmission to their destination, but which were
                      discarded (e.g., for lack of buffer space).  Note
                      that this counter would include datagrams counted
                      in ipForwDatagrams if any such packets met this
                      (discretionary) discard criterion."
              ::= { ip 11 }

          ipOutNoRoutes OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP datagrams discarded because no
                      route could be found to transmit them to their
                      destination.  Note that this counter includes any
                      packets counted in ipForwDatagrams which meet this
                      `no-route' criterion.  Note that this includes any
                      datagarms which a host cannot route because all of
                      its default gateways are down."
              ::= { ip 12 }

          ipReasmTimeout OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The maximum number of seconds which received
                      fragments are held while they are awaiting
                      reassembly at this entity."
              ::= { ip 13 }

          ipReasmReqds OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP fragments received which needed
                      to be reassembled at this entity."
              ::= { ip 14 }

          ipReasmOKs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP datagrams successfully re-
                      assembled."

              ::= { ip 15 }

          ipReasmFails OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of failures detected by the IP re-
                      assembly algorithm (for whatever reason: timed
                      out, errors, etc).  Note that this is not
                      necessarily a count of discarded IP fragments
                      since some algorithms (notably the algorithm in
                      RFC 815) can lose track of the number of fragments
                      by combining them as they are received."
              ::= { ip 16 }

          ipFragOKs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP datagrams that have been
                      successfully fragmented at this entity."
              ::= { ip 17 }

          ipFragFails OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP datagrams that have been
                      discarded because they needed to be fragmented at
                      this entity but could not be, e.g., because their
                      Don't Fragment flag was set."
              ::= { ip 18 }

          ipFragCreates OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of IP datagram fragments that have
                      been generated as a result of fragmentation at
                      this entity."
              ::= { ip 19 }

          -- the IP address table

          -- The IP address table contains this entity's IP addressing
          -- information.

          ipAddrTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF IpAddrEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "The table of addressing information relevant to
                      this entity's IP addresses."
              ::= { ip 20 }

          ipAddrEntry OBJECT-TYPE
              SYNTAX  IpAddrEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "The addressing information for one of this
                      entity's IP addresses."
              INDEX   { ipAdEntAddr }
              ::= { ipAddrTable 1 }

          IpAddrEntry ::=
              SEQUENCE {
                  ipAdEntAddr
                      IpAddress,
                  ipAdEntIfIndex
                      INTEGER,
                  ipAdEntNetMask
                      IpAddress,
                  ipAdEntBcastAddr
                      INTEGER,
                  ipAdEntReasmMaxSize
                      INTEGER (0..65535)
              }

          ipAdEntAddr OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The IP address to which this entry's addressing
                      information pertains."
              ::= { ipAddrEntry 1 }

          ipAdEntIfIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The index value which uniquely identifies the
                      interface to which this entry is applicable.  The
                      interface identified by a particular value of this
                      index is the same interface as identified by the
                      same value of ifIndex."
              ::= { ipAddrEntry 2 }

          ipAdEntNetMask OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The subnet mask associated with the IP address of
                      this entry.  The value of the mask is an IP
                      address with all the network bits set to 1 and all
                      the hosts bits set to 0."
              ::= { ipAddrEntry 3 }

          ipAdEntBcastAddr OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The value of the least-significant bit in the IP
                      broadcast address used for sending datagrams on
                      the (logical) interface associated with the IP
                      address of this entry.  For example, when the
                      Internet standard all-ones broadcast address is
                      used, the value will be 1.  This value applies to
                      both the subnet and network broadcasts addresses
                      used by the entity on this (logical) interface."
              ::= { ipAddrEntry 4 }

          ipAdEntReasmMaxSize OBJECT-TYPE
              SYNTAX  INTEGER (0..65535)
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The size of the largest IP datagram which this
                      entity can re-assemble from incoming IP fragmented
                      datagrams received on this interface."
              ::= { ipAddrEntry 5 }

          -- the IP routing table

          -- The IP routing table contains an entry for each route
          -- presently known to this entity.

          ipRouteTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF IpRouteEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "This entity's IP Routing table."
              ::= { ip 21 }

          ipRouteEntry OBJECT-TYPE
              SYNTAX  IpRouteEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "A route to a particular destination."
              INDEX   { ipRouteDest }
              ::= { ipRouteTable 1 }

          IpRouteEntry ::=
              SEQUENCE {
                  ipRouteDest
                      IpAddress,
                  ipRouteIfIndex
                      INTEGER,
                  ipRouteMetric1
                      INTEGER,
                  ipRouteMetric2
                      INTEGER,
                  ipRouteMetric3
                      INTEGER,
                  ipRouteMetric4
                      INTEGER,
                  ipRouteNextHop
                      IpAddress,
                  ipRouteType
                      INTEGER,
                  ipRouteProto
                      INTEGER,
                  ipRouteAge
                      INTEGER,
                  ipRouteMask
                      IpAddress,
                  ipRouteMetric5
                      INTEGER,

                  ipRouteInfo
                      OBJECT IDENTIFIER
              }

          ipRouteDest OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The destination IP address of this route.  An
                      entry with a value of 0.0.0.0 is considered a
                      default route.  Multiple routes to a single
                      destination can appear in the table, but access to
                      such multiple entries is dependent on the table-
                      access mechanisms defined by the network
                      management protocol in use."
              ::= { ipRouteEntry 1 }

          ipRouteIfIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The index value which uniquely identifies the
                      local interface through which the next hop of this
                      route should be reached.  The interface identified
                      by a particular value of this index is the same
                      interface as identified by the same value of
                      ifIndex."
              ::= { ipRouteEntry 2 }

          ipRouteMetric1 OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The primary routing metric for this route.  The
                      semantics of this metric are determined by the
                      routing-protocol specified in the route's
                      ipRouteProto value.  If this metric is not used,
                      its value should be set to -1."
              ::= { ipRouteEntry 3 }

          ipRouteMetric2 OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION

                      "An alternate routing metric for this route.  The
                      semantics of this metric are determined by the
                      routing-protocol specified in the route's
                      ipRouteProto value.  If this metric is not used,
                      its value should be set to -1."
              ::= { ipRouteEntry 4 }

          ipRouteMetric3 OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "An alternate routing metric for this route.  The
                      semantics of this metric are determined by the
                      routing-protocol specified in the route's
                      ipRouteProto value.  If this metric is not used,
                      its value should be set to -1."
              ::= { ipRouteEntry 5 }

          ipRouteMetric4 OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "An alternate routing metric for this route.  The
                      semantics of this metric are determined by the
                      routing-protocol specified in the route's
                      ipRouteProto value.  If this metric is not used,
                      its value should be set to -1."
              ::= { ipRouteEntry 6 }

          ipRouteNextHop OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The IP address of the next hop of this route.
                      (In the case of a route bound to an interface
                      which is realized via a broadcast media, the value
                      of this field is the agent's IP address on that
                      interface.)"
              ::= { ipRouteEntry 7 }

          ipRouteType OBJECT-TYPE
              SYNTAX  INTEGER {
                          other(1),        -- none of the following

                          invalid(2),      -- an invalidated route

                                           -- route to directly
                          direct(3),       -- connected (sub-)network

                                           -- route to a non-local
                          indirect(4)      -- host/network/sub-network
                      }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The type of route.  Note that the values
                      direct(3) and indirect(4) refer to the notion of
                      direct and indirect routing in the IP
                      architecture.

                      Setting this object to the value invalid(2) has
                      the effect of invalidating the corresponding entry
                      in the ipRouteTable object.  That is, it
                      effectively dissasociates the destination
                      identified with said entry from the route
                      identified with said entry.  It is an
                      implementation-specific matter as to whether the
                      agent removes an invalidated entry from the table.
                      Accordingly, management stations must be prepared
                      to receive tabular information from agents that
                      corresponds to entries not currently in use.
                      Proper interpretation of such entries requires
                      examination of the relevant ipRouteType object."
              ::= { ipRouteEntry 8 }

          ipRouteProto OBJECT-TYPE
              SYNTAX  INTEGER {
                          other(1),       -- none of the following

                                          -- non-protocol information,
                                          -- e.g., manually configured
                          local(2),       -- entries

                                          -- set via a network
                          netmgmt(3),     -- management protocol

                                          -- obtained via ICMP,
                          icmp(4),        -- e.g., Redirect

                                          -- the remaining values are
                                          -- all gateway routing
                                          -- protocols
                          egp(5),
                          ggp(6),

                          hello(7),
                          rip(8),
                          is-is(9),
                          es-is(10),
                          ciscoIgrp(11),
                          bbnSpfIgp(12),
                          ospf(13),
                          bgp(14)
                      }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The routing mechanism via which this route was
                      learned.  Inclusion of values for gateway routing
                      protocols is not intended to imply that hosts
                      should support those protocols."
              ::= { ipRouteEntry 9 }

          ipRouteAge OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The number of seconds since this route was last
                      updated or otherwise determined to be correct.
                      Note that no semantics of `too old' can be implied
                      except through knowledge of the routing protocol
                      by which the route was learned."
              ::= { ipRouteEntry 10 }

          ipRouteMask OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "Indicate the mask to be logical-ANDed with the
                      destination address before being compared to the
                      value in the ipRouteDest field.  For those systems
                      that do not support arbitrary subnet masks, an
                      agent constructs the value of the ipRouteMask by
                      determining whether the value of the correspondent
                      ipRouteDest field belong to a class-A, B, or C
                      network, and then using one of:

                           mask           network
                           255.0.0.0      class-A
                           255.255.0.0    class-B
                           255.255.255.0  class-C

                      If the value of the ipRouteDest is 0.0.0.0 (a
                      default route), then the mask value is also
                      0.0.0.0.  It should be noted that all IP routing
                      subsystems implicitly use this mechanism."
              ::= { ipRouteEntry 11 }

          ipRouteMetric5 OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "An alternate routing metric for this route.  The
                      semantics of this metric are determined by the
                      routing-protocol specified in the route's
                      ipRouteProto value.  If this metric is not used,
                      its value should be set to -1."
              ::= { ipRouteEntry 12 }

          ipRouteInfo OBJECT-TYPE
              SYNTAX  OBJECT IDENTIFIER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "A reference to MIB definitions specific to the
                      particular routing protocol which is responsible
                      for this route, as determined by the value
                      specified in the route's ipRouteProto value.  If
                      this information is not present, its value should
                      be set to the OBJECT IDENTIFIER { 0 0 }, which is
                      a syntatically valid object identifier, and any
                      conformant implementation of ASN.1 and BER must be
                      able to generate and recognize this value."
              ::= { ipRouteEntry 13 }

          -- the IP Address Translation table

          -- The IP address translation table contain the IpAddress to
          -- `physical' address equivalences.  Some interfaces do not
          -- use translation tables for determining address
          -- equivalences (e.g., DDN-X.25 has an algorithmic method);
          -- if all interfaces are of this type, then the Address
          -- Translation table is empty, i.e., has zero entries.

          ipNetToMediaTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF IpNetToMediaEntry
              ACCESS  not-accessible
              STATUS  mandatory

              DESCRIPTION
                      "The IP Address Translation table used for mapping
                      from IP addresses to physical addresses."
              ::= { ip 22 }

          ipNetToMediaEntry OBJECT-TYPE
              SYNTAX  IpNetToMediaEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "Each entry contains one IpAddress to `physical'
                      address equivalence."
              INDEX   { ipNetToMediaIfIndex,
                        ipNetToMediaNetAddress }
              ::= { ipNetToMediaTable 1 }

          IpNetToMediaEntry ::=
              SEQUENCE {
                  ipNetToMediaIfIndex
                      INTEGER,
                  ipNetToMediaPhysAddress
                      PhysAddress,
                  ipNetToMediaNetAddress
                      IpAddress,
                  ipNetToMediaType
                      INTEGER
              }

          ipNetToMediaIfIndex OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The interface on which this entry's equivalence
                      is effective.  The interface identified by a
                      particular value of this index is the same
                      interface as identified by the same value of
                      ifIndex."
              ::= { ipNetToMediaEntry 1 }

          ipNetToMediaPhysAddress OBJECT-TYPE
              SYNTAX  PhysAddress
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The media-dependent `physical' address."
              ::= { ipNetToMediaEntry 2 }

          ipNetToMediaNetAddress OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The IpAddress corresponding to the media-
                      dependent `physical' address."
              ::= { ipNetToMediaEntry 3 }

          ipNetToMediaType OBJECT-TYPE
              SYNTAX  INTEGER {
                          other(1),        -- none of the following
                          invalid(2),      -- an invalidated mapping
                          dynamic(3),
                          static(4)
                      }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The type of mapping.

                      Setting this object to the value invalid(2) has
                      the effect of invalidating the corresponding entry
                      in the ipNetToMediaTable.  That is, it effectively
                      dissasociates the interface identified with said
                      entry from the mapping identified with said entry.
                      It is an implementation-specific matter as to
                      whether the agent removes an invalidated entry
                      from the table.  Accordingly, management stations
                      must be prepared to receive tabular information
                      from agents that corresponds to entries not
                      currently in use.  Proper interpretation of such
                      entries requires examination of the relevant
                      ipNetToMediaType object."
              ::= { ipNetToMediaEntry 4 }

          -- additional IP objects

          ipRoutingDiscards OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of routing entries which were chosen
                      to be discarded even though they are valid.  One
                      possible reason for discarding such an entry could
                      be to free-up buffer space for other routing

                      entries."
              ::= { ip 23 }

          -- the ICMP group

          -- Implementation of the ICMP group is mandatory for all
          -- systems.

          icmpInMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of ICMP messages which the
                      entity received.  Note that this counter includes
                      all those counted by icmpInErrors."
              ::= { icmp 1 }

          icmpInErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP messages which the entity
                      received but determined as having ICMP-specific
                      errors (bad ICMP checksums, bad length, etc.)."
              ::= { icmp 2 }

          icmpInDestUnreachs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Destination Unreachable
                      messages received."
              ::= { icmp 3 }

          icmpInTimeExcds OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Time Exceeded messages
                      received."
              ::= { icmp 4 }

          icmpInParmProbs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Parameter Problem messages
                      received."
              ::= { icmp 5 }

          icmpInSrcQuenchs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Source Quench messages
                      received."
              ::= { icmp 6 }

          icmpInRedirects OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Redirect messages received."
              ::= { icmp 7 }

          icmpInEchos OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Echo (request) messages
                      received."
              ::= { icmp 8 }

          icmpInEchoReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Echo Reply messages received."
              ::= { icmp 9 }

          icmpInTimestamps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION

                      "The number of ICMP Timestamp (request) messages
                      received."
              ::= { icmp 10 }

          icmpInTimestampReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Timestamp Reply messages
                      received."
              ::= { icmp 11 }

          icmpInAddrMasks OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Address Mask Request messages
                      received."
              ::= { icmp 12 }

          icmpInAddrMaskReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Address Mask Reply messages
                      received."
              ::= { icmp 13 }

          icmpOutMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of ICMP messages which this
                      entity attempted to send.  Note that this counter
                      includes all those counted by icmpOutErrors."
              ::= { icmp 14 }

          icmpOutErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP messages which this entity did
                      not send due to problems discovered within ICMP

                      such as a lack of buffers.  This value should not
                      include errors discovered outside the ICMP layer
                      such as the inability of IP to route the resultant
                      datagram.  In some implementations there may be no
                      types of error which contribute to this counter's
                      value."
              ::= { icmp 15 }

          icmpOutDestUnreachs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Destination Unreachable
                      messages sent."
              ::= { icmp 16 }

          icmpOutTimeExcds OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Time Exceeded messages sent."
              ::= { icmp 17 }

          icmpOutParmProbs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Parameter Problem messages
                      sent."
              ::= { icmp 18 }

          icmpOutSrcQuenchs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Source Quench messages sent."
              ::= { icmp 19 }

          icmpOutRedirects OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Redirect messages sent.  For a

                      host, this object will always be zero, since hosts
                      do not send redirects."
              ::= { icmp 20 }

          icmpOutEchos OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Echo (request) messages sent."
              ::= { icmp 21 }

          icmpOutEchoReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Echo Reply messages sent."
              ::= { icmp 22 }

          icmpOutTimestamps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Timestamp (request) messages
                      sent."
              ::= { icmp 23 }

          icmpOutTimestampReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Timestamp Reply messages
                      sent."
              ::= { icmp 24 }

          icmpOutAddrMasks OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Address Mask Request messages
                      sent."
              ::= { icmp 25 }

          icmpOutAddrMaskReps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of ICMP Address Mask Reply messages
                      sent."
              ::= { icmp 26 }

          -- the TCP group

          -- Implementation of the TCP group is mandatory for all
          -- systems that implement the TCP.

          -- Note that instances of object types that represent
          -- information about a particular TCP connection are
          -- transient; they persist only as long as the connection
          -- in question.

          tcpRtoAlgorithm OBJECT-TYPE
              SYNTAX  INTEGER {
                          other(1),    -- none of the following

                          constant(2), -- a constant rto
                          rsre(3),     -- MIL-STD-1778, Appendix B
                          vanj(4)      -- Van Jacobson's algorithm [10]
                      }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The algorithm used to determine the timeout value
                      used for retransmitting unacknowledged octets."
              ::= { tcp 1 }

          tcpRtoMin OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The minimum value permitted by a TCP
                      implementation for the retransmission timeout,
                      measured in milliseconds.  More refined semantics
                      for objects of this type depend upon the algorithm
                      used to determine the retransmission timeout.  In
                      particular, when the timeout algorithm is rsre(3),
                      an object of this type has the semantics of the
                      LBOUND quantity described in RFC 793."

              ::= { tcp 2 }

          tcpRtoMax OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The maximum value permitted by a TCP
                      implementation for the retransmission timeout,
                      measured in milliseconds.  More refined semantics
                      for objects of this type depend upon the algorithm
                      used to determine the retransmission timeout.  In
                      particular, when the timeout algorithm is rsre(3),
                      an object of this type has the semantics of the
                      UBOUND quantity described in RFC 793."
              ::= { tcp 3 }

          tcpMaxConn OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The limit on the total number of TCP connections
                      the entity can support.  In entities where the
                      maximum number of connections is dynamic, this
                      object should contain the value -1."
              ::= { tcp 4 }

          tcpActiveOpens OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of times TCP connections have made a
                      direct transition to the SYN-SENT state from the
                      CLOSED state."
              ::= { tcp 5 }

          tcpPassiveOpens OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of times TCP connections have made a
                      direct transition to the SYN-RCVD state from the
                      LISTEN state."
              ::= { tcp 6 }

          tcpAttemptFails OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of times TCP connections have made a
                      direct transition to the CLOSED state from either
                      the SYN-SENT state or the SYN-RCVD state, plus the
                      number of times TCP connections have made a direct
                      transition to the LISTEN state from the SYN-RCVD
                      state."
              ::= { tcp 7 }

          tcpEstabResets OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of times TCP connections have made a
                      direct transition to the CLOSED state from either
                      the ESTABLISHED state or the CLOSE-WAIT state."
              ::= { tcp 8 }

          tcpCurrEstab OBJECT-TYPE
              SYNTAX  Gauge
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of TCP connections for which the
                      current state is either ESTABLISHED or CLOSE-
                      WAIT."
              ::= { tcp 9 }

          tcpInSegs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of segments received, including
                      those received in error.  This count includes
                      segments received on currently established
                      connections."
              ::= { tcp 10 }

          tcpOutSegs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "The total number of segments sent, including
                      those on current connections but excluding those
                      containing only retransmitted octets."
              ::= { tcp 11 }

          tcpRetransSegs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of segments retransmitted - that
                      is, the number of TCP segments transmitted
                      containing one or more previously transmitted
                      octets."
              ::= { tcp 12 }

          -- the TCP Connection table

          -- The TCP connection table contains information about this
          -- entity's existing TCP connections.

          tcpConnTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF TcpConnEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "A table containing TCP connection-specific
                      information."
              ::= { tcp 13 }

          tcpConnEntry OBJECT-TYPE
              SYNTAX  TcpConnEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "Information about a particular current TCP
                      connection.  An object of this type is transient,
                      in that it ceases to exist when (or soon after)
                      the connection makes the transition to the CLOSED
                      state."
              INDEX   { tcpConnLocalAddress,
                        tcpConnLocalPort,
                        tcpConnRemAddress,
                        tcpConnRemPort }
              ::= { tcpConnTable 1 }

          TcpConnEntry ::=
              SEQUENCE {
                  tcpConnState
                      INTEGER,
                  tcpConnLocalAddress
                      IpAddress,
                  tcpConnLocalPort
                      INTEGER (0..65535),
                  tcpConnRemAddress
                      IpAddress,
                  tcpConnRemPort
                      INTEGER (0..65535)
              }

          tcpConnState OBJECT-TYPE
              SYNTAX  INTEGER {
                          closed(1),
                          listen(2),
                          synSent(3),
                          synReceived(4),
                          established(5),
                          finWait1(6),
                          finWait2(7),
                          closeWait(8),
                          lastAck(9),
                          closing(10),
                          timeWait(11),
                          deleteTCB(12)
                      }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "The state of this TCP connection.

                      The only value which may be set by a management
                      station is deleteTCB(12).  Accordingly, it is
                      appropriate for an agent to return a `badValue'
                      response if a management station attempts to set
                      this object to any other value.

                      If a management station sets this object to the
                      value deleteTCB(12), then this has the effect of
                      deleting the TCB (as defined in RFC 793) of the
                      corresponding connection on the managed node,
                      resulting in immediate termination of the
                      connection.

                      As an implementation-specific option, a RST

                      segment may be sent from the managed node to the
                      other TCP endpoint (note however that RST segments
                      are not sent reliably)."
              ::= { tcpConnEntry 1 }

          tcpConnLocalAddress OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The local IP address for this TCP connection.  In
                      the case of a connection in the listen state which
                      is willing to accept connections for any IP
                      interface associated with the node, the value
                      0.0.0.0 is used."
              ::= { tcpConnEntry 2 }

          tcpConnLocalPort OBJECT-TYPE
              SYNTAX  INTEGER (0..65535)
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The local port number for this TCP connection."
              ::= { tcpConnEntry 3 }

          tcpConnRemAddress OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The remote IP address for this TCP connection."
              ::= { tcpConnEntry 4 }

          tcpConnRemPort OBJECT-TYPE
              SYNTAX  INTEGER (0..65535)
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The remote port number for this TCP connection."
              ::= { tcpConnEntry 5 }

          -- additional TCP objects

          tcpInErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "The total number of segments received in error
                      (e.g., bad TCP checksums)."
              ::= { tcp 14 }

          tcpOutRsts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of TCP segments sent containing the
                      RST flag."
              ::= { tcp 15 }

          -- the UDP group

          -- Implementation of the UDP group is mandatory for all
          -- systems which implement the UDP.

          udpInDatagrams OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of UDP datagrams delivered to
                      UDP users."
              ::= { udp 1 }

          udpNoPorts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of received UDP datagrams for
                      which there was no application at the destination
                      port."
              ::= { udp 2 }

          udpInErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of received UDP datagrams that could
                      not be delivered for reasons other than the lack
                      of an application at the destination port."
              ::= { udp 3 }

          udpOutDatagrams OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of UDP datagrams sent from this
                      entity."
              ::= { udp 4 }

          -- the UDP Listener table

          -- The UDP listener table contains information about this
          -- entity's UDP end-points on which a local application is
          -- currently accepting datagrams.

          udpTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF UdpEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "A table containing UDP listener information."
              ::= { udp 5 }

          udpEntry OBJECT-TYPE
              SYNTAX  UdpEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "Information about a particular current UDP
                      listener."
              INDEX   { udpLocalAddress, udpLocalPort }
              ::= { udpTable 1 }

          UdpEntry ::=
              SEQUENCE {
                  udpLocalAddress
                      IpAddress,
                  udpLocalPort
                      INTEGER (0..65535)
              }

          udpLocalAddress OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The local IP address for this UDP listener.  In

                      the case of a UDP listener which is willing to
                      accept datagrams for any IP interface associated
                      with the node, the value 0.0.0.0 is used."
              ::= { udpEntry 1 }

          udpLocalPort OBJECT-TYPE
              SYNTAX  INTEGER (0..65535)
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The local port number for this UDP listener."
              ::= { udpEntry 2 }

          -- the EGP group

          -- Implementation of the EGP group is mandatory for all
          -- systems which implement the EGP.

          egpInMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP messages received without
                      error."
              ::= { egp 1 }

          egpInErrors OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP messages received that proved
                      to be in error."
              ::= { egp 2 }

          egpOutMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of locally generated EGP
                      messages."
              ::= { egp 3 }

          egpOutErrors OBJECT-TYPE
              SYNTAX  Counter

              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of locally generated EGP messages not
                      sent due to resource limitations within an EGP
                      entity."
              ::= { egp 4 }

          -- the EGP Neighbor table

          -- The EGP neighbor table contains information about this
          -- entity's EGP neighbors.

          egpNeighTable OBJECT-TYPE
              SYNTAX  SEQUENCE OF EgpNeighEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "The EGP neighbor table."
              ::= { egp 5 }

          egpNeighEntry OBJECT-TYPE
              SYNTAX  EgpNeighEntry
              ACCESS  not-accessible
              STATUS  mandatory
              DESCRIPTION
                      "Information about this entity's relationship with
                      a particular EGP neighbor."
              INDEX   { egpNeighAddr }
              ::= { egpNeighTable 1 }

          EgpNeighEntry ::=
              SEQUENCE {
                  egpNeighState
                      INTEGER,
                  egpNeighAddr
                      IpAddress,
                  egpNeighAs
                      INTEGER,
                  egpNeighInMsgs
                      Counter,
                  egpNeighInErrs
                      Counter,
                  egpNeighOutMsgs
                      Counter,
                  egpNeighOutErrs
                      Counter,

                  egpNeighInErrMsgs
                      Counter,
                  egpNeighOutErrMsgs
                      Counter,
                  egpNeighStateUps
                      Counter,
                  egpNeighStateDowns
                      Counter,
                  egpNeighIntervalHello
                      INTEGER,
                  egpNeighIntervalPoll
                      INTEGER,
                  egpNeighMode
                      INTEGER,
                  egpNeighEventTrigger
                      INTEGER
              }

          egpNeighState OBJECT-TYPE
              SYNTAX  INTEGER {
                          idle(1),
                          acquisition(2),
                          down(3),
                          up(4),
                          cease(5)
                      }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The EGP state of the local system with respect to
                      this entry's EGP neighbor.  Each EGP state is
                      represented by a value that is one greater than
                      the numerical value associated with said state in
                      RFC 904."
              ::= { egpNeighEntry 1 }

          egpNeighAddr OBJECT-TYPE
              SYNTAX  IpAddress
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The IP address of this entry's EGP neighbor."
              ::= { egpNeighEntry 2 }

          egpNeighAs OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "The autonomous system of this EGP peer.  Zero
                      should be specified if the autonomous system
                      number of the neighbor is not yet known."
              ::= { egpNeighEntry 3 }

          egpNeighInMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP messages received without error
                      from this EGP peer."
              ::= { egpNeighEntry 4 }

          egpNeighInErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP messages received from this EGP
                      peer that proved to be in error (e.g., bad EGP
                      checksum)."
              ::= { egpNeighEntry 5 }

          egpNeighOutMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of locally generated EGP messages to
                      this EGP peer."
              ::= { egpNeighEntry 6 }

          egpNeighOutErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of locally generated EGP messages not
                      sent to this EGP peer due to resource limitations
                      within an EGP entity."
              ::= { egpNeighEntry 7 }

          egpNeighInErrMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "The number of EGP-defined error messages received
                      from this EGP peer."
              ::= { egpNeighEntry 8 }

          egpNeighOutErrMsgs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP-defined error messages sent to
                      this EGP peer."
              ::= { egpNeighEntry 9 }

          egpNeighStateUps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP state transitions to the UP
                      state with this EGP peer."
              ::= { egpNeighEntry 10 }

          egpNeighStateDowns OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The number of EGP state transitions from the UP
                      state to any other state with this EGP peer."
              ::= { egpNeighEntry 11 }

          egpNeighIntervalHello OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The interval between EGP Hello command
                      retransmissions (in hundredths of a second).  This
                      represents the t1 timer as defined in RFC 904."
              ::= { egpNeighEntry 12 }

          egpNeighIntervalPoll OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The interval between EGP poll command

                      retransmissions (in hundredths of a second).  This
                      represents the t3 timer as defined in RFC 904."
              ::= { egpNeighEntry 13 }

          egpNeighMode OBJECT-TYPE
              SYNTAX  INTEGER { active(1), passive(2) }
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The polling mode of this EGP entity, either
                      passive or active."
              ::= { egpNeighEntry 14 }

          egpNeighEventTrigger OBJECT-TYPE
              SYNTAX  INTEGER { start(1), stop(2) }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "A control variable used to trigger operator-
                      initiated Start and Stop events.  When read, this
                      variable always returns the most recent value that
                      egpNeighEventTrigger was set to.  If it has not
                      been set since the last initialization of the
                      network management subsystem on the node, it
                      returns a value of `stop'.

                      When set, this variable causes a Start or Stop
                      event on the specified neighbor, as specified on
                      pages 8-10 of RFC 904.  Briefly, a Start event
                      causes an Idle peer to begin neighbor acquisition
                      and a non-Idle peer to reinitiate neighbor
                      acquisition.  A stop event causes a non-Idle peer
                      to return to the Idle state until a Start event
                      occurs, either via egpNeighEventTrigger or
                      otherwise."
              ::= { egpNeighEntry 15 }

          -- additional EGP objects

          egpAs OBJECT-TYPE
              SYNTAX  INTEGER
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The autonomous system number of this EGP entity."
              ::= { egp 6 }

          -- the Transmission group

          -- Based on the transmission media underlying each interface
          -- on a system, the corresponding portion of the Transmission
          -- group is mandatory for that system.

          -- When Internet-standard definitions for managing
          -- transmission media are defined, the transmission group is
          -- used to provide a prefix for the names of those objects.

          -- Typically, such definitions reside in the experimental
          -- portion of the MIB until they are "proven", then as a
          -- part of the Internet standardization process, the
          -- definitions are accordingly elevated and a new object
          -- identifier, under the transmission group is defined. By
          -- convention, the name assigned is:
          --
          --     type OBJECT IDENTIFIER    ::= { transmission number }
          --
          -- where "type" is the symbolic value used for the media in
          -- the ifType column of the ifTable object, and "number" is
          -- the actual integer value corresponding to the symbol.

          -- the SNMP group

          -- Implementation of the SNMP group is mandatory for all
          -- systems which support an SNMP protocol entity.  Some of
          -- the objects defined below will be zero-valued in those
          -- SNMP implementations that are optimized to support only
          -- those functions specific to either a management agent or
          -- a management station.  In particular, it should be
          -- observed that the objects below refer to an SNMP entity,
          -- and there may be several SNMP entities residing on a
          -- managed node (e.g., if the node is hosting acting as
          -- a management station).

          snmpInPkts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of Messages delivered to the
                      SNMP entity from the transport service."
              ::= { snmp 1 }

          snmpOutPkts OBJECT-TYPE
              SYNTAX  Counter

              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Messages which were
                      passed from the SNMP protocol entity to the
                      transport service."
              ::= { snmp 2 }

          snmpInBadVersions OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Messages which were
                      delivered to the SNMP protocol entity and were for
                      an unsupported SNMP version."
              ::= { snmp 3 }

          snmpInBadCommunityNames OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Messages delivered to
                      the SNMP protocol entity which used a SNMP
                      community name not known to said entity."
              ::= { snmp 4 }

          snmpInBadCommunityUses OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Messages delivered to
                      the SNMP protocol entity which represented an SNMP
                      operation which was not allowed by the SNMP
                      community named in the Message."
              ::= { snmp 5 }

          snmpInASNParseErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of ASN.1 or BER errors
                      encountered by the SNMP protocol entity when
                      decoding received SNMP Messages."
              ::= { snmp 6 }

          -- { snmp 7 } is not used

          snmpInTooBigs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      delivered to the SNMP protocol entity and for
                      which the value of the error-status field is
                      `tooBig'."
              ::= { snmp 8 }

          snmpInNoSuchNames OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      delivered to the SNMP protocol entity and for
                      which the value of the error-status field is
                      `noSuchName'."
              ::= { snmp 9 }

          snmpInBadValues OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      delivered to the SNMP protocol entity and for
                      which the value of the error-status field is
                      `badValue'."
              ::= { snmp 10 }

          snmpInReadOnlys OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number valid SNMP PDUs which were
                      delivered to the SNMP protocol entity and for
                      which the value of the error-status field is
                      `readOnly'.  It should be noted that it is a
                      protocol error to generate an SNMP PDU which
                      contains the value `readOnly' in the error-status
                      field, as such this object is provided as a means
                      of detecting incorrect implementations of the

                      SNMP."
              ::= { snmp 11 }

          snmpInGenErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      delivered to the SNMP protocol entity and for
                      which the value of the error-status field is
                      `genErr'."
              ::= { snmp 12 }

          snmpInTotalReqVars OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of MIB objects which have been
                      retrieved successfully by the SNMP protocol entity
                      as the result of receiving valid SNMP Get-Request
                      and Get-Next PDUs."
              ::= { snmp 13 }

          snmpInTotalSetVars OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of MIB objects which have been
                      altered successfully by the SNMP protocol entity
                      as the result of receiving valid SNMP Set-Request
                      PDUs."
              ::= { snmp 14 }

          snmpInGetRequests OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Get-Request PDUs which
                      have been accepted and processed by the SNMP
                      protocol entity."
              ::= { snmp 15 }

          snmpInGetNexts OBJECT-TYPE
              SYNTAX  Counter

              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Get-Next PDUs which have
                      been accepted and processed by the SNMP protocol
                      entity."
              ::= { snmp 16 }

          snmpInSetRequests OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Set-Request PDUs which
                      have been accepted and processed by the SNMP
                      protocol entity."
              ::= { snmp 17 }

          snmpInGetResponses OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Get-Response PDUs which
                      have been accepted and processed by the SNMP
                      protocol entity."
              ::= { snmp 18 }

          snmpInTraps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Trap PDUs which have
                      been accepted and processed by the SNMP protocol
                      entity."
              ::= { snmp 19 }

          snmpOutTooBigs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      generated by the SNMP protocol entity and for
                      which the value of the error-status field is
                      `tooBig.'"
              ::= { snmp 20 }

          snmpOutNoSuchNames OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      generated by the SNMP protocol entity and for
                      which the value of the error-status is
                      `noSuchName'."
              ::= { snmp 21 }

          snmpOutBadValues OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      generated by the SNMP protocol entity and for
                      which the value of the error-status field is
                      `badValue'."
              ::= { snmp 22 }

          -- { snmp 23 } is not used

          snmpOutGenErrs OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP PDUs which were
                      generated by the SNMP protocol entity and for
                      which the value of the error-status field is
                      `genErr'."
              ::= { snmp 24 }

          snmpOutGetRequests OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Get-Request PDUs which
                      have been generated by the SNMP protocol entity."
              ::= { snmp 25 }

          snmpOutGetNexts OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory

              DESCRIPTION
                      "The total number of SNMP Get-Next PDUs which have
                      been generated by the SNMP protocol entity."
              ::= { snmp 26 }

          snmpOutSetRequests OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Set-Request PDUs which
                      have been generated by the SNMP protocol entity."
              ::= { snmp 27 }

          snmpOutGetResponses OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Get-Response PDUs which
                      have been generated by the SNMP protocol entity."
              ::= { snmp 28 }

          snmpOutTraps OBJECT-TYPE
              SYNTAX  Counter
              ACCESS  read-only
              STATUS  mandatory
              DESCRIPTION
                      "The total number of SNMP Trap PDUs which have
                      been generated by the SNMP protocol entity."
              ::= { snmp 29 }

          snmpEnableAuthenTraps OBJECT-TYPE
              SYNTAX  INTEGER { enabled(1), disabled(2) }
              ACCESS  read-write
              STATUS  mandatory
              DESCRIPTION
                      "Indicates whether the SNMP agent process is
                      permitted to generate authentication-failure
                      traps.  The value of this object overrides any
                      configuration information; as such, it provides a
                      means whereby all authentication-failure traps may
                      be disabled.

                      Note that it is strongly recommended that this
                      object be stored in non-volatile memory so that it
                      remains constant between re-initializations of the
                      network management system."

              ::= { snmp 30 }

END


RFC-1215 DEFINITIONS ::= BEGIN

-- This  module is a empty module.  It has been created solely for the
-- purpose of allowing other modules to correctly import the TRAP-TYPE
-- clause from RFC-1215 where it should be imported from.  It's a
-- built in type in the UCD-SNMP code, and in fact RFC-1215 doesn't
-- actually define a mib at all; it only defines macros.  However,
-- importing the TRAP-TYPE is conventionally done from an import
-- clause pointing to RFC-1215.  The definition of the trap macro is
-- in the comment field below.
--
--   Wes 7/17/98

--  TRAP-TYPE MACRO ::=
--  BEGIN
--      TYPE NOTATION ::= "ENTERPRISE" value
--                            (enterprise OBJECT IDENTIFIER)
--                        VarPart
--                        DescrPart
--                        ReferPart
--      VALUE NOTATION ::= value (VALUE INTEGER)
--      VarPart ::=
--                 "VARIABLES" "{" VarTypes "}"
--                      | empty
--      VarTypes ::=
--                 VarType | VarTypes "," VarType
--      VarType ::=
--                 value (vartype ObjectName)
--      DescrPart ::=
--                 "DESCRIPTION" value (description DisplayString)
--                      | empty
--      ReferPart ::=
--                 "REFERENCE" value (reference DisplayString)
--                      | empty
--  END

END


RMON-MIB DEFINITIONS ::= BEGIN

    IMPORTS
    Counter                FROM RFC1155-SMI
    DisplayString          FROM RFC1158-MIB
    mib-2                  FROM RFC1213-MIB
    OBJECT-TYPE            FROM RFC-1212
    TRAP-TYPE              FROM RFC-1215;

--  Remote Network Monitoring MIB

    rmon    OBJECT IDENTIFIER ::= { mib-2 16 }

    -- textual conventions

    OwnerString ::= DisplayString
    -- This data type is used to model an administratively
    -- assigned name of the owner of a resource. This
    -- information is taken from the NVT ASCII character
    -- set.  It is suggested that this name contain one or
    -- more of the following: IP address, management station
    -- name, network manager's name, location, or phone
    -- number.
    -- In some cases the agent itself will be the owner of
    -- an entry.  In these cases, this string shall be set
    -- to a string starting with 'monitor'.
    --
    -- SNMP access control is articulated entirely in terms
    -- of the contents of MIB views; access to a particular
    -- SNMP object instance depends only upon its presence
    -- or absence in a particular MIB view and never upon
    -- its value or the value of related object instances.
    -- Thus, objects of this type afford resolution of
    -- resource contention only among cooperating managers;
    -- they realize no access control function with respect
    -- to uncooperative parties.
    --
    -- By convention, objects with this syntax are declared as
    -- having
    --
    --      SIZE (0..127)

    EntryStatus ::= INTEGER
           { valid(1),
         createRequest(2),
         underCreation(3),
         invalid(4)
           }
    -- The status of a table entry.
    --
    -- Setting this object to the value invalid(4) has the
    -- effect of invalidating the corresponding entry.
    -- That is, it effectively disassociates the mapping
    -- identified with said entry.
    -- It is an implementation-specific matter as to whether
    -- the agent removes an invalidated entry from the table.
    -- Accordingly, management stations must be prepared to
    -- receive tabular information from agents that
    -- corresponds to entries currently not in use.  Proper
    -- interpretation of such entries requires examination
    -- of the relevant EntryStatus object.
    --
    -- An existing instance of this object cannot be set to
    -- createRequest(2).  This object may only be set to
    -- createRequest(2) when this instance is created.  When
    -- this object is created, the agent may wish to create
    -- supplemental object instances with default values
    -- to complete a conceptual row in this table.  Because
    -- the creation of these default objects is entirely at
    -- the option of the agent, the manager must not assume
    -- that any will be created, but may make use of any that
    -- are created. Immediately after completing the create
    -- operation, the agent must set this object to
    -- underCreation(3).
    --
    -- When in the underCreation(3) state, an entry is
    -- allowed to exist in a possibly incomplete, possibly
    -- inconsistent state, usually to allow it to be
    -- modified in mutiple PDUs.  When in this state, an
    -- entry is not fully active.  Entries shall exist in
    -- the underCreation(3) state until the management
    -- station is finished configuring the entry and sets
    -- this object to valid(1) or aborts, setting this
    -- object to invalid(4).  If the agent determines that
    -- an entry has been in the underCreation(3) state for
    -- an abnormally long time, it may decide that the
    -- management station has crashed.  If the agent makes
    -- this decision, it may set this object to invalid(4)
    -- to reclaim the entry.  A prudent agent will
    -- understand that the management station may need to
    -- wait for human input and will allow for that
    -- possibility in its determination of this abnormally
    -- long period.
    --
    -- An entry in the valid(1) state is fully configured and
    -- consistent and fully represents the configuration or
    -- operation such a row is intended to represent.  For
    -- example, it could be a statistical function that is
    -- configured and active, or a filter that is available
    -- in the list of filters processed by the packet capture
    -- process.
    --
    -- A manager is restricted to changing the state of an
    -- entry in the following ways:
    --
    --                       create   under
    --      To:       valid  Request  Creation  invalid
    -- From:
    -- valid             OK       NO        OK       OK
    -- createRequest    N/A      N/A       N/A      N/A
    -- underCreation     OK       NO        OK       OK
    -- invalid           NO       NO        NO       OK
    -- nonExistent       NO       OK        NO       OK
    --
    -- In the table above, it is not applicable to move the
    -- state from the createRequest state to any other
    -- state because the manager will never find the
    -- variable in that state.  The nonExistent state is
    -- not a value of the enumeration, rather it means that
    -- the entryStatus variable does not exist at all.
    --
    -- An agent may allow an entryStatus variable to change
    -- state in additional ways, so long as the semantics
    -- of the states are followed.  This allowance is made
    -- to ease the implementation of the agent and is made
    -- despite the fact that managers should never
    -- excercise these additional state transitions.

    statistics        OBJECT IDENTIFIER ::= { rmon 1 }
    history           OBJECT IDENTIFIER ::= { rmon 2 }
    alarm             OBJECT IDENTIFIER ::= { rmon 3 }
    hosts             OBJECT IDENTIFIER ::= { rmon 4 }
    hostTopN          OBJECT IDENTIFIER ::= { rmon 5 }
    matrix            OBJECT IDENTIFIER ::= { rmon 6 }
    filter            OBJECT IDENTIFIER ::= { rmon 7 }
    capture           OBJECT IDENTIFIER ::= { rmon 8 }
    event             OBJECT IDENTIFIER ::= { rmon 9 }

-- The Ethernet Statistics Group
--
-- Implementation of the Ethernet Statistics group is
-- optional.
--
-- The ethernet statistics group contains statistics
-- measured by the probe for each monitored interface on
-- this device.  These statistics take the form of free
-- running counters that start from zero when a valid entry
-- is created.
--
-- This group currently has statistics defined only for
-- Ethernet interfaces.  Each etherStatsEntry contains
-- statistics for one Ethernet interface.  The probe must
-- create one etherStats entry for each monitored Ethernet
-- interface on the device.

etherStatsTable OBJECT-TYPE
    SYNTAX SEQUENCE OF EtherStatsEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of Ethernet statistics entries."
    ::= { statistics 1 }

etherStatsEntry OBJECT-TYPE
    SYNTAX EtherStatsEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A collection of statistics kept for a particular
    Ethernet interface.  As an example, an instance of the
    etherStatsPkts object might be named etherStatsPkts.1"
    INDEX { etherStatsIndex }
    ::= { etherStatsTable 1 }

EtherStatsEntry ::= SEQUENCE {
    etherStatsIndex                    INTEGER (1..65535),
    etherStatsDataSource               OBJECT IDENTIFIER,
    etherStatsDropEvents               Counter,
    etherStatsOctets                   Counter,
    etherStatsPkts                     Counter,
    etherStatsBroadcastPkts            Counter,
    etherStatsMulticastPkts            Counter,
    etherStatsCRCAlignErrors           Counter,
    etherStatsUndersizePkts            Counter,
    etherStatsOversizePkts             Counter,
    etherStatsFragments                Counter,
    etherStatsJabbers                  Counter,
    etherStatsCollisions               Counter,
    etherStatsPkts64Octets             Counter,
    etherStatsPkts65to127Octets        Counter,
    etherStatsPkts128to255Octets       Counter,
    etherStatsPkts256to511Octets       Counter,
    etherStatsPkts512to1023Octets      Counter,
    etherStatsPkts1024to1518Octets     Counter,
    etherStatsOwner                    OwnerString,
    etherStatsStatus                   EntryStatus
}

etherStatsIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of this object uniquely identifies this
    etherStats entry."
    ::= { etherStatsEntry 1 }

etherStatsDataSource OBJECT-TYPE
    SYNTAX OBJECT IDENTIFIER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object identifies the source of the data that
    this etherStats entry is configured to analyze.  This
    source can be any ethernet interface on this device.
    In order to identify a particular interface, this
    object shall identify the instance of the ifIndex
    object, defined in RFC 1213 and RFC 1573 [4,6], for
    the desired interface.  For example, if an entry
    were to receive data from interface #1, this object
    would be set to ifIndex.1.

    The statistics in this group reflect all packets
    on the local network segment attached to the
    identified interface.

    An agent may or may not be able to tell if
    fundamental changes to the media of the interface
    have occurred and necessitate an invalidation of
    this entry.  For example, a hot-pluggable ethernet
    card could be pulled out and replaced by a
    token-ring card.  In such a case, if the agent has
    such knowledge of the change, it is recommended that
    it invalidate this entry.

    This object may not be modified if the associated
    etherStatsStatus object is equal to valid(1)."
    ::= { etherStatsEntry 2 }

etherStatsDropEvents OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of events in which packets
    were dropped by the probe due to lack of resources.
    Note that this number is not necessarily the number of
    packets dropped; it is just the number of times this
    condition has been detected."
    ::= { etherStatsEntry 3 }

etherStatsOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of octets of data (including
    those in bad packets) received on the
    network (excluding framing bits but including
    FCS octets).

    This object can be used as a reasonable estimate of
    ethernet utilization.  If greater precision is
    desired, the etherStatsPkts and etherStatsOctets
    objects should be sampled before and after a common
    interval.  The differences in the sampled values are
    Pkts and Octets, respectively, and the number of
    seconds in the interval is Interval.  These values
    are used to calculate the Utilization as follows:

             Pkts * (9.6 + 6.4) + (Octets * .8)
     Utilization = -------------------------------------
                 Interval * 10,000

    The result of this equation is the value Utilization
    which is the percent utilization of the ethernet
    segment on a scale of 0 to 100 percent."
    ::= { etherStatsEntry 4 }

etherStatsPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad packets,
    broadcast packets, and multicast packets) received."
    ::= { etherStatsEntry 5 }

etherStatsBroadcastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of good packets received that were
    directed to the broadcast address.  Note that this
    does not include multicast packets."
    ::= { etherStatsEntry 6 }

etherStatsMulticastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of good packets received that were
    directed to a multicast address.  Note that this
    number does not include packets directed to the
    broadcast address."
    ::= { etherStatsEntry 7 }

etherStatsCRCAlignErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received that
    had a length (excluding framing bits, but
    including FCS octets) of between 64 and 1518
    octets, inclusive, but but had either a bad
    Frame Check Sequence (FCS) with an integral
    number of octets (FCS Error) or a bad FCS with
    a non-integral number of octets (Alignment Error)."
    ::= { etherStatsEntry 8 }

etherStatsUndersizePkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received that were
    less than 64 octets long (excluding framing bits,
    but including FCS octets) and were otherwise well
    formed."
    ::= { etherStatsEntry 9 }

etherStatsOversizePkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received that were
    longer than 1518 octets (excluding framing bits,
    but including FCS octets) and were otherwise
    well formed."
    ::= { etherStatsEntry 10 }

etherStatsFragments OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received that were less
    than 64 octets in length (excluding framing bits but
    including FCS octets) and had either a bad Frame
    Check Sequence (FCS) with an integral number of
    octets (FCS Error) or a bad FCS with a non-integral
    number of octets (Alignment Error).

    Note that it is entirely normal for
    etherStatsFragments to increment.  This is because
    it counts both runts (which are normal occurrences
    due to collisions) and noise hits."
    ::= { etherStatsEntry 11 }

etherStatsJabbers OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received that were
    longer than 1518 octets (excluding framing bits,
    but including FCS octets), and had either a bad
    Frame Check Sequence (FCS) with an integral number
    of octets (FCS Error) or a bad FCS with a
    non-integral number of octets (Alignment Error).

    Note that this definition of jabber is different
    than the definition in IEEE-802.3 section 8.2.1.5
    (10BASE5) and section 10.3.1.4 (10BASE2).  These
    documents define jabber as the condition where any
    packet exceeds 20 ms.  The allowed range to detect
    jabber is between 20 ms and 150 ms."
    ::= { etherStatsEntry 12 }

etherStatsCollisions OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The best estimate of the total number of collisions
    on this Ethernet segment.

    The value returned will depend on the location of
    the RMON probe. Section 8.2.1.3 (10BASE-5) and
    section 10.3.1.3 (10BASE-2) of IEEE standard 802.3
    states that a station must detect a collision, in
    the receive mode, if three or more stations are
    transmitting simultaneously.  A repeater port must
    detect a collision when two or more stations are
    transmitting simultaneously.  Thus a probe placed on
    a repeater port could record more collisions than a
    probe connected to a station on the same segment
    would.

    Probe location plays a much smaller role when
    considering 10BASE-T.  14.2.1.4 (10BASE-T) of IEEE
    standard 802.3 defines a collision as the
    simultaneous presence of signals on the DO and RD
    circuits (transmitting and receiving at the same
    time).  A 10BASE-T station can only detect
    collisions when it is transmitting.  Thus probes
    placed on a station and a repeater, should report
    the same number of collisions.

    Note also that an RMON probe inside a repeater
    should ideally report collisions between the
    repeater and one or more other hosts (transmit
    collisions as defined by IEEE 802.3k) plus receiver
    collisions observed on any coax segments to which
    the repeater is connected."
    ::= { etherStatsEntry 13 }

etherStatsPkts64Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were 64 octets in length
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 14 }

etherStatsPkts65to127Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were between
    65 and 127 octets in length inclusive
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 15 }

etherStatsPkts128to255Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were between
    128 and 255 octets in length inclusive
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 16 }

etherStatsPkts256to511Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were between
    256 and 511 octets in length inclusive
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 17 }

etherStatsPkts512to1023Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were between
    512 and 1023 octets in length inclusive
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 18 }

etherStatsPkts1024to1518Octets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets (including bad
    packets) received that were between
    1024 and 1518 octets in length inclusive
    (excluding framing bits but including FCS octets)."
    ::= { etherStatsEntry 19 }

etherStatsOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { etherStatsEntry 20 }

etherStatsStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this etherStats entry."
    ::= { etherStatsEntry 21 }

-- The History Control Group

-- Implementation of the History Control group is optional.
--
-- The history control group controls the periodic statistical
-- sampling of data from various types of networks.  The
-- historyControlTable stores configuration entries that each
-- define an interface, polling period, and other parameters.
-- Once samples are taken, their data is stored in an entry
-- in a media-specific table.  Each such entry defines one
-- sample, and is associated with the historyControlEntry that
-- caused the sample to be taken.  Each counter in the
-- etherHistoryEntry counts the same event as its
-- similarly-named counterpart in the etherStatsEntry,
-- except that each value here is a cumulative sum during a
-- sampling period.
--
-- If the probe keeps track of the time of day, it should
-- start the first sample of the history at a time such that
-- when the next hour of the day begins, a sample is
-- started at that instant.  This tends to make more
-- user-friendly reports, and enables comparison of reports
-- from different probes that have relatively accurate time
-- of day.
--
-- The probe is encouraged to add two history control entries
-- per monitored interface upon initialization that describe
-- a short term and a long term polling period.  Suggested
-- parameters are 30 seconds for the short term polling period
-- and 30 minutes for the long term period.

historyControlTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HistoryControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of history control entries."
    ::= { history 1 }

historyControlEntry OBJECT-TYPE
    SYNTAX HistoryControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of parameters that set up a periodic sampling
    of statistics.  As an example, an instance of the
    historyControlInterval object might be named
    historyControlInterval.2"
    INDEX { historyControlIndex }
    ::= { historyControlTable 1 }

HistoryControlEntry ::= SEQUENCE {
    historyControlIndex             INTEGER (1..65535),
    historyControlDataSource        OBJECT IDENTIFIER,
    historyControlBucketsRequested  INTEGER (1..65535),
    historyControlBucketsGranted    INTEGER (1..65535),
    historyControlInterval          INTEGER (1..3600),
    historyControlOwner             OwnerString,
    historyControlStatus            EntryStatus
}

historyControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    historyControl table.  Each such entry defines a
    set of samples at a particular interval for an
    interface on the device."
    ::= { historyControlEntry 1 }

historyControlDataSource OBJECT-TYPE
    SYNTAX OBJECT IDENTIFIER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object identifies the source of the data for
    which historical data was collected and
    placed in a media-specific table on behalf of this
    historyControlEntry.  This source can be any
    interface on this device.  In order to identify
    a particular interface, this object shall identify
    the instance of the ifIndex object, defined
    in  RFC 1213 and RFC 1573 [4,6], for the desired
    interface.  For example, if an entry were to receive
    data from interface #1, this object would be set
    to ifIndex.1.

    The statistics in this group reflect all packets
    on the local network segment attached to the
    identified interface.

    An agent may or may not be able to tell if fundamental
    changes to the media of the interface have occurred
    and necessitate an invalidation of this entry.  For
    example, a hot-pluggable ethernet card could be
    pulled out and replaced by a token-ring card.  In
    such a case, if the agent has such knowledge of the
    change, it is recommended that it invalidate this
    entry.

    This object may not be modified if the associated
    historyControlStatus object is equal to valid(1)."
    ::= { historyControlEntry 2 }

historyControlBucketsRequested OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The requested number of discrete time intervals
    over which data is to be saved in the part of the
    media-specific table associated with this
    historyControlEntry.

    When this object is created or modified, the probe
    should set historyControlBucketsGranted as closely to
    this object as is possible for the particular probe
    implementation and available resources."
    DEFVAL { 50 }
    ::= { historyControlEntry 3 }

historyControlBucketsGranted OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of discrete sampling intervals
    over which data shall be saved in the part of
    the media-specific table associated with this
    historyControlEntry.

    When the associated historyControlBucketsRequested
    object is created or modified, the probe
    should set this object as closely to the requested
    value as is possible for the particular
    probe implementation and available resources.  The
    probe must not lower this value except as a result
    of a modification to the associated
    historyControlBucketsRequested object.

    There will be times when the actual number of
    buckets associated with this entry is less than
    the value of this object.  In this case, at the
    end of each sampling interval, a new bucket will
    be added to the media-specific table.

    When the number of buckets reaches the value of
    this object and a new bucket is to be added to the
    media-specific table, the oldest bucket associated
    with this historyControlEntry shall be deleted by
    the agent so that the new bucket can be added.

    When the value of this object changes to a value less
    than the current value, entries are deleted
    from the media-specific table associated with this
    historyControlEntry.  Enough of the oldest of these
    entries shall be deleted by the agent so that their
    number remains less than or equal to the new value of
    this object.

    When the value of this object changes to a value
    greater than the current value, the number of
    associated media- specific entries may be allowed to
    grow."
    ::= { historyControlEntry 4 }

historyControlInterval OBJECT-TYPE
    SYNTAX INTEGER (1..3600)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The interval in seconds over which the data is
    sampled for each bucket in the part of the
    media-specific table associated with this
    historyControlEntry.  This interval can
    be set to any number of seconds between 1 and
    3600 (1 hour).

    Because the counters in a bucket may overflow at their
    maximum value with no indication, a prudent manager
    will take into account the possibility of overflow
    in any of the associated counters.  It is important
    to consider the minimum time in which any counter
    could overflow on a particular media type and set
    the historyControlInterval object to a value less
    than this interval.  This is typically most
    important for the 'octets' counter in any
    media-specific table.  For example, on an Ethernet
    network, the etherHistoryOctets counter could
    overflow in about one hour at the Ethernet's maximum
    utilization.

    This object may not be modified if the associated
    historyControlStatus object is equal to valid(1)."
    DEFVAL { 1800 }
    ::= { historyControlEntry 5 }

historyControlOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { historyControlEntry 6 }

historyControlStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this historyControl entry.

    Each instance of the media-specific table associated
    with this historyControlEntry will be deleted by the
    agent if this historyControlEntry is not equal to
    valid(1)."
    ::= { historyControlEntry 7 }

-- The Ethernet History Group

-- Implementation of the Ethernet History group is optional.
--
-- The Ethernet History group records periodic
-- statistical samples from a network and stores them
-- for later retrieval.  Once samples are taken, their
-- data is stored in an entry in a media-specific
-- table.  Each such entry defines one sample, and is
-- associated with the historyControlEntry that caused
-- the sample to be taken.  This group defines the
-- etherHistoryTable, for Ethernet networks.
--

etherHistoryTable OBJECT-TYPE
    SYNTAX SEQUENCE OF EtherHistoryEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of Ethernet history entries."
    ::= { history 2 }

etherHistoryEntry OBJECT-TYPE
    SYNTAX EtherHistoryEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "An historical sample of Ethernet statistics on a
    particular Ethernet interface.  This sample is
    associated with the historyControlEntry which set up
    the parameters for a regular collection of these
    samples.  As an example, an instance of the
    etherHistoryPkts object might be named
    etherHistoryPkts.2.89"
    INDEX { etherHistoryIndex , etherHistorySampleIndex }
    ::= { etherHistoryTable 1 }

EtherHistoryEntry ::= SEQUENCE {
    etherHistoryIndex                 INTEGER (1..65535),
    etherHistorySampleIndex           INTEGER (1..2147483647),
    etherHistoryIntervalStart         TimeTicks,
    etherHistoryDropEvents            Counter,
    etherHistoryOctets                Counter,
    etherHistoryPkts                  Counter,
    etherHistoryBroadcastPkts         Counter,
    etherHistoryMulticastPkts         Counter,
    etherHistoryCRCAlignErrors        Counter,
    etherHistoryUndersizePkts         Counter,
    etherHistoryOversizePkts          Counter,
    etherHistoryFragments             Counter,
    etherHistoryJabbers               Counter,
    etherHistoryCollisions            Counter,
    etherHistoryUtilization           INTEGER (0..10000)
}

etherHistoryIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The history of which this entry is a part.  The
    history identified by a particular value of this
    index is the same history as identified
    by the same value of historyControlIndex."
    ::= { etherHistoryEntry 1 }

etherHistorySampleIndex OBJECT-TYPE
    SYNTAX INTEGER (1..2147483647)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies the particular
    sample this entry represents among all samples
    associated with the same historyControlEntry.
    This index starts at 1 and increases by one
    as each new sample is taken."
    ::= { etherHistoryEntry 2 }

etherHistoryIntervalStart OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime at the start of the interval
    over which this sample was measured.  If the probe
    keeps track of the time of day, it should start
    the first sample of the history at a time such that
    when the next hour of the day begins, a sample is
    started at that instant.  Note that following this
    rule may require the probe to delay collecting the
    first sample of the history, as each sample must be
    of the same interval.  Also note that the sample which
    is currently being collected is not accessible in this
    table until the end of its interval."
    ::= { etherHistoryEntry 3 }

etherHistoryDropEvents OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of events in which packets
    were dropped by the probe due to lack of resources
    during this sampling interval.  Note that this number
    is not necessarily the number of packets dropped, it
    is just the number of times this condition has been
    detected."
    ::= { etherHistoryEntry 4 }

etherHistoryOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of octets of data (including
    those in bad packets) received on the
    network (excluding framing bits but including
    FCS octets)."
    ::= { etherHistoryEntry 5 }

etherHistoryPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets (including bad packets)
    received during this sampling interval."
    ::= { etherHistoryEntry 6 }

etherHistoryBroadcastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets received during this
    sampling interval that were directed to the
    broadcast address."
    ::= { etherHistoryEntry 7 }

etherHistoryMulticastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets received during this
    sampling interval that were directed to a
    multicast address.  Note that this number does not
    include packets addressed to the broadcast address."
    ::= { etherHistoryEntry 8 }

etherHistoryCRCAlignErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets received during this sampling
    interval that had a length (excluding framing bits
    but including FCS octets) between 64 and 1518
    octets, inclusive, but had either a bad Frame Check
    Sequence (FCS) with an integral number of octets
    (FCS Error) or a bad FCS with a non-integral number
    of octets (Alignment Error)."
    ::= { etherHistoryEntry 9 }

etherHistoryUndersizePkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets received during this
    sampling interval that were less than 64 octets
    long (excluding framing bits but including FCS
    octets) and were otherwise well formed."
    ::= { etherHistoryEntry 10 }

etherHistoryOversizePkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets received during this
    sampling interval that were longer than 1518
    octets (excluding framing bits but including
    FCS octets) but were otherwise well formed."
    ::= { etherHistoryEntry 11 }

etherHistoryFragments OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The total number of packets received during this
    sampling interval that were less than 64 octets in
    length (excluding framing bits but including FCS
    octets) had either a bad Frame Check Sequence (FCS)
    with an integral number of octets (FCS Error) or a bad
    FCS with a non-integral number of octets (Alignment
    Error).

    Note that it is entirely normal for
    etherHistoryFragments to increment.  This is because
    it counts both runts (which are normal occurrences
    due to collisions) and noise hits."
    ::= { etherHistoryEntry 12 }

etherHistoryJabbers OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets received during this
    sampling interval that were longer than 1518 octets
    (excluding framing bits but including FCS octets),
    and  had either a bad Frame Check Sequence (FCS)
    with an integral number of octets (FCS Error) or
    a bad FCS with a non-integral number of octets
    (Alignment Error).

    Note that this definition of jabber is different
    than the definition in IEEE-802.3 section 8.2.1.5
    (10BASE5) and section 10.3.1.4 (10BASE2).  These
    documents define jabber as the condition where any
    packet exceeds 20 ms.  The allowed range to detect
    jabber is between 20 ms and 150 ms."
    ::= { etherHistoryEntry 13 }

etherHistoryCollisions OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The best estimate of the total number of collisions
    on this Ethernet segment during this sampling
    interval.

    The value returned will depend on the location of
    the RMON probe. Section 8.2.1.3 (10BASE-5) and
    section 10.3.1.3 (10BASE-2) of IEEE standard 802.3
    states that a station must detect a collision, in
    the receive mode, if three or more stations are
    transmitting simultaneously.  A repeater port must
    detect a collision when two or more stations are
    transmitting simultaneously.  Thus a probe placed on
    a repeater port could record more collisions than a
    probe connected to a station on the same segment
    would.

    Probe location plays a much smaller role when
    considering 10BASE-T.  14.2.1.4 (10BASE-T) of IEEE
    standard 802.3 defines a collision as the
    simultaneous presence of signals on the DO and RD
    circuits (transmitting and receiving at the same
    time).  A 10BASE-T station can only detect
    collisions when it is transmitting.  Thus probes
    placed on a station and a repeater, should report
    the same number of collisions.

    Note also that an RMON probe inside a repeater
    should ideally report collisions between the
    repeater and one or more other hosts (transmit
    collisions as defined by IEEE 802.3k) plus receiver
    collisions observed on any coax segments to which
    the repeater is connected."
    ::= { etherHistoryEntry 14 }

etherHistoryUtilization OBJECT-TYPE
    SYNTAX INTEGER (0..10000)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The best estimate of the mean physical layer
    network utilization on this interface during this
    sampling interval, in hundredths of a percent."
    ::= { etherHistoryEntry 15 }

-- The Alarm Group

-- Implementation of the Alarm group is optional.
--
-- The Alarm Group requires the implementation of the Event
-- group.
--
-- The Alarm group periodically takes
-- statistical samples from variables in the probe and
-- compares them to thresholds that have been
-- configured.  The alarm table stores configuration
-- entries that each define a variable, polling period,
-- and threshold parameters.  If a sample is found to
-- cross the threshold values, an event is generated.
-- Only variables that resolve to an ASN.1 primitive
-- type of INTEGER (INTEGER, Counter, Gauge, or
-- TimeTicks) may be monitored in this way.
--
-- This function has a hysteresis mechanism to limit
-- the generation of events.  This mechanism generates
-- one event as a threshold is crossed in the
-- appropriate direction.  No more events are generated
-- for that threshold until the opposite threshold is
-- crossed.
--
-- In the case of a sampling a deltaValue, a probe may
-- implement this mechanism with more precision if it
-- takes a delta sample twice per period, each time
-- comparing the sum of the latest two samples to the
-- threshold.  This allows the detection of threshold
-- crossings that span the sampling boundary.  Note
-- that this does not require any special configuration
-- of the threshold value.  It is suggested that probes
-- implement this more precise algorithm.

alarmTable OBJECT-TYPE
    SYNTAX SEQUENCE OF AlarmEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of alarm entries."
    ::= { alarm 1 }

alarmEntry OBJECT-TYPE
    SYNTAX AlarmEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of parameters that set up a periodic checking
    for alarm conditions.  For example, an instance of the
    alarmValue object might be named alarmValue.8"
    INDEX { alarmIndex }
    ::= { alarmTable 1 }

AlarmEntry ::= SEQUENCE {
    alarmIndex                    INTEGER (1..65535),
    alarmInterval                 INTEGER,
    alarmVariable                 OBJECT IDENTIFIER,
    alarmSampleType               INTEGER,
    alarmValue                    INTEGER,
    alarmStartupAlarm             INTEGER,
    alarmRisingThreshold          INTEGER,
    alarmFallingThreshold         INTEGER,
    alarmRisingEventIndex         INTEGER (0..65535),
    alarmFallingEventIndex        INTEGER (0..65535),
    alarmOwner                    OwnerString,
    alarmStatus                   EntryStatus
}

alarmIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    alarm table.  Each such entry defines a
    diagnostic sample at a particular interval
    for an object on the device."
    ::= { alarmEntry 1 }

alarmInterval OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The interval in seconds over which the data is
    sampled and compared with the rising and falling
    thresholds.  When setting this variable, care
    should be taken in the case of deltaValue
    sampling - the interval should be set short enough
    that the sampled variable is very unlikely to
    increase or decrease by more than 2^31 - 1 during
    a single sampling interval.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 2 }

alarmVariable OBJECT-TYPE
    SYNTAX OBJECT IDENTIFIER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The object identifier of the particular variable to
    be sampled.  Only variables that resolve to an ASN.1
    primitive type of INTEGER (INTEGER, Counter, Gauge,
    or TimeTicks) may be sampled.

    Because SNMP access control is articulated entirely
    in terms of the contents of MIB views, no access
    control mechanism exists that can restrict the value
    of this object to identify only those objects that
    exist in a particular MIB view.  Because there is
    thus no acceptable means of restricting the read
    access that could be obtained through the alarm
    mechanism, the probe must only grant write access to
    this object in those views that have read access to
    all objects on the probe.

    During a set operation, if the supplied variable
    name is not available in the selected MIB view, a
    badValue error must be returned.  If at any time the
    variable name of an established alarmEntry is no
    longer available in the selected MIB view, the probe
    must change the status of this alarmEntry to
    invalid(4).

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 3 }

alarmSampleType OBJECT-TYPE
    SYNTAX INTEGER {
    absoluteValue(1),
    deltaValue(2)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The method of sampling the selected variable and
    calculating the value to be compared against the
    thresholds.  If the value of this object is
    absoluteValue(1), the value of the selected variable
    will be compared directly with the thresholds at the
    end of the sampling interval.  If the value of this
    object is deltaValue(2), the value of the selected
    variable at the last sample will be subtracted from
    the current value, and the difference compared with
    the thresholds.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 4 }

alarmValue OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of the statistic during the last sampling
    period.  For example, if the sample type is
    deltaValue, this value will be the difference
    between the samples at the beginning and end of the
    period.  If the sample type is absoluteValue, this
    value will be the sampled value at the end of the
    period.

    This is the value that is compared with the rising and
    falling thresholds.

    The value during the current sampling period is not
    made available until the period is completed and will
    remain available until the next period completes."
    ::= { alarmEntry 5 }

alarmStartupAlarm OBJECT-TYPE
    SYNTAX INTEGER {
    risingAlarm(1),
    fallingAlarm(2),
    risingOrFallingAlarm(3)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The alarm that may be sent when this entry is first
    set to valid.  If the first sample after this entry
    becomes valid is greater than or equal to the
    risingThreshold and alarmStartupAlarm is equal to
    risingAlarm(1) or risingOrFallingAlarm(3), then a
    single rising alarm will be generated.  If the first
    sample after this entry becomes valid is less than
    or equal to the fallingThreshold and
    alarmStartupAlarm is equal to fallingAlarm(2) or
    risingOrFallingAlarm(3), then a single falling alarm
    will be generated.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 6 }

alarmRisingThreshold OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "A threshold for the sampled statistic.  When the
    current sampled value is greater than or equal to
    this threshold, and the value at the last sampling
    interval was less than this threshold, a single
    event will be generated.  A single event will also
    be generated if the first sample after this entry
    becomes valid is greater than or equal to this
    threshold and the associated alarmStartupAlarm is
    equal to risingAlarm(1) or risingOrFallingAlarm(3).

    After a rising event is generated, another such event
    will not be generated until the sampled value
    falls below this threshold and reaches the
    alarmFallingThreshold.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 7 }

alarmFallingThreshold OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "A threshold for the sampled statistic.  When the
    current sampled value is less than or equal to this
    threshold, and the value at the last sampling
    interval was greater than this threshold, a single
    event will be generated.  A single event will also
    be generated if the first sample after this entry
    becomes valid is less than or equal to this
    threshold and the associated alarmStartupAlarm is
    equal to fallingAlarm(2) or risingOrFallingAlarm(3).

    After a falling event is generated, another such event
    will not be generated until the sampled value
    rises above this threshold and reaches the
    alarmRisingThreshold.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 8 }

alarmRisingEventIndex OBJECT-TYPE
    SYNTAX INTEGER (0..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The index of the eventEntry that is
    used when a rising threshold is crossed.  The
    eventEntry identified by a particular value of
    this index is the same as identified by the same value
    of the eventIndex object.  If there is no
    corresponding entry in the eventTable, then
    no association exists.  In particular, if this value
    is zero, no associated event will be generated, as
    zero is not a valid event index.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 9 }

alarmFallingEventIndex OBJECT-TYPE
    SYNTAX INTEGER (0..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The index of the eventEntry that is
    used when a falling threshold is crossed.  The
    eventEntry identified by a particular value of
    this index is the same as identified by the same value
    of the eventIndex object.  If there is no
    corresponding entry in the eventTable, then
    no association exists.  In particular, if this value
    is zero, no associated event will be generated, as
    zero is not a valid event index.

    This object may not be modified if the associated
    alarmStatus object is equal to valid(1)."
    ::= { alarmEntry 10 }

alarmOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { alarmEntry 11 }

alarmStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this alarm entry."
    ::= { alarmEntry 12 }

-- The Host Group

-- Implementation of the Host group is optional.
--
-- The host group discovers new hosts on the network by
-- keeping a list of source and destination MAC Addresses seen
-- in good packets.  For each of these addresses, the host
-- group keeps a set of statistics.  The hostControlTable
-- controls which interfaces this function is performed on,
-- and contains some information about the process.  On
-- behalf of each hostControlEntry, data is collected on an
-- interface and placed in both the hostTable and the
-- hostTimeTable.  If the monitoring device finds itself
-- short of resources, it may delete entries as needed.  It
-- is suggested that the device delete the least recently
-- used entries first.

-- The hostTable contains entries for each address
-- discovered on a particular interface.  Each entry
-- contains statistical data about that host.  This table is
-- indexed by the MAC address of the host, through which a
-- random access may be achieved.

-- The hostTimeTable contains data in the same format as the
-- hostTable, and must contain the same set of hosts, but is
-- indexed using hostTimeCreationOrder rather than
-- hostAddress.
-- The hostTimeCreationOrder is an integer which reflects
-- the relative order in which a particular entry was
-- discovered and thus inserted into the table.  As this
-- order, and thus the index, is among those entries
-- currently in the table, the index for a particular entry
-- may change if an (earlier) entry is deleted.  Thus the
-- association between hostTimeCreationOrder and
-- hostTimeEntry may be broken at any time.

-- The hostTimeTable has two important uses.  The first is the
-- fast download of this potentially large table.  Because the
-- index of this table runs from 1 to the size of the table,
-- inclusive, its values are predictable.  This allows very
-- efficient packing of variables into SNMP PDU's and allows
-- a table transfer to have multiple packets outstanding.
-- These benefits increase transfer rates tremendously.

-- The second use of the hostTimeTable is the efficient
-- discovery by the management station of new entries added
-- to the table. After the management station has downloaded
-- the entire table, it knows that new entries will be added
-- immediately after the end of the current table.  It can
-- thus detect new entries there and retrieve them easily.

-- Because the association between hostTimeCreationOrder and
-- hostTimeEntry may be broken at any time, the management
-- station must monitor the related hostControlLastDeleteTime
-- object.  When the management station thus detects a
-- deletion, it must assume that any such associations have
--- been broken, and invalidate any it has stored locally.
-- This includes restarting any download of the
-- hostTimeTable that may have been in progress, as well as
-- rediscovering the end of the hostTimeTable so that it may
-- detect new entries.  If the management station does not
-- detect the broken association, it may continue to refer
-- to a particular host by its creationOrder while
-- unwittingly retrieving the data associated with another
-- host entirely.  If this happens while downloading the
-- host table, the management station may fail to download
-- all of the entries in the table.

hostControlTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HostControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of host table control entries."
    ::= { hosts 1 }

hostControlEntry OBJECT-TYPE
    SYNTAX HostControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of parameters that set up the discovery of
    hosts on a particular interface and the collection
    of statistics about these hosts.  For example, an
    instance of the hostControlTableSize object might be
    named hostControlTableSize.1"
    INDEX { hostControlIndex }
    ::= { hostControlTable 1 }

HostControlEntry ::= SEQUENCE {
    hostControlIndex            INTEGER (1..65535),
    hostControlDataSource       OBJECT IDENTIFIER,
    hostControlTableSize        INTEGER,
    hostControlLastDeleteTime   TimeTicks,
    hostControlOwner            OwnerString,
    hostControlStatus           EntryStatus
}

hostControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    hostControl table.  Each such entry defines
    a function that discovers hosts on a particular
    interface and places statistics about them in the
    hostTable and the hostTimeTable on behalf of this
    hostControlEntry."
    ::= { hostControlEntry 1 }

hostControlDataSource OBJECT-TYPE
    SYNTAX OBJECT IDENTIFIER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object identifies the source of the data for
    this instance of the host function.  This source
    can be any interface on this device.  In order
    to identify a particular interface, this object shall
    identify the instance of the ifIndex object, defined
    in RFC 1213 and RFC 1573 [4,6], for the desired
    interface. For example, if an entry were to receive
    data from interface #1, this object would be set to
    ifIndex.1.

    The statistics in this group reflect all packets
    on the local network segment attached to the
    identified interface.

    An agent may or may not be able to tell if
    fundamental changes to the media of the interface
    have occurred and necessitate an invalidation of
    this entry.  For example, a hot-pluggable ethernet
    card could be pulled out and replaced by a
    token-ring card.  In such a case, if the agent has
    such knowledge of the change, it is recommended that
    it invalidate this entry.

    This object may not be modified if the associated
    hostControlStatus object is equal to valid(1)."
    ::= { hostControlEntry 2 }

hostControlTableSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of hostEntries in the hostTable and the
    hostTimeTable associated with this hostControlEntry."
    ::= { hostControlEntry 3 }

hostControlLastDeleteTime OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime when the last entry
    was deleted from the portion of the hostTable
    associated with this hostControlEntry.  If no
    deletions have occurred, this value shall be zero."
    ::= { hostControlEntry 4 }

hostControlOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { hostControlEntry 5 }

hostControlStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this hostControl entry.

    If this object is not equal to valid(1), all
    associated entries in the hostTable, hostTimeTable,
    and the hostTopNTable shall be deleted by the
    agent."
    ::= { hostControlEntry 6 }

hostTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HostEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of host entries."
    ::= { hosts 2 }

hostEntry OBJECT-TYPE
    SYNTAX HostEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A collection of statistics for a particular host
    that has been discovered on an interface of this
    device.  For example, an instance of the
    hostOutBroadcastPkts object might be named
    hostOutBroadcastPkts.1.6.8.0.32.27.3.176"
    INDEX { hostIndex, hostAddress }
    ::= { hostTable 1 }

HostEntry ::= SEQUENCE {
    hostAddress             OCTET STRING,
    hostCreationOrder       INTEGER (1..65535),
    hostIndex               INTEGER (1..65535),
    hostInPkts              Counter,
    hostOutPkts             Counter,
    hostInOctets            Counter,
    hostOutOctets           Counter,
    hostOutErrors           Counter,
    hostOutBroadcastPkts    Counter,
    hostOutMulticastPkts    Counter
}

hostAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The physical address of this host."
    ::= { hostEntry 1 }

hostCreationOrder OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that defines the relative ordering of
    the creation time of hosts captured for a
    particular hostControlEntry.  This index shall
    be between 1 and N, where N is the value of
    the associated hostControlTableSize.  The ordering
    of the indexes is based on the order of each entry's
    insertion into the table, in which entries added
    earlier have a lower index value than entries added
    later.

    It is important to note that the order for a
    particular entry may change as an (earlier) entry
    is deleted from the table.  Because this order may
    change, management stations should make use of the
    hostControlLastDeleteTime variable in the
    hostControlEntry associated with the relevant
    portion of the hostTable.  By observing
    this variable, the management station may detect
    the circumstances where a previous association
    between a value of hostCreationOrder
    and a hostEntry may no longer hold."
    ::= { hostEntry 2 }

hostIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The set of collected host statistics of which
    this entry is a part.  The set of hosts
    identified by a particular value of this
    index is associated with the hostControlEntry
    as identified by the same value of hostControlIndex."
    ::= { hostEntry 3 }

hostInPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted to this
    address since it was added to the hostTable."
    ::= { hostEntry 4 }

hostOutPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets, including bad packets,
    transmitted by this address since it was added
    to the hostTable."
    ::= { hostEntry 5 }

hostInOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets transmitted to this address
    since it was added to the hostTable (excluding
    framing bits but including FCS octets), except for
    those octets in bad packets."
    ::= { hostEntry 6 }

hostOutOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets transmitted by this address
    since it was added to the hostTable (excluding
    framing bits but including FCS octets), including
    those octets in bad packets."
    ::= { hostEntry 7 }

hostOutErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of bad packets transmitted by this address
    since this host was added to the hostTable."
    ::= { hostEntry 8 }

hostOutBroadcastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted by this
    address that were directed to the broadcast address
    since this host was added to the hostTable."
    ::= { hostEntry 9 }

hostOutMulticastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted by this
    address that were directed to a multicast address
    since this host was added to the hostTable.
    Note that this number does not include packets
    directed to the broadcast address."
    ::= { hostEntry 10 }

-- host Time Table

hostTimeTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HostTimeEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of time-ordered host table entries."
    ::= { hosts 3 }

hostTimeEntry OBJECT-TYPE
    SYNTAX HostTimeEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A collection of statistics for a particular host
    that has been discovered on an interface of this
    device.  This collection includes the relative
    ordering of the creation time of this object.  For
    example, an instance of the hostTimeOutBroadcastPkts
    object might be named
    hostTimeOutBroadcastPkts.1.687"
    INDEX { hostTimeIndex, hostTimeCreationOrder }
    ::= { hostTimeTable 1 }

HostTimeEntry ::= SEQUENCE {
    hostTimeAddress              OCTET STRING,
    hostTimeCreationOrder        INTEGER (1..65535),
    hostTimeIndex                INTEGER (1..65535),
    hostTimeInPkts               Counter,
    hostTimeOutPkts              Counter,
    hostTimeInOctets             Counter,
    hostTimeOutOctets            Counter,
    hostTimeOutErrors            Counter,
    hostTimeOutBroadcastPkts     Counter,
    hostTimeOutMulticastPkts     Counter
}

hostTimeAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The physical address of this host."
    ::= { hostTimeEntry 1 }

hostTimeCreationOrder OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in
    the hostTime table among those entries associated
    with the same hostControlEntry.  This index shall
    be between 1 and N, where N is the value of
    the associated hostControlTableSize.  The ordering
    of the indexes is based on the order of each entry's
    insertion into the table, in which entries added
    earlier have a lower index value than entries added
    later. Thus the management station has the ability to
    learn of new entries added to this table without
    downloading the entire table.

    It is important to note that the index for a
    particular entry may change as an (earlier) entry
    is deleted from the table.  Because this order may
    change, management stations should make use of the
    hostControlLastDeleteTime variable in the
    hostControlEntry associated with the relevant
    portion of the hostTimeTable.  By observing
    this variable, the management station may detect
    the circumstances where a download of the table
    may have missed entries, and where a previous
    association between a value of hostTimeCreationOrder
    and a hostTimeEntry may no longer hold."
    ::= { hostTimeEntry 2 }

hostTimeIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The set of collected host statistics of which
    this entry is a part.  The set of hosts
    identified by a particular value of this
    index is associated with the hostControlEntry
    as identified by the same value of hostControlIndex."
    ::= { hostTimeEntry 3 }

hostTimeInPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted to this
    address since it was added to the hostTimeTable."
    ::= { hostTimeEntry 4 }

hostTimeOutPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of god packets transmitted by this
    address since it was added to the hostTimeTable."
    ::= { hostTimeEntry 5 }

hostTimeInOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets transmitted to this address
    since it was added to the hostTimeTable (excluding
    framing bits but including FCS octets), except for
    those octets in bad packets."
    ::= { hostTimeEntry 6 }

hostTimeOutOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets transmitted by this address
    since it was added to the hostTimeTable (excluding
    framing bits but including FCS octets), including
    those octets in bad packets."
    ::= { hostTimeEntry 7 }

hostTimeOutErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of bad packets transmitted by this address
    since this host was added to the hostTimeTable."
    ::= { hostTimeEntry 8 }

hostTimeOutBroadcastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted by this
    address that were directed to the broadcast address
    since this host was added to the hostTimeTable."
    ::= { hostTimeEntry 9 }

hostTimeOutMulticastPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of good packets transmitted by this
    address that were directed to a multicast address
    since this host was added to the hostTimeTable.
    Note that this number does not include packets
    directed to the broadcast address."
    ::= { hostTimeEntry 10 }

-- The Host Top "N" Group

-- Implementation of the Host Top N group is optional.
--
-- The Host Top N group requires the implementation of the
-- host group.
--
-- The Host Top N group is used to prepare reports that
-- describe the hosts that top a list ordered by one of
-- their statistics.
-- The available statistics are samples of one of their
-- base statistics, over an interval specified by the
-- management station.  Thus, these statistics are rate
-- based.  The management station also selects how many such
-- hosts are reported.

-- The hostTopNControlTable is used to initiate the
-- generation of such a report.  The management station
-- may select the parameters of such a report, such as
-- which interface, which statistic, how many hosts,
-- and the start and stop times of the sampling.  When
-- the report is prepared, entries are created in the
-- hostTopNTable associated with the relevant
-- hostTopNControlEntry.  These entries are static for
-- each report after it has been prepared.

hostTopNControlTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HostTopNControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of top N host control entries."
    ::= { hostTopN 1 }

hostTopNControlEntry OBJECT-TYPE
    SYNTAX HostTopNControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of parameters that control the creation of a
    report of the top N hosts according to several
    metrics.  For example, an instance of the
    hostTopNDuration object might be named
    hostTopNDuration.3"
    INDEX { hostTopNControlIndex }
    ::= { hostTopNControlTable 1 }

HostTopNControlEntry ::= SEQUENCE {
    hostTopNControlIndex    INTEGER (1..65535),
    hostTopNHostIndex       INTEGER (1..65535),
    hostTopNRateBase        INTEGER,
    hostTopNTimeRemaining   INTEGER,
    hostTopNDuration        INTEGER,
    hostTopNRequestedSize   INTEGER,
    hostTopNGrantedSize     INTEGER,
    hostTopNStartTime       TimeTicks,
    hostTopNOwner           OwnerString,
    hostTopNStatus          EntryStatus
}

hostTopNControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry
    in the hostTopNControl table.  Each such
    entry defines one top N report prepared for
    one interface."
    ::= { hostTopNControlEntry 1 }

hostTopNHostIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The host table for which a top N report will be
    prepared on behalf of this entry.  The host table
    identified by a particular value of this index is
    associated with the same host table as identified by
    the same value of hostIndex.

    This object may not be modified if the associated
    hostTopNStatus object is equal to valid(1)."
    ::= { hostTopNControlEntry 2 }

hostTopNRateBase OBJECT-TYPE
    SYNTAX INTEGER {
        hostTopNInPkts(1),
        hostTopNOutPkts(2),
        hostTopNInOctets(3),
        hostTopNOutOctets(4),
        hostTopNOutErrors(5),
        hostTopNOutBroadcastPkts(6),
        hostTopNOutMulticastPkts(7)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The variable for each host that the hostTopNRate
    variable is based upon.

    This object may not be modified if the associated
    hostTopNStatus object is equal to valid(1)."
    ::= { hostTopNControlEntry 3 }

hostTopNTimeRemaining OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The number of seconds left in the report currently
    being collected.  When this object is modified by
    the management station, a new collection is started,
    possibly aborting a currently running report.  The
    new value is used as the requested duration of this
    report, which is loaded into the associated
    hostTopNDuration object.

    When this object is set to a non-zero value, any
    associated hostTopNEntries shall be made
    inaccessible by the monitor.  While the value of
    this object is non-zero, it decrements by one per
    second until it reaches zero.  During this time, all
    associated hostTopNEntries shall remain
    inaccessible.  At the time that this object
    decrements to zero, the report is made accessible in
    the hostTopNTable.  Thus, the hostTopN table needs
    to be created only at the end of the collection
    interval."
    DEFVAL { 0 }
    ::= { hostTopNControlEntry 4 }

hostTopNDuration OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of seconds that this report has collected
    during the last sampling interval, or if this
    report is currently being collected, the number
    of seconds that this report is being collected
    during this sampling interval.

    When the associated hostTopNTimeRemaining object is
    set, this object shall be set by the probe to the
    same value and shall not be modified until the next
    time the hostTopNTimeRemaining is set.

    This value shall be zero if no reports have been
    requested for this hostTopNControlEntry."
    DEFVAL { 0 }
    ::= { hostTopNControlEntry 5 }

hostTopNRequestedSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The maximum number of hosts requested for the top N
    table.

    When this object is created or modified, the probe
    should set hostTopNGrantedSize as closely to this
    object as is possible for the particular probe
    implementation and available resources."
    DEFVAL { 10 }
    ::= { hostTopNControlEntry 6 }

hostTopNGrantedSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The maximum number of hosts in the top N table.

    When the associated hostTopNRequestedSize object is
    created or modified, the probe should set this
    object as closely to the requested value as is
    possible for the particular implementation and
    available resources. The probe must not lower this
    value except as a result of a set to the associated
    hostTopNRequestedSize object.
    Hosts with the highest value of hostTopNRate shall be
    placed in this table in decreasing order of this rate
    until there is no more room or until there are no more
    hosts."
    ::= { hostTopNControlEntry 7 }

hostTopNStartTime OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime when this top N report was
    last started.  In other words, this is the time that
    the associated hostTopNTimeRemaining object was
    modified to start the requested report."
    ::= { hostTopNControlEntry 8 }

hostTopNOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { hostTopNControlEntry 9 }

hostTopNStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this hostTopNControl entry.

    If this object is not equal to valid(1), all
    associated hostTopNEntries shall be deleted by the
    agent."
    ::= { hostTopNControlEntry 10 }

hostTopNTable OBJECT-TYPE
    SYNTAX SEQUENCE OF HostTopNEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of top N host entries."
    ::= { hostTopN 2 }

hostTopNEntry OBJECT-TYPE
    SYNTAX HostTopNEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of statistics for a host that is part of a
    top N report.  For example, an instance of the
    hostTopNRate object might be named
    hostTopNRate.3.10"
    INDEX { hostTopNReport, hostTopNIndex }
    ::= { hostTopNTable 1 }

HostTopNEntry ::= SEQUENCE {
    hostTopNReport                INTEGER (1..65535),
    hostTopNIndex                 INTEGER (1..65535),
    hostTopNAddress               OCTET STRING,
    hostTopNRate                  INTEGER
}

hostTopNReport OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "This object identifies the top N report of which
    this entry is a part.  The set of hosts
    identified by a particular value of this
    object is part of the same report as identified
    by the same value of the hostTopNControlIndex object."
    ::= { hostTopNEntry 1 }

hostTopNIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in
    the hostTopN table among those in the same report.
    This index is between 1 and N, where N is the
    number of entries in this table.  Increasing values
    of hostTopNIndex shall be assigned to entries with
    decreasing values of hostTopNRate until index N
    is assigned to the entry with the lowest value of
    hostTopNRate or there are no more hostTopNEntries."
    ::= { hostTopNEntry 2 }

hostTopNAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The physical address of this host."
    ::= { hostTopNEntry 3 }

hostTopNRate OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The amount of change in the selected variable
    during this sampling interval.  The selected
    variable is this host's instance of the object
    selected by hostTopNRateBase."
    ::= { hostTopNEntry 4 }

-- The Matrix Group

-- Implementation of the Matrix group is optional.
--
-- The Matrix group consists of the matrixControlTable,
-- matrixSDTable and the matrixDSTable.  These tables
-- store statistics for a particular conversation
-- between two addresses.  As the device detects a new
-- conversation, including those to a non-unicast
-- address, it creates a new entry in both of the
-- matrix tables.  It must only create new entries
-- based on information received in good packets.  If
-- the monitoring device finds itself short of
-- resources, it may delete entries as needed.  It is
-- suggested that the device delete the least recently
-- used entries first.

matrixControlTable OBJECT-TYPE
    SYNTAX SEQUENCE OF MatrixControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of information entries for the
    traffic matrix on each interface."
    ::= { matrix 1 }

matrixControlEntry OBJECT-TYPE
    SYNTAX MatrixControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "Information about a traffic matrix on a particular
    interface.  For example, an instance of the
    matrixControlLastDeleteTime object might be named
    matrixControlLastDeleteTime.1"
    INDEX { matrixControlIndex }
    ::= { matrixControlTable 1 }

MatrixControlEntry ::= SEQUENCE {
    matrixControlIndex           INTEGER (1..65535),
    matrixControlDataSource      OBJECT IDENTIFIER,
    matrixControlTableSize       INTEGER,
    matrixControlLastDeleteTime  TimeTicks,
    matrixControlOwner           OwnerString,
    matrixControlStatus          EntryStatus
}

matrixControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    matrixControl table.  Each such entry defines
    a function that discovers conversations on a
    particular interface and places statistics about
    them in the matrixSDTable and the matrixDSTable on
    behalf of this matrixControlEntry."
    ::= { matrixControlEntry 1 }

matrixControlDataSource OBJECT-TYPE
    SYNTAX OBJECT IDENTIFIER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object identifies the source of
    the data from which this entry creates a traffic
    matrix. This source can be any interface on this
    device.  In order to identify a particular
    interface, this object shall identify the instance
    of the ifIndex object, defined in RFC 1213 and RFC
    1573 [4,6], for the desired interface.  For example,
    if an entry were to receive data from interface #1,
    this object would be set to ifIndex.1.

    The statistics in this group reflect all packets
    on the local network segment attached to the
    identified interface.

    An agent may or may not be able to tell if
    fundamental changes to the media of the interface
    have occurred and necessitate an invalidation of
    this entry.  For example, a hot-pluggable ethernet
    card could be pulled out and replaced by a
    token-ring card.  In such a case, if the agent has
    such knowledge of the change, it is recommended that
    it invalidate this entry.

    This object may not be modified if the associated
    matrixControlStatus object is equal to valid(1)."
    ::= { matrixControlEntry 2 }

matrixControlTableSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of matrixSDEntries in the matrixSDTable
    for this interface.  This must also be the value of
    the number of entries in the matrixDSTable for this
    interface."
    ::= { matrixControlEntry 3 }

matrixControlLastDeleteTime OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime when the last entry
    was deleted from the portion of the matrixSDTable
    or matrixDSTable associated with this
    matrixControlEntry. If no deletions have occurred,
    this value shall be zero."
    ::= { matrixControlEntry 4 }

matrixControlOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { matrixControlEntry 5 }

matrixControlStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this matrixControl entry.

    If this object is not equal to valid(1), all
    associated entries in the matrixSDTable and the
    matrixDSTable shall be deleted by the agent."
    ::= { matrixControlEntry 6 }

matrixSDTable OBJECT-TYPE
    SYNTAX SEQUENCE OF MatrixSDEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of traffic matrix entries indexed by
    source and destination MAC address."
    ::= { matrix 2 }

matrixSDEntry OBJECT-TYPE
    SYNTAX MatrixSDEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A collection of statistics for communications between
    two addresses on a particular interface.  For example,
    an instance of the matrixSDPkts object might be named
    matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113"
    INDEX { matrixSDIndex,
        matrixSDSourceAddress, matrixSDDestAddress }
    ::= { matrixSDTable 1 }

MatrixSDEntry ::= SEQUENCE {
    matrixSDSourceAddress       OCTET STRING,
    matrixSDDestAddress         OCTET STRING,
    matrixSDIndex               INTEGER (1..65535),
    matrixSDPkts                Counter,
    matrixSDOctets              Counter,
    matrixSDErrors              Counter
}

matrixSDSourceAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The source physical address."
    ::= { matrixSDEntry 1 }

matrixSDDestAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The destination physical address."
    ::= { matrixSDEntry 2 }

matrixSDIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The set of collected matrix statistics of which
    this entry is a part.  The set of matrix statistics
    identified by a particular value of this index
    is associated with the same matrixControlEntry
    as identified by the same value of
    matrixControlIndex."
    ::= { matrixSDEntry 3 }

matrixSDPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets transmitted from the source
    address to the destination address (this number
    includes bad packets)."
    ::= { matrixSDEntry 4 }

matrixSDOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets (excluding framing bits but
    including FCS octets) contained in all packets
    transmitted from the source address to the
    destination address."
    ::= { matrixSDEntry 5 }

matrixSDErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of bad packets transmitted from
    the source address to the destination address."
    ::= { matrixSDEntry 6 }

-- Traffic matrix tables from destination to source

matrixDSTable OBJECT-TYPE
    SYNTAX SEQUENCE OF MatrixDSEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of traffic matrix entries indexed by
    destination and source MAC address."
    ::= { matrix 3 }

matrixDSEntry OBJECT-TYPE
    SYNTAX MatrixDSEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A collection of statistics for communications between
    two addresses on a particular interface.  For example,
    an instance of the matrixSDPkts object might be named
    matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176"
    INDEX { matrixDSIndex,
        matrixDSDestAddress, matrixDSSourceAddress }
    ::= { matrixDSTable 1 }

MatrixDSEntry ::= SEQUENCE {
    matrixDSSourceAddress       OCTET STRING,
    matrixDSDestAddress         OCTET STRING,
    matrixDSIndex               INTEGER (1..65535),
    matrixDSPkts                Counter,
    matrixDSOctets              Counter,
    matrixDSErrors              Counter
}

matrixDSSourceAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The source physical address."
    ::= { matrixDSEntry 1 }

matrixDSDestAddress OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The destination physical address."
    ::= { matrixDSEntry 2 }

matrixDSIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The set of collected matrix statistics of which
    this entry is a part.  The set of matrix statistics
    identified by a particular value of this index
    is associated with the same matrixControlEntry
    as identified by the same value of
    matrixControlIndex."
    ::= { matrixDSEntry 3 }

matrixDSPkts OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets transmitted from the source
    address to the destination address (this number
    includes bad packets)."
    ::= { matrixDSEntry 4 }

matrixDSOctets OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of octets (excluding framing bits
    but including FCS octets) contained in all packets
    transmitted from the source address to the
    destination address."
    ::= { matrixDSEntry 5 }

matrixDSErrors OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of bad packets transmitted from
    the source address to the destination address."
    ::= { matrixDSEntry 6 }

-- The Filter Group

-- Implementation of the Filter group is optional.
--
-- The Filter group allows packets to be captured with an
-- arbitrary filter expression.  A logical data and
-- event stream or "channel" is formed by the packets
-- that match the filter expression.
--
-- This filter mechanism allows the creation of an arbitrary
-- logical expression with which to filter packets.  Each
-- filter associated with a channel is OR'ed with the others.
-- Within a filter, any bits checked in the data and status
-- are AND'ed with respect to other bits in the same filter.
-- The NotMask also allows for checking for inequality.
-- Finally, the channelAcceptType object allows for
-- inversion of the whole equation.
--
-- If a management station wishes to receive a trap to alert
-- it that new packets have been captured and are available
-- for download, it is recommended that it set up an alarm
-- entry that monitors the value of the relevant
-- channelMatches instance.
--
-- The channel can be turned on or off, and can also
-- generate events when packets pass through it.

filterTable OBJECT-TYPE
    SYNTAX SEQUENCE OF FilterEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of packet filter entries."
    ::= { filter 1 }

filterEntry OBJECT-TYPE
    SYNTAX FilterEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of parameters for a packet filter applied on a
    particular interface.  As an example, an instance of
    the filterPktData object might be named
    filterPktData.12"
    INDEX { filterIndex }
    ::= { filterTable 1 }

FilterEntry ::= SEQUENCE {
    filterIndex                 INTEGER (1..65535),
    filterChannelIndex          INTEGER (1..65535),
    filterPktDataOffset         INTEGER,
    filterPktData               OCTET STRING,
    filterPktDataMask           OCTET STRING,
    filterPktDataNotMask        OCTET STRING,
    filterPktStatus             INTEGER,
    filterPktStatusMask         INTEGER,
    filterPktStatusNotMask      INTEGER,
    filterOwner                 OwnerString,
    filterStatus                EntryStatus
}

filterIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry
    in the filter table.  Each such entry defines
    one filter that is to be applied to every packet
    received on an interface."
    ::= { filterEntry 1 }

filterChannelIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object identifies the channel of which this
    filter is a part.  The filters identified by a
    particular value of this object are associated with
    the same channel as identified by the same value of
    the channelIndex object."
    ::= { filterEntry 2 }

filterPktDataOffset OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The offset from the beginning of each packet where
    a match of packet data will be attempted.  This offset
    is measured from the point in the physical layer
    packet after the framing bits, if any.  For example,
    in an Ethernet frame, this point is at the beginning
    of the destination MAC address.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    DEFVAL { 0 }
    ::= { filterEntry 3 }

filterPktData OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The data that is to be matched with the input
    packet.  For each packet received, this filter and
    the accompanying filterPktDataMask and
    filterPktDataNotMask will be adjusted for the
    offset.  The only bits relevant to this match
    algorithm are those that have the corresponding
    filterPktDataMask bit equal to one.  The following
    three rules are then applied to every packet:

    (1) If the packet is too short and does not have data
        corresponding to part of the filterPktData, the
        packet will fail this data match.

    (2) For each relevant bit from the packet with the
        corresponding filterPktDataNotMask bit set to
        zero, if the bit from the packet is not equal to
        the corresponding bit from the filterPktData,
        then the packet will fail this data match.

    (3) If for every relevant bit from the packet with the
        corresponding filterPktDataNotMask bit set to one,
        the bit from the packet is equal to the
        corresponding bit from the filterPktData, then
        the packet will fail this data match.

    Any packets that have not failed any of the three
    matches above have passed this data match.  In
    particular, a zero length filter will match any
    packet.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 4 }

filterPktDataMask OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The mask that is applied to the match process.
    After adjusting this mask for the offset, only those
    bits in the received packet that correspond to bits
    set in this mask are relevant for further processing
    by the match algorithm.  The offset is applied to
    filterPktDataMask in the same way it is applied to the
    filter.  For the purposes of the matching algorithm,
    if the associated filterPktData object is longer
    than this mask, this mask is conceptually extended
    with '1' bits until it reaches the length of the
    filterPktData object.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 5 }

filterPktDataNotMask OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The inversion mask that is applied to the match
    process.  After adjusting this mask for the offset,
    those relevant bits in the received packet that
    correspond to bits cleared in this mask must all be
    equal to their corresponding bits in the
    filterPktData object for the packet to be accepted.
    In addition, at least one of those relevant bits in
    the received packet that correspond to bits set in
    this mask must be different to its corresponding bit
    in the filterPktData object.

    For the purposes of the matching algorithm, if the
    associated filterPktData object is longer than this
    mask, this mask is conceptually extended with '0'
    bits until it reaches the length of the
    filterPktData object.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 6 }

filterPktStatus OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status that is to be matched with the input
    packet.  The only bits relevant to this match
    algorithm are those that have the corresponding
    filterPktStatusMask bit equal to one.  The following
    two rules are then applied to every packet:

    (1) For each relevant bit from the packet status
        with the corresponding filterPktStatusNotMask bit
        set to zero, if the bit from the packet status is
        not equal to the corresponding bit from the
        filterPktStatus, then the packet will fail this
        status match.

    (2) If for every relevant bit from the packet status
        with the corresponding filterPktStatusNotMask bit
        set to one, the bit from the packet status is
        equal to the corresponding bit from the
        filterPktStatus, then the packet will fail this
        status match.

    Any packets that have not failed either of the two
    matches above have passed this status match.  In
    particular, a zero length status filter will match any
    packet's status.

    The value of the packet status is a sum.  This sum
    initially takes the value zero.  Then, for each
    error, E, that has been discovered in this packet,
    2 raised to a value representing E is added to the
    sum. The errors and the bits that represent them are
    dependent on the media type of the interface that
    this channel is receiving packets from.

    The errors defined for a packet captured off of an
    Ethernet interface are as follows:

        bit #    Error
        0    Packet is longer than 1518 octets
        1    Packet is shorter than 64 octets
        2    Packet experienced a CRC or Alignment
             error

    For example, an Ethernet fragment would have a
    value of 6 (2^1 + 2^2).

    As this MIB is expanded to new media types, this
    object will have other media-specific errors
    defined.

    For the purposes of this status matching algorithm,
    if the packet status is longer than this
    filterPktStatus object, this object is conceptually
    extended with '0' bits until it reaches the size of
    the packet status.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 7 }

filterPktStatusMask OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The mask that is applied to the status match
    process.  Only those bits in the received packet
    that correspond to bits set in this mask are
    relevant for further processing by the status match
    algorithm.  For the purposes of the matching
    algorithm, if the associated filterPktStatus object
    is longer than this mask, this mask is conceptually
    extended with '1' bits until it reaches the size of
    the filterPktStatus.  In addition, if a packet
    status is longer than this mask, this mask is
    conceptually extended with '0' bits until it reaches
    the size of the packet status.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 8 }

filterPktStatusNotMask OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The inversion mask that is applied to the status
    match process.  Those relevant bits in the received
    packet status that correspond to bits cleared in
    this mask must all be equal to their corresponding
    bits in the filterPktStatus object for the packet to
    be accepted.  In addition, at least one of those
    relevant bits in the received packet status that
    correspond to bits set in this mask must be
    different to its corresponding bit in the
    filterPktStatus object for the packet to be
    accepted.

    For the purposes of the matching algorithm, if the
    associated filterPktStatus object or a packet status
    is longer than this mask, this mask is conceptually
    extended with '0' bits until it reaches the longer
    of the lengths of the filterPktStatus object and the
    packet status.

    This object may not be modified if the associated
    filterStatus object is equal to valid(1)."
    ::= { filterEntry 9 }

filterOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { filterEntry 10 }

filterStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this filter entry."
    ::= { filterEntry 11 }

channelTable OBJECT-TYPE
    SYNTAX SEQUENCE OF ChannelEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of packet channel entries."
    ::= { filter 2 }

channelEntry OBJECT-TYPE
    SYNTAX ChannelEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of parameters for a packet channel applied on a
    particular interface.  As an example, an instance of
    the channelMatches object might be named
    channelMatches.3"
    INDEX { channelIndex }
    ::= { channelTable 1 }

ChannelEntry ::= SEQUENCE {
    channelIndex               INTEGER (1..65535),
    channelIfIndex             INTEGER (1..65535),
    channelAcceptType          INTEGER,
    channelDataControl         INTEGER,
    channelTurnOnEventIndex    INTEGER (0..65535),
    channelTurnOffEventIndex   INTEGER (0..65535),
    channelEventIndex          INTEGER (0..65535),
    channelEventStatus         INTEGER,
    channelMatches             Counter,
    channelDescription         DisplayString (SIZE (0..127)),
    channelOwner               OwnerString,
    channelStatus              EntryStatus
}

channelIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    channel table.  Each such entry defines one channel,
    a logical data and event stream.

    It is suggested that before creating a channel, an
    application should scan all instances of the
    filterChannelIndex object to make sure that there
    are no pre-existing filters that would be
    inadvertently be linked to the channel."
    ::= { channelEntry 1 }

channelIfIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The value of this object uniquely identifies the
    interface on this remote network monitoring device
    to which the associated filters are applied to allow
    data into this channel.  The interface identified by
    a particular value of this object is the same
    interface as identified by the same value of the
    ifIndex object, defined in RFC 1213 and RFC 1573
    [4,6].

    The filters in this group are applied to all packets
    on the local network segment attached to the
    identified interface.

    An agent may or may not be able to tell if
    fundamental changes to the media of the interface
    have occurred and necessitate an invalidation of
    this entry.  For example, a hot-pluggable ethernet
    card could be pulled out and replaced by a
    token-ring card.  In such a case, if the agent has
    such knowledge of the change, it is recommended that
    it invalidate this entry.

    This object may not be modified if the associated
    channelStatus object is equal to valid(1)."
    ::= { channelEntry 2 }

channelAcceptType OBJECT-TYPE
    SYNTAX INTEGER {
    acceptMatched(1),
    acceptFailed(2)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object controls the action of the filters
    associated with this channel.  If this object is equal
    to acceptMatched(1), packets will be accepted to this
    channel if they are accepted by both the packet data
    and packet status matches of an associated filter.  If
    this object is equal to acceptFailed(2), packets will
    be accepted to this channel only if they fail either
    the packet data match or the packet status match of
    each of the associated filters.

    In particular, a channel with no associated filters
    will match no packets if set to acceptMatched(1)
    case and will match all packets in the
    acceptFailed(2) case.

    This object may not be modified if the associated
    channelStatus object is equal to valid(1)."
    ::= { channelEntry 3 }

channelDataControl OBJECT-TYPE
    SYNTAX INTEGER {
    on(1),
    off(2)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "This object controls the flow of data through this
    channel.  If this object is on(1), data, status and
    events flow through this channel.  If this object is
    off(2), data, status and events will not flow
    through this channel."
    DEFVAL { off }
    ::= { channelEntry 4 }

channelTurnOnEventIndex OBJECT-TYPE
    SYNTAX INTEGER (0..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The value of this object identifies the event
    that is configured to turn the associated
    channelDataControl from off to on when the event is
    generated.  The event identified by a particular value
    of this object is the same event as identified by the
    same value of the eventIndex object.  If there is no
    corresponding entry in the eventTable, then no
    association exists.  In fact, if no event is intended
    for this channel, channelTurnOnEventIndex must be
    set to zero, a non-existent event index.

    This object may not be modified if the associated
    channelStatus object is equal to valid(1)."
    ::= { channelEntry 5 }

channelTurnOffEventIndex OBJECT-TYPE
    SYNTAX INTEGER (0..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The value of this object identifies the event
    that is configured to turn the associated
    channelDataControl from on to off when the event is
    generated.  The event identified by a particular value
    of this object is the same event as identified by the
    same value of the eventIndex object.  If there is no
    corresponding entry in the eventTable, then no
    association exists.  In fact, if no event is intended
    for this channel, channelTurnOffEventIndex must be
    set to zero, a non-existent event index.

    This object may not be modified if the associated
    channelStatus object is equal to valid(1)."
    ::= { channelEntry 6 }

channelEventIndex OBJECT-TYPE
    SYNTAX INTEGER (0..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The value of this object identifies the event
    that is configured to be generated when the
    associated channelDataControl is on and a packet
    is matched.  The event identified by a particular
    value of this object is the same event as identified
    by the same value of the eventIndex object.  If
    there is no corresponding entry in the eventTable,
    then no association exists.  In fact, if no event is
    intended for this channel, channelEventIndex must be
    set to zero, a non-existent event index.

    This object may not be modified if the associated
    channelStatus object is equal to valid(1)."
    ::= { channelEntry 7 }

channelEventStatus OBJECT-TYPE
    SYNTAX INTEGER {
    eventReady(1),
    eventFired(2),
    eventAlwaysReady(3)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The event status of this channel.

    If this channel is configured to generate events
    when packets are matched, a means of controlling
    the flow of those events is often needed.  When
    this object is equal to eventReady(1), a single
    event may be generated, after which this object
    will be set by the probe to eventFired(2).  While
    in the eventFired(2) state, no events will be
    generated until the object is modified to
    eventReady(1) (or eventAlwaysReady(3)).  The
    management station can thus easily respond to a
    notification of an event by re-enabling this object.

    If the management station wishes to disable this
    flow control and allow events to be generated
    at will, this object may be set to
    eventAlwaysReady(3).  Disabling the flow control
    is discouraged as it can result in high network
    traffic or other performance problems."
    DEFVAL { eventReady }
    ::= { channelEntry 8 }

channelMatches OBJECT-TYPE
    SYNTAX Counter
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of times this channel has matched a
    packet. Note that this object is updated even when
    channelDataControl is set to off."
    ::= { channelEntry 9 }

channelDescription OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..127))
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "A comment describing this channel."
    ::= { channelEntry 10 }

channelOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { channelEntry 11 }

channelStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this channel entry."
    ::= { channelEntry 12 }

-- The Packet Capture Group

-- Implementation of the Packet Capture group is optional.
--
-- The Packet Capture Group requires implementation of the
-- Filter Group.
--
-- The Packet Capture group allows packets to be captured
-- upon a filter match.  The bufferControlTable controls
-- the captured packets output from a channel that is
-- associated with it.  The captured packets are placed
-- in entries in the captureBufferTable.  These entries are
-- associated with the bufferControlEntry on whose behalf they
-- were stored.

bufferControlTable OBJECT-TYPE
    SYNTAX SEQUENCE OF BufferControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of buffers control entries."
    ::= { capture 1 }

bufferControlEntry OBJECT-TYPE
    SYNTAX BufferControlEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of parameters that control the collection of
    a stream of packets that have matched filters.  As
    an example, an instance of the
    bufferControlCaptureSliceSize object might be named
    bufferControlCaptureSliceSize.3"
    INDEX { bufferControlIndex }
    ::= { bufferControlTable 1 }

BufferControlEntry ::= SEQUENCE {
    bufferControlIndex                INTEGER (1..65535),
    bufferControlChannelIndex         INTEGER (1..65535),
    bufferControlFullStatus           INTEGER,
    bufferControlFullAction           INTEGER,
    bufferControlCaptureSliceSize     INTEGER,
    bufferControlDownloadSliceSize    INTEGER,
    bufferControlDownloadOffset       INTEGER,
    bufferControlMaxOctetsRequested   INTEGER,
    bufferControlMaxOctetsGranted     INTEGER,
    bufferControlCapturedPackets      INTEGER,
    bufferControlTurnOnTime           TimeTicks,
    bufferControlOwner                OwnerString,
    bufferControlStatus               EntryStatus
}

bufferControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry
    in the bufferControl table.  The value of this
    index shall never be zero.  Each such
    entry defines one set of packets that is
    captured and controlled by one or more filters."
    ::= { bufferControlEntry 1 }

bufferControlChannelIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "An index that identifies the channel that is the
    source of packets for this bufferControl table.
    The channel identified by a particular value of this
    index is the same as identified by the same value of
    the channelIndex object.

    This object may not be modified if the associated
    bufferControlStatus object is equal to valid(1)."
    ::= { bufferControlEntry 2 }

bufferControlFullStatus OBJECT-TYPE
    SYNTAX INTEGER {
        spaceAvailable(1),
        full(2)
    }
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "This object shows whether the buffer has room to
    accept new packets or if it is full.

    If the status is spaceAvailable(1), the buffer is
    accepting new packets normally.  If the status is
    full(2) and the associated bufferControlFullAction
    object is wrapWhenFull, the buffer is accepting new
    packets by deleting enough of the oldest packets
    to make room for new ones as they arrive.  Otherwise,
    if the status is full(2) and the
    bufferControlFullAction object is lockWhenFull,
    then the buffer has stopped collecting packets.

    When this object is set to full(2) the probe must
    not later set it to spaceAvailable(1) except in the
    case of a significant gain in resources such as
    an increase of bufferControlOctetsGranted.  In
    particular, the wrap-mode action of deleting old
    packets to make room for newly arrived packets
    must not affect the value of this object."
    ::= { bufferControlEntry 3 }

bufferControlFullAction OBJECT-TYPE
    SYNTAX INTEGER {
        lockWhenFull(1),
        wrapWhenFull(2)    -- FIFO
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "Controls the action of the buffer when it
    reaches the full status.  When in the lockWhenFull(1)
    state and a packet is added to the buffer that
    fills the buffer, the bufferControlFullStatus will
    be set to full(2) and this buffer will stop capturing
    packets."
    ::= { bufferControlEntry 4 }

bufferControlCaptureSliceSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The maximum number of octets of each packet
    that will be saved in this capture buffer.
    For example, if a 1500 octet packet is received by
    the probe and this object is set to 500, then only
    500 octets of the packet will be stored in the
    associated capture buffer.  If this variable is set
    to 0, the capture buffer will save as many octets
    as is possible.

    This object may not be modified if the associated
    bufferControlStatus object is equal to valid(1)."
    DEFVAL { 100 }
    ::= { bufferControlEntry 5 }

bufferControlDownloadSliceSize OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The maximum number of octets of each packet
    in this capture buffer that will be returned in
    an SNMP retrieval of that packet.  For example,
    if 500 octets of a packet have been stored in the
    associated capture buffer, the associated
    bufferControlDownloadOffset is 0, and this
    object is set to 100, then the captureBufferPacket
    object that contains the packet will contain only
    the first 100 octets of the packet.

    A prudent manager will take into account possible
    interoperability or fragmentation problems that may
    occur if the download slice size is set too large.
    In particular, conformant SNMP implementations are not
    required to accept messages whose length exceeds 484
    octets, although they are encouraged to support larger
    datagrams whenever feasible."
    DEFVAL { 100 }
    ::= { bufferControlEntry 6 }

bufferControlDownloadOffset OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The offset of the first octet of each packet
    in this capture buffer that will be returned in
    an SNMP retrieval of that packet.  For example,
    if 500 octets of a packet have been stored in the
    associated capture buffer and this object is set to
    100, then the captureBufferPacket object that
    contains the packet will contain bytes starting
    100 octets into the packet."
    DEFVAL { 0 }
    ::= { bufferControlEntry 7 }

bufferControlMaxOctetsRequested OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The requested maximum number of octets to be
    saved in this captureBuffer, including any
    implementation-specific overhead. If this variable
    is set to -1, the capture buffer will save as many
    octets as is possible.

    When this object is created or modified, the probe
    should set bufferControlMaxOctetsGranted as closely
    to this object as is possible for the particular probe
    implementation and available resources.  However, if
    the object has the special value of -1, the probe
    must set bufferControlMaxOctetsGranted to -1."
    DEFVAL { -1 }
    ::= { bufferControlEntry 8 }

bufferControlMaxOctetsGranted OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The maximum number of octets that can be
    saved in this captureBuffer, including overhead.
    If this variable is -1, the capture buffer will save
    as many octets as possible.

    When the bufferControlMaxOctetsRequested object is
    created or modified, the probe should set this object
    as closely to the requested value as is possible for
    the particular probe implementation and available
    resources.
    However, if the request object has the special value
    of -1, the probe must set this object to -1.
    The probe must not lower this value except as a result
    of a modification to the associated
    bufferControlMaxOctetsRequested object.

    When this maximum number of octets is reached
    and a new packet is to be added to this
    capture buffer and the corresponding
    bufferControlFullAction is set to wrapWhenFull(2),
    enough of the oldest packets associated with this
    capture buffer shall be deleted by the agent so
    that the new packet can be added.  If the
    corresponding bufferControlFullAction is set to
    lockWhenFull(1), the new packet shall be discarded.
    In either case, the probe must set
    bufferControlFullStatus to full(2).

    When the value of this object changes to a value less
    than the current value, entries are deleted from
    the captureBufferTable associated with this
    bufferControlEntry.  Enough of the
    oldest of these captureBufferEntries shall be
    deleted by the agent so that the number of octets
    used remains less than or equal to the new value of
    this object.

    When the value of this object changes to a value
    greater than the current value, the number of
    associated captureBufferEntries may be allowed to
    grow."
    ::= { bufferControlEntry 9 }

bufferControlCapturedPackets OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of packets currently in this
    captureBuffer."
    ::= { bufferControlEntry 10 }

bufferControlTurnOnTime OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime when this capture buffer was
    first turned on."
    ::= { bufferControlEntry 11 }

bufferControlOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it."
    ::= { bufferControlEntry 12 }

bufferControlStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this buffer Control Entry."
    ::= { bufferControlEntry 13 }

captureBufferTable OBJECT-TYPE
    SYNTAX SEQUENCE OF CaptureBufferEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of packets captured off of a channel."
    ::= { capture 2 }

captureBufferEntry OBJECT-TYPE
    SYNTAX CaptureBufferEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A packet captured off of an attached network.  As an
    example, an instance of the captureBufferPacketData
    object might be named captureBufferPacketData.3.1783"
    INDEX { captureBufferControlIndex, captureBufferIndex }
    ::= { captureBufferTable 1 }

CaptureBufferEntry ::= SEQUENCE {
    captureBufferControlIndex   INTEGER (1..65535),
    captureBufferIndex          INTEGER (1..2147483647),
    captureBufferPacketID       INTEGER,
    captureBufferPacketData     OCTET STRING,
    captureBufferPacketLength   INTEGER,
    captureBufferPacketTime     INTEGER,
    captureBufferPacketStatus   INTEGER
}

captureBufferControlIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The index of the bufferControlEntry with which
    this packet is associated."
    ::= { captureBufferEntry 1 }

captureBufferIndex OBJECT-TYPE
    SYNTAX INTEGER (1..2147483647)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry
    in the captureBuffer table associated with a
    particular bufferControlEntry.  This index will
    start at 1 and increase by one for each new packet
    added with the same captureBufferControlIndex.

    Should this value reach 2147483647, the next packet
    added with the same captureBufferControlIndex shall
    cause this value to wrap around to 1."
    ::= { captureBufferEntry 2 }

captureBufferPacketID OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that describes the order of packets
    that are received on a particular interface.
    The packetID of a packet captured on an
    interface is defined to be greater than the
    packetID's of all packets captured previously on
    the same interface.  As the captureBufferPacketID
    object has a maximum positive value of 2^31 - 1,
    any captureBufferPacketID object shall have the
    value of the associated packet's packetID mod 2^31."
    ::= { captureBufferEntry 3 }

captureBufferPacketData OBJECT-TYPE
    SYNTAX OCTET STRING
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The data inside the packet, starting at the
    beginning of the packet plus any offset specified in
    the associated bufferControlDownloadOffset,
    including any link level headers.  The length of the
    data in this object is the minimum of the length of
    the captured packet minus the offset, the length of
    the associated bufferControlCaptureSliceSize minus
    the offset, and the associated
    bufferControlDownloadSliceSize.  If this minimum is
    less than zero, this object shall have a length of
    zero."
    ::= { captureBufferEntry 4 }

captureBufferPacketLength OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The actual length (off the wire) of the packet stored
    in this entry, including FCS octets."
    ::= { captureBufferEntry 5 }

captureBufferPacketTime OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The number of milliseconds that had passed since
    this capture buffer was first turned on when this
    packet was captured."
    ::= { captureBufferEntry 6 }

captureBufferPacketStatus OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "A value which indicates the error status of this
    packet.

    The value of this object is defined in the same way as
    filterPktStatus.  The value is a sum.  This sum
    initially takes the value zero.  Then, for each
    error, E, that has been discovered in this packet,
    2 raised to a value representing E is added to the
    sum.

    The errors defined for a packet captured off of an
    Ethernet interface are as follows:

        bit #    Error
        0    Packet is longer than 1518 octets
        1    Packet is shorter than 64 octets
        2    Packet experienced a CRC or Alignment
             error
        3    First packet in this capture buffer after
             it was detected that some packets were
             not processed correctly.
        4    Packet's order in buffer is only
             approximate (May only be set for packets
             sent from the probe)

    For example, an Ethernet fragment would have a
    value of 6 (2^1 + 2^2).

    As this MIB is expanded to new media types, this
    object will have other media-specific errors defined."
    ::= { captureBufferEntry 7 }

-- The Event Group

-- Implementation of the Event group is optional.
--
-- The Event group controls the generation and notification
-- of events from this device.  Each entry in the eventTable
-- describes the parameters of the event that can be
-- triggered. Each event entry is fired by an associated
-- condition located elsewhere in the MIB.  An event entry
-- may also be associated- with a function elsewhere in the
-- MIB that will be executed when the event is generated.  For
-- example, a channel may be turned on or off by the firing
-- of an event.
--
-- Each eventEntry may optionally specify that a log entry
-- be created on its behalf whenever the event occurs.
-- Each entry may also specify that notification should
-- occur by way of SNMP trap messages.  In this case, the
-- community for the trap message is given in the associated
-- eventCommunity object.  The enterprise and specific trap
-- fields of the trap are determined by the condition that
-- triggered the event.  Two traps are defined: risingAlarm
-- and fallingAlarm.  If the eventTable is triggered by a
-- condition specified elsewhere, the enterprise and
-- specific trap fields must be specified for traps
-- generated for that condition.

eventTable OBJECT-TYPE
    SYNTAX SEQUENCE OF EventEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of events to be generated."
    ::= { event 1 }

eventEntry OBJECT-TYPE
    SYNTAX EventEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of parameters that describe an event to be
    generated when certain conditions are met.  As an
    example, an instance of the eventLastTimeSent object
    might be named eventLastTimeSent.6"
    INDEX { eventIndex }
    ::= { eventTable 1 }

EventEntry ::= SEQUENCE {
    eventIndex          INTEGER (1..65535),
    eventDescription    DisplayString (SIZE (0..127)),
    eventType           INTEGER,
    eventCommunity      OCTET STRING (SIZE (0..127)),
    eventLastTimeSent   TimeTicks,
    eventOwner          OwnerString,
    eventStatus         EntryStatus
}

eventIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry in the
    event table.  Each such entry defines one event that
    is to be generated when the appropriate conditions
    occur."
    ::= { eventEntry 1 }

eventDescription OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..127))
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "A comment describing this event entry."
    ::= { eventEntry 2 }

eventType OBJECT-TYPE
    SYNTAX INTEGER {
        none(1),
        log(2),
        snmp-trap(3),    -- send an SNMP trap
        log-and-trap(4)
    }
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The type of notification that the probe will make
    about this event.  In the case of log, an entry is
    made in the log table for each event.  In the case of
    snmp-trap, an SNMP trap is sent to one or more
    management stations."
    ::= { eventEntry 3 }

eventCommunity OBJECT-TYPE
    SYNTAX OCTET STRING (SIZE (0..127))
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "If an SNMP trap is to be sent, it will be sent to
    the SNMP community specified by this octet string.
    In the future this table will be extended to include
    the party security mechanism.  This object shall be
    set to a string of length zero if it is intended that
    that mechanism be used to specify the destination of
    the trap."
    ::= { eventEntry 4 }

eventLastTimeSent OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime at the time this event
    entry last generated an event.  If this entry has
    not generated any events, this value will be
    zero."
    ::= { eventEntry 5 }

eventOwner OBJECT-TYPE
    SYNTAX OwnerString
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The entity that configured this entry and is
    therefore using the resources assigned to it.

    If this object contains a string starting with
    'monitor' and has associated entries in the log
    table, all connected management stations should
    retrieve those log entries, as they may have
    significance to all management stations connected to
    this device"
    ::= { eventEntry 6 }

eventStatus OBJECT-TYPE
    SYNTAX EntryStatus
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
    "The status of this event entry.

    If this object is not equal to valid(1), all
    associated log entries shall be deleted by the
    agent."
    ::= { eventEntry 7 }

--
logTable OBJECT-TYPE
    SYNTAX SEQUENCE OF LogEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A list of events that have been logged."
    ::= { event 2 }

logEntry OBJECT-TYPE
    SYNTAX LogEntry
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
    "A set of data describing an event that has been
    logged.  For example, an instance of the
    logDescription object might be named
    logDescription.6.47"
    INDEX { logEventIndex, logIndex }
    ::= { logTable 1 }

LogEntry ::= SEQUENCE {
    logEventIndex           INTEGER (1..65535),
    logIndex                INTEGER (1..2147483647),
    logTime                 TimeTicks,
    logDescription          DisplayString (SIZE (0..255))
}

logEventIndex OBJECT-TYPE
    SYNTAX INTEGER (1..65535)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The event entry that generated this log
    entry.  The log identified by a particular
    value of this index is associated with the same
    eventEntry as identified by the same value
    of eventIndex."
    ::= { logEntry 1 }

logIndex OBJECT-TYPE
    SYNTAX INTEGER (1..2147483647)
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An index that uniquely identifies an entry
    in the log table amongst those generated by the
    same eventEntries.  These indexes are
    assigned beginning with 1 and increase by one
    with each new log entry.  The association
    between values of logIndex and logEntries
    is fixed for the lifetime of each logEntry.
    The agent may choose to delete the oldest
    instances of logEntry as required because of
    lack of memory.  It is an implementation-specific
    matter as to when this deletion may occur."
    ::= { logEntry 2 }

logTime OBJECT-TYPE
    SYNTAX TimeTicks
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "The value of sysUpTime when this log entry was
    created."
    ::= { logEntry 3 }

logDescription OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
    "An implementation dependent description of the
    event that activated this log entry."
    ::= { logEntry 4 }

--  These definitions use the TRAP-TYPE macro as
--  defined in RFC 1215 [10]

--  Remote Network Monitoring Traps

risingAlarm TRAP-TYPE
    ENTERPRISE rmon
    VARIABLES { alarmIndex, alarmVariable, alarmSampleType,
        alarmValue, alarmRisingThreshold }
    DESCRIPTION
    "The SNMP trap that is generated when an alarm
    entry crosses its rising threshold and generates
    an event that is configured for sending SNMP
    traps."
    ::= 1

fallingAlarm TRAP-TYPE
    ENTERPRISE rmon
    VARIABLES { alarmIndex, alarmVariable, alarmSampleType,
        alarmValue, alarmFallingThreshold }
    DESCRIPTION
    "The SNMP trap that is generated when an alarm
    entry crosses its falling threshold and generates
    an event that is configured for sending SNMP
    traps."
    ::= 2

END


SNMP-COMMUNITY-MIB DEFINITIONS ::= BEGIN

IMPORTS
    IpAddress,
    MODULE-IDENTITY,
    OBJECT-TYPE,
    Integer32,
    snmpModules
    FROM SNMPv2-SMI
    RowStatus,
    StorageType
    FROM SNMPv2-TC
    SnmpAdminString,
    SnmpEngineID
    FROM SNMP-FRAMEWORK-MIB
    SnmpTagValue,
    snmpTargetAddrEntry
    FROM SNMP-TARGET-MIB
    MODULE-COMPLIANCE,
    OBJECT-GROUP
    FROM SNMPv2-CONF;

snmpCommunityMIB MODULE-IDENTITY
    LAST-UPDATED "199910050000Z"          -- 5 Oct 1999, midnight
    ORGANIZATION "SNMPv3 Working Group"
    CONTACT-INFO "WG-email:   snmpv3@lists.tislabs.com
          Subscribe:  majordomo@lists.tislabs.com
                  In msg body:  subscribe snmpv3

          Chair:      Russ Mundy
                  TIS Labs at Network Associates
          Postal:     3060 Washington Rd
                  Glenwood MD 21738
                  USA
          Email:      mundy@tislabs.com
          Phone:      +1-301-854-6889

          Co-editor:  Rob Frye
                  MCI WorldCom
          Postal:     2100 Reston Parkway, Suite 600
                  Reston, VA 20191
                  USA
          E-mail:     Rob.Frye@wcom.com
          Phone:      +1 703 715 7225

          Co-editor:  David B. Levi
                  Nortel Networks
          Postal:     3505 Kesterwood Drive
                  Knoxville, TN 37918
          E-mail:     dlevi@nortelnetworks.com
          Phone:      +1 423 686 0432

          Co-editor:  Shawn A. Routhier
                  Integrated Systems Inc.
          Postal:     333 North Ave 4th Floor
                  Wakefield, MA 01880
          E-mail:     sar@epilogue.com
          Phone:      +1 781 245 0804

          Co-editor:  Bert Wijnen
                  IBM T. J. Watson Research
          Postal:     Schagen 33
                  3461 GL Linschoten
                  Netherlands
          Email:      wijnen@vnet.ibm.com
          Phone:      +31-348-432-794
         "

    DESCRIPTION
        "This MIB module defines objects to help support coexistence
         between SNMPv1, SNMPv2c, and SNMPv3."
    REVISION "199905130000Z" -- 13 May 1999
    DESCRIPTION "The Initial Revision"
    REVISION "199910050000Z" -- 5 Oct 1999 (same as LAST-UPDATED)
    DESCRIPTION "This version published as RFC xxxx"
         -- RFC-editor assigns xxxx
    ::= { snmpModules 18 }

-- Administrative assignments ****************************************

snmpCommunityMIBObjects     OBJECT IDENTIFIER ::= { snmpCommunityMIB 1 }
snmpCommunityMIBConformance OBJECT IDENTIFIER ::= { snmpCommunityMIB 2 }

--
-- The snmpCommunityTable contains a database of community strings.
-- This table provides mappings between community strings, and the
-- parameters required for View-based Access Control.
--

snmpCommunityTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF SnmpCommunityEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
    "The table of community strings configured in the SNMP
     engine's Local Configuration Datastore (LCD)."
    ::= { snmpCommunityMIBObjects 1 }

snmpCommunityEntry OBJECT-TYPE
    SYNTAX       SnmpCommunityEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
    "Information about a particular community string."
    INDEX       { IMPLIED snmpCommunityIndex }
    ::= { snmpCommunityTable 1 }

SnmpCommunityEntry ::= SEQUENCE {
    snmpCommunityIndex               SnmpAdminString,
    snmpCommunityName                OCTET STRING,
    snmpCommunitySecurityName        SnmpAdminString,
    snmpCommunityContextEngineID     SnmpEngineID,
    snmpCommunityContextName         SnmpAdminString,
    snmpCommunityTransportTag        SnmpTagValue,
    snmpCommunityStorageType         StorageType,
    snmpCommunityStatus              RowStatus
}

snmpCommunityIndex OBJECT-TYPE
    SYNTAX      SnmpAdminString (SIZE(1..32))
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
    "The unique index value of a row in this table."
    ::= { snmpCommunityEntry 1 }

snmpCommunityName OBJECT-TYPE
    SYNTAX       OCTET STRING
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "The community string for which a row in this table
     represents a configuration."
    ::= { snmpCommunityEntry 2 }

snmpCommunitySecurityName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(1..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "A human readable string representing the corresponding
     value of snmpCommunityName in a Security Model
     independent format."
    ::= { snmpCommunityEntry 3 }

snmpCommunityContextEngineID OBJECT-TYPE
    SYNTAX       SnmpEngineID
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "The contextEngineID indicating the location of the
     context in which management information is accessed
     when using the community string specified by the
     corresponding instance of snmpCommunityName.

     The default value is the snmpEngineID of the entity in
     which this object is instantiated."
    ::= { snmpCommunityEntry 4 }

snmpCommunityContextName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "The context in which management information is accessed
     when using the community string specified by the corresponding
     instance of snmpCommunityName."
    DEFVAL      { ''H }   -- the empty string
    ::= { snmpCommunityEntry 5 }

snmpCommunityTransportTag OBJECT-TYPE
    SYNTAX       SnmpTagValue
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "This object specifies a set of transport endpoints
     from which a command responder application will accept
     management requests.  If a management request containing
     this community is received on a transport endpoint other
     than the transport endpoints identified by this object,
     the request is deemed unauthentic.

     The transports identified by this object are specified
     in the snmpTargetAddrTable.  Entries in that table
     whose snmpTargetAddrTagList contains this tag value
     are identified.

     If the value of this object has zero-length, transport
     endpoints are not checked when authenticating messages
     containing this community string."
    DEFVAL      { ''H }   -- the empty string
    ::= { snmpCommunityEntry 6 }

snmpCommunityStorageType OBJECT-TYPE
    SYNTAX       StorageType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "The storage type for this conceptual row in the
     snmpCommunityTable.  Conceptual rows having the value
     'permanent' need not allow write-access to any
     columnar object in the row."
    ::= { snmpCommunityEntry 7 }

snmpCommunityStatus OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION
    "The status of this conceptual row in the snmpCommunityTable.

     An entry in this table is not qualified for activation
     until instances of all corresponding columns have been
     initialized, either through default values, or through
     Set operations.  The snmpCommunityName and
     snmpCommunitySecurityName objects must be explicitly set.

     There is no restriction on setting columns in this table
     when the value of snmpCommunityStatus is active(1)."
    ::= { snmpCommunityEntry 8 }

--
-- The snmpTargetAddrExtTable
--

snmpTargetAddrExtTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF SnmpTargetAddrExtEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
    "The table of mask and mms values associated with the
     snmpTargetAddrTable.

     The snmpTargetAddrExtTable augments the
     snmpTargetAddrTable with a transport address mask value
     and a maximum message size value.  The transport address
     mask allows entries in the snmpTargetAddrTable to define
     a set of addresses instead of just a single address.
     The maximum message size value allows the maximum
     message size of another SNMP entity to be configured for
     use in SNMPv1 (and SNMPv2c) transactions, where the
     message format does not specify a maximum message size."
    ::= { snmpCommunityMIBObjects 2 }

snmpTargetAddrExtEntry OBJECT-TYPE
    SYNTAX       SnmpTargetAddrExtEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION
    "Information about a particular mask and mms value."
    AUGMENTS       { snmpTargetAddrEntry }
    ::= { snmpTargetAddrExtTable 1 }

SnmpTargetAddrExtEntry ::= SEQUENCE {
    snmpTargetAddrTMask              OCTET STRING,
    snmpTargetAddrMMS                Integer32
}

snmpTargetAddrTMask OBJECT-TYPE
    SYNTAX      OCTET STRING (SIZE (0..255))
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
    "The mask value associated with an entry in the
     snmpTargetAddrTable.  The value of this object must
     have the same length as the corresponding instance of
     snmpTargetAddrTAddress, or must have length 0.  An
     attempt to set it to any other value will result in
     an inconsistentValue error.

     The value of this object allows an entry in the
     snmpTargetAddrTable to specify multiple addresses.

     The mask value is used to select which bits of
     a transport address must match bits of the corresponding
     instance of snmpTargetAddrTAddress, in order for the
     transport address to match a particular entry in the
     snmpTargetAddrTable.  Bits which are 1 in the mask
     value indicate bits in the transport address which
     must match bits in the snmpTargetAddrTAddress value.
     Bits which are 0 in the mask indicate bits in the
     transport address which need not match.  If the
     length of the mask is 0, the mask should be treated
     as if all its bits were 1 and its length were equal
     to the length of the corresponding value of
     snmpTargetAddrTable.

     This object may not be modified while the value of the
     corresponding instance of snmpTargetAddrRowStatus is
     active(1).  An attempt to set this object in this case
     will result in an inconsistentValue error."
    DEFVAL { ''H }
    ::= { snmpTargetAddrExtEntry 1 }

snmpTargetAddrMMS OBJECT-TYPE
    SYNTAX      Integer32 (0|484..2147483647)
    MAX-ACCESS  read-create
    STATUS      current
    DESCRIPTION
    "The maximum message size value associated with an entry
     in the snmpTargetAddrTable."
    DEFVAL { 484 }
    ::= { snmpTargetAddrExtEntry 2 }

--
-- The snmpTrapAddress and snmpTrapCommunity objects are included
-- in notifications that are forwarded by a proxy, which were
-- originally received as SNMPv1 Trap messages.
--

snmpTrapAddress OBJECT-TYPE
    SYNTAX      IpAddress
    MAX-ACCESS  accessible-for-notify
    STATUS      current
    DESCRIPTION
    "The value of the agent-addr field of a Trap PDU which
     is forwarded by a proxy forwarder application using
     an SNMP version other than SNMPv1.  The value of this
     object SHOULD contain the value of the agent-addr field
     from the original Trap PDU as generated by an SNMPv1
     agent."
    ::= { snmpCommunityMIBObjects 3 }

snmpTrapCommunity OBJECT-TYPE
    SYNTAX      OCTET STRING
    MAX-ACCESS  accessible-for-notify
    STATUS      current
    DESCRIPTION
    "The value of the community string field of an SNMPv1
     message containing a Trap PDU which is forwarded by a
     a proxy forwarder application using an SNMP version
     other than SNMPv1.  The value of this object SHOULD
     contain the value of the community string field from
     the original SNMPv1 message containing a Trap PDU as
     generated by an SNMPv1 agent."
    ::= { snmpCommunityMIBObjects 4 }

-- Conformance Information *******************************************

snmpCommunityMIBCompliances OBJECT IDENTIFIER
                ::= { snmpCommunityMIBConformance 1 }
snmpCommunityMIBGroups      OBJECT IDENTIFIER
                ::= { snmpCommunityMIBConformance 2 }

-- Compliance statements

snmpCommunityMIBCompliance MODULE-COMPLIANCE
    STATUS       current
    DESCRIPTION
    "The compliance statement for SNMP engines which
     implement the SNMP-COMMUNITY-MIB."

    MODULE       -- this module
    MANDATORY-GROUPS { snmpCommunityGroup }

    OBJECT           snmpCommunityName
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunitySecurityName
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunityContextEngineID
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunityContextName
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunityTransportTag
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunityStorageType
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    OBJECT           snmpCommunityStatus
    MIN-ACCESS       read-only
    DESCRIPTION     "Write access is not required."

    ::= { snmpCommunityMIBCompliances 1 }

snmpProxyTrapForwardCompliance MODULE-COMPLIANCE
    STATUS       current
    DESCRIPTION
    "The compliance statement for SNMP engines which
     contain a proxy forwarding application which is
     capable of forwarding SNMPv1 traps using SNMPv2c
     or SNMPv3."
    MODULE       -- this module
    MANDATORY-GROUPS { snmpProxyTrapForwardGroup }
    ::= { snmpCommunityMIBCompliances 2 }

snmpCommunityGroup OBJECT-GROUP
    OBJECTS {
    snmpCommunityName,
    snmpCommunitySecurityName,
    snmpCommunityContextEngineID,
    snmpCommunityContextName,
    snmpCommunityTransportTag,
    snmpCommunityStorageType,
    snmpCommunityStatus,
    snmpTargetAddrTMask,
    snmpTargetAddrMMS
    }
    STATUS       current
    DESCRIPTION
    "A collection of objects providing for configuration
     of community strings for SNMPv1 (and SNMPv2c) usage."
    ::= { snmpCommunityMIBGroups 1 }

snmpProxyTrapForwardGroup OBJECT-GROUP
    OBJECTS {
    snmpTrapAddress,
    snmpTrapCommunity
    }
    STATUS       current
    DESCRIPTION
    "Objects which are used by proxy forwarding applications
     when translating traps between SNMP versions.  These are
     used to preserve SNMPv1-specific information when
     translating to SNMPv2c or SNMPv3."
    ::= { snmpCommunityMIBGroups 3 }

END


SNMP-FRAMEWORK-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-IDENTITY, OBJECT-TYPE,
   OBJECT-IDENTITY,
   snmpModules                           FROM SNMPv2-SMI
   TEXTUAL-CONVENTION                    FROM SNMPv2-TC
   MODULE-COMPLIANCE, OBJECT-GROUP       FROM SNMPv2-CONF;

snmpFrameworkMIB MODULE-IDENTITY
   LAST-UPDATED "9901190000Z"            -- 19 January 1999
   ORGANIZATION "SNMPv3 Working Group"
   CONTACT-INFO "WG-EMail:   snmpv3@tis.com
         Subscribe:  majordomo@tis.com
                 In message body:  subscribe snmpv3

         Chair:      Russ Mundy
                 TIS Labs at Network Associates
         postal:     3060 Washington Rd
                 Glenwood MD 21738
                 USA
         EMail:      mundy@tis.com
         phone:      +1 301-854-6889

         Co-editor   Dave Harrington
                 Cabletron Systems, Inc.
         postal:     Post Office Box 5005
                 Mail Stop: Durham
                 35 Industrial Way
                 Rochester, NH 03867-5005
                 USA
         EMail:      dbh@ctron.com
         phone:      +1 603-337-7357

         Co-editor   Randy Presuhn
                 BMC Software, Inc.
         postal:     965 Stewart Drive
                 Sunnyvale, CA 94086
                 USA
         EMail:      randy_presuhn@bmc.com
         phone:      +1 408-616-3100

         Co-editor:  Bert Wijnen
                 IBM T.J. Watson Research
         postal:     Schagen 33
                 3461 GL Linschoten
                 Netherlands
         EMail:      wijnen@vnet.ibm.com
         phone:      +31 348-432-794
        "
   DESCRIPTION  "The SNMP Management Architecture MIB"
-- Revision History

   REVISION     "9901190000Z"            -- 19 January 1999
   DESCRIPTION  "Updated editors' addresses, fixed typos.
         Published as RFC2571.
        "
   REVISION     "9711200000Z"            -- 20 November 1997
   DESCRIPTION  "The initial version, published in RFC 2271.
        "
   ::= { snmpModules 10 }

-- Textual Conventions used in the SNMP Management Architecture ***

SnmpEngineID ::= TEXTUAL-CONVENTION
   STATUS       current
   DESCRIPTION "An SNMP engine's administratively-unique identifier.
        Objects of this type are for identification, not for
        addressing, even though it is possible that an
        address may have been used in the generation of
        a specific value.

        The value for this object may not be all zeros or
        all 'ff'H or the empty (zero length) string.

        The initial value for this object may be configured
        via an operator console entry or via an algorithmic
        function.  In the latter case, the following
        example algorithm is recommended.

        In cases where there are multiple engines on the
        same system, the use of this algorithm is NOT
        appropriate, as it would result in all of those
        engines ending up with the same ID value.

        1) The very first bit is used to indicate how the
           rest of the data is composed.

           0 - as defined by enterprise using former methods
               that existed before SNMPv3. See item 2 below.

           1 - as defined by this architecture, see item 3
               below.

           Note that this allows existing uses of the
           engineID (also known as AgentID [RFC1910]) to
           co-exist with any new uses.

        2) The snmpEngineID has a length of 12 octets.

           The first four octets are set to the binary
           equivalent of the agent's SNMP management
           private enterprise number as assigned by the
           Internet Assigned Numbers Authority (IANA).
           For example, if Acme Networks has been assigned
           { enterprises 696 }, the first four octets would
           be assigned '000002b8'H.

           The remaining eight octets are determined via
           one or more enterprise-specific methods. Such
           methods must be designed so as to maximize the
           possibility that the value of this object will
           be unique in the agent's administrative domain.
           For example, it may be the IP address of the SNMP
           entity, or the MAC address of one of the
           interfaces, with each address suitably padded
           with random octets.  If multiple methods are
           defined, then it is recommended that the first
           octet indicate the method being used and the
           remaining octets be a function of the method.

        3) The length of the octet strings varies.

           The first four octets are set to the binary
           equivalent of the agent's SNMP management
           private enterprise number as assigned by the
           Internet Assigned Numbers Authority (IANA).
           For example, if Acme Networks has been assigned
           { enterprises 696 }, the first four octets would
           be assigned '000002b8'H.

           The very first bit is set to 1. For example, the
           above value for Acme Networks now changes to be
           '800002b8'H.

           The fifth octet indicates how the rest (6th and
           following octets) are formatted. The values for
           the fifth octet are:

             0     - reserved, unused.

             1     - IPv4 address (4 octets)
                 lowest non-special IP address

             2     - IPv6 address (16 octets)
                 lowest non-special IP address

             3     - MAC address (6 octets)
                 lowest IEEE MAC address, canonical
                 order

             4     - Text, administratively assigned
                 Maximum remaining length 27

             5     - Octets, administratively assigned
                 Maximum remaining length 27

             6-127 - reserved, unused

           127-255 - as defined by the enterprise
                 Maximum remaining length 27
           "
   SYNTAX       OCTET STRING (SIZE(5..32))

SnmpSecurityModel ::= TEXTUAL-CONVENTION
   STATUS       current
   DESCRIPTION "An identifier that uniquely identifies a
        securityModel of the Security Subsystem within the
        SNMP Management Architecture.

        The values for securityModel are allocated as
        follows:

        - The zero value is reserved.
        - Values between 1 and 255, inclusive, are reserved
          for standards-track Security Models and are
          managed by the Internet Assigned Numbers Authority
          (IANA).
        - Values greater than 255 are allocated to
          enterprise-specific Security Models.  An
          enterprise-specific securityModel value is defined
          to be:

          enterpriseID * 256 + security model within
          enterprise

          For example, the fourth Security Model defined by
          the enterprise whose enterpriseID is 1 would be
          260.

        This scheme for allocation of securityModel
        values allows for a maximum of 255 standards-
        based Security Models, and for a maximum of
        255 Security Models per enterprise.

        It is believed that the assignment of new
        securityModel values will be rare in practice
        because the larger the number of simultaneously
        utilized Security Models, the larger the
        chance that interoperability will suffer.
        Consequently, it is believed that such a range
        will be sufficient.  In the unlikely event that
        the standards committee finds this number to be
        insufficient over time, an enterprise number
        can be allocated to obtain an additional 255
        possible values.

        Note that the most significant bit must be zero;
        hence, there are 23 bits allocated for various
        organizations to design and define non-standard
        securityModels.  This limits the ability to
        define new proprietary implementations of Security
        Models to the first 8,388,608 enterprises.

        It is worthwhile to note that, in its encoded
        form, the securityModel value will normally
        require only a single byte since, in practice,
        the leftmost bits will be zero for most messages
        and sign extension is suppressed by the encoding
        rules.

        As of this writing, there are several values
        of securityModel defined for use with SNMP or
        reserved for use with supporting MIB objects.
        They are as follows:

            0  reserved for 'any'
            1  reserved for SNMPv1
            2  reserved for SNMPv2c
            3  User-Based Security Model (USM)
           "
   SYNTAX       INTEGER(0 .. 2147483647)

SnmpMessageProcessingModel ::= TEXTUAL-CONVENTION
   STATUS       current
   DESCRIPTION "An identifier that uniquely identifies a Message
        Processing Model of the Message Processing
        Subsystem within a SNMP Management Architecture.

        The values for messageProcessingModel are
        allocated as follows:

        - Values between 0 and 255, inclusive, are
          reserved for standards-track Message Processing
          Models and are managed by the Internet Assigned
          Numbers Authority (IANA).

        - Values greater than 255 are allocated to
          enterprise-specific Message Processing Models.
          An enterprise messageProcessingModel value is
          defined to be:

          enterpriseID * 256 +
               messageProcessingModel within enterprise

          For example, the fourth Message Processing Model
          defined by the enterprise whose enterpriseID
          is 1 would be 260.

        This scheme for allocating messageProcessingModel
        values allows for a maximum of 255 standards-
        based Message Processing Models, and for a
        maximum of 255 Message Processing Models per
        enterprise.

        It is believed that the assignment of new
        messageProcessingModel values will be rare
        in practice because the larger the number of
        simultaneously utilized Message Processing Models,
        the larger the chance that interoperability
        will suffer. It is believed that such a range
        will be sufficient.  In the unlikely event that
        the standards committee finds this number to be
        insufficient over time, an enterprise number
        can be allocated to obtain an additional 256
        possible values.

        Note that the most significant bit must be zero;
        hence, there are 23 bits allocated for various
        organizations to design and define non-standard
        messageProcessingModels.  This limits the ability
        to define new proprietary implementations of
        Message Processing Models to the first 8,388,608
        enterprises.

        It is worthwhile to note that, in its encoded
        form, the messageProcessingModel value will
        normally require only a single byte since, in
        practice, the leftmost bits will be zero for
        most messages and sign extension is suppressed
        by the encoding rules.

        As of this writing, there are several values of
        messageProcessingModel defined for use with SNMP.
        They are as follows:

            0  reserved for SNMPv1
            1  reserved for SNMPv2c
            2  reserved for SNMPv2u and SNMPv2*
            3  reserved for SNMPv3
           "
   SYNTAX       INTEGER(0 .. 2147483647)

SnmpSecurityLevel ::= TEXTUAL-CONVENTION
   STATUS       current
   DESCRIPTION "A Level of Security at which SNMP messages can be
        sent or with which operations are being processed;
        in particular, one of:

          noAuthNoPriv - without authentication and
                 without privacy,
          authNoPriv   - with authentication but
                 without privacy,
          authPriv     - with authentication and
                 with privacy.

        These three values are ordered such that
        noAuthNoPriv is less than authNoPriv and
        authNoPriv is less than authPriv.
           "
   SYNTAX       INTEGER { noAuthNoPriv(1),
              authNoPriv(2),
              authPriv(3)
            }

SnmpAdminString ::= TEXTUAL-CONVENTION
   DISPLAY-HINT "255a"
   STATUS       current
   DESCRIPTION "An octet string containing administrative
        information, preferably in human-readable form.

        To facilitate internationalization, this
        information is represented using the ISO/IEC
        IS 10646-1 character set, encoded as an octet
        string using the UTF-8 transformation format
        described in [RFC2279].

        Since additional code points are added by
        amendments to the 10646 standard from time
        to time, implementations must be prepared to
        encounter any code point from 0x00000000 to
        0x7fffffff.  Byte sequences that do not
        correspond to the valid UTF-8 encoding of a
        code point or are outside this range are
        prohibited.

        The use of control codes should be avoided.

        When it is necessary to represent a newline,
        the control code sequence CR LF should be used.

        The use of leading or trailing white space should
        be avoided.

        For code points not directly supported by user
        interface hardware or software, an alternative
        means of entry and display, such as hexadecimal,
        may be provided.

        For information encoded in 7-bit US-ASCII,
        the UTF-8 encoding is identical to the
        US-ASCII encoding.

        UTF-8 may require multiple bytes to represent a
        single character / code point; thus the length
        of this object in octets may be different from
        the number of characters encoded.  Similarly,
        size constraints refer to the number of encoded
        octets, not the number of characters represented
        by an encoding.

        Note that when this TC is used for an object that
        is used or envisioned to be used as an index, then
        a SIZE restriction MUST be specified so that the
        number of sub-identifiers for any object instance
        does not exceed the limit of 128, as defined by
        [RFC1905].

        Note that the size of an SnmpAdminString object is
        measured in octets, not characters.
           "
   SYNTAX       OCTET STRING (SIZE (0..255))

-- Administrative assignments ***************************************

snmpFrameworkAdmin
   OBJECT IDENTIFIER ::= { snmpFrameworkMIB 1 }
snmpFrameworkMIBObjects
   OBJECT IDENTIFIER ::= { snmpFrameworkMIB 2 }
snmpFrameworkMIBConformance
   OBJECT IDENTIFIER ::= { snmpFrameworkMIB 3 }

-- the snmpEngine Group ********************************************

snmpEngine OBJECT IDENTIFIER ::= { snmpFrameworkMIBObjects 1 }

snmpEngineID     OBJECT-TYPE
   SYNTAX       SnmpEngineID
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "An SNMP engine's administratively-unique identifier.
           "
   ::= { snmpEngine 1 }

snmpEngineBoots  OBJECT-TYPE
   SYNTAX       INTEGER (1..2147483647)
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The number of times that the SNMP engine has
        (re-)initialized itself since snmpEngineID
        was last configured.
           "
   ::= { snmpEngine 2 }

snmpEngineTime   OBJECT-TYPE
   SYNTAX       INTEGER (0..2147483647)
   UNITS        "seconds"
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The number of seconds since the value of
        the snmpEngineBoots object last changed.
        When incrementing this object's value would
        cause it to exceed its maximum,
        snmpEngineBoots is incremented as if a
        re-initialization had occurred, and this
        object's value consequently reverts to zero.
           "
   ::= { snmpEngine 3 }

snmpEngineMaxMessageSize OBJECT-TYPE
   SYNTAX       INTEGER (484..2147483647)
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The maximum length in octets of an SNMP message
        which this SNMP engine can send or receive and
        process, determined as the minimum of the maximum
        message size values supported among all of the
        transports available to and supported by the engine.
           "
   ::= { snmpEngine 4 }

-- Registration Points for Authentication and Privacy Protocols **

snmpAuthProtocols OBJECT-IDENTITY
   STATUS        current
   DESCRIPTION  "Registration point for standards-track
         authentication protocols used in SNMP Management
         Frameworks.
        "
   ::= { snmpFrameworkAdmin 1 }

snmpPrivProtocols OBJECT-IDENTITY
   STATUS        current
   DESCRIPTION  "Registration point for standards-track privacy
         protocols used in SNMP Management Frameworks.
        "
   ::= { snmpFrameworkAdmin 2 }

-- Conformance information ******************************************

snmpFrameworkMIBCompliances
          OBJECT IDENTIFIER ::= {snmpFrameworkMIBConformance 1}
snmpFrameworkMIBGroups
          OBJECT IDENTIFIER ::= {snmpFrameworkMIBConformance 2}

-- compliance statements

snmpFrameworkMIBCompliance MODULE-COMPLIANCE
   STATUS       current
   DESCRIPTION "The compliance statement for SNMP engines which
        implement the SNMP Management Framework MIB.
           "
   MODULE    -- this module
       MANDATORY-GROUPS { snmpEngineGroup }

   ::= { snmpFrameworkMIBCompliances 1 }

-- units of conformance

snmpEngineGroup OBJECT-GROUP
   OBJECTS {
         snmpEngineID,
         snmpEngineBoots,
         snmpEngineTime,
         snmpEngineMaxMessageSize
       }
   STATUS       current
   DESCRIPTION "A collection of objects for identifying and
        determining the configuration and current timeliness
        values of an SNMP engine.
           "
   ::= { snmpFrameworkMIBGroups 1 }

END


SNMP-MPD-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-COMPLIANCE, OBJECT-GROUP         FROM SNMPv2-CONF
   MODULE-IDENTITY, OBJECT-TYPE,
   snmpModules, Counter32                  FROM SNMPv2-SMI;

snmpMPDMIB MODULE-IDENTITY
   LAST-UPDATED "9905041636Z"              -- 4 April 1999
   ORGANIZATION "SNMPv3 Working Group"
   CONTACT-INFO "WG-EMail:   snmpv3@lists.tislabs.com
         Subscribe:  majordomo@lists.tislabs.com
                 In message body:  subscribe snmpv3

         Chair:      Russ Mundy
                 TIS Labs at Network Associates
         postal:     3060 Washington Road
                 Glenwood, MD 21738
                 USA
         EMail:      mundy@tislabs.com
         phone:      +1 301-854-6889

         Co-editor:  Jeffrey Case
                 SNMP Research, Inc.
         postal:     3001 Kimberlin Heights Road
                 Knoxville, TN 37920-9716
                 USA
         EMail:      case@snmp.com
         phone:      +1 423-573-1434

         Co-editor   Dave Harrington
                 Cabletron Systems, Inc.
         postal:     Post Office Box 5005
                 MailStop: Durham
                 35 Industrial Way
                 Rochester, NH 03867-5005
                 USA
         EMail:      dbh@ctron.com
         phone:      +1 603-337-7357

         Co-editor:  Randy Presuhn
                 BMC Software, Inc.
         postal:     965 Stewart Drive
                 Sunnyvale, CA 94086
                 USA
         EMail:      randy_presuhn@bmc.com
         phone:      +1 408-616-3100

         Co-editor:  Bert Wijnen
                 IBM T. J. Watson Research
         postal:     Schagen 33
                 3461 GL Linschoten
                 Netherlands
         EMail:      wijnen@vnet.ibm.com
         phone:      +31 348-432-794

        "
   DESCRIPTION  "The MIB for Message Processing and Dispatching"
   REVISION     "9905041636Z"              -- 4 April 1999
   DESCRIPTION  "Updated addresses, published as RFC 2572."
   REVISION     "9709300000Z"              -- 30 September 1997
   DESCRIPTION  "Original version, published as RFC 2272."
   ::= { snmpModules 11 }

-- Administrative assignments ***************************************

snmpMPDAdmin           OBJECT IDENTIFIER ::= { snmpMPDMIB 1 }
snmpMPDMIBObjects      OBJECT IDENTIFIER ::= { snmpMPDMIB 2 }
snmpMPDMIBConformance  OBJECT IDENTIFIER ::= { snmpMPDMIB 3 }

-- Statistics for SNMP Messages *************************************

snmpMPDStats           OBJECT IDENTIFIER ::= { snmpMPDMIBObjects 1 }

snmpUnknownSecurityModels OBJECT-TYPE
   SYNTAX       Counter32
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The total number of packets received by the SNMP
        engine which were dropped because they referenced a
        securityModel that was not known to or supported by
        the SNMP engine.
           "
   ::= { snmpMPDStats 1 }

snmpInvalidMsgs OBJECT-TYPE
   SYNTAX       Counter32
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The total number of packets received by the SNMP
        engine which were dropped because there were invalid
        or inconsistent components in the SNMP message.
           "
   ::= { snmpMPDStats 2 }

snmpUnknownPDUHandlers OBJECT-TYPE
   SYNTAX       Counter32
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION "The total number of packets received by the SNMP
        engine which were dropped because the PDU contained
        in the packet could not be passed to an application
        responsible for handling the pduType, e.g. no SNMP
        application had registered for the proper
        combination of the contextEngineID and the pduType.
           "
   ::= { snmpMPDStats 3 }

-- Conformance information ******************************************

snmpMPDMIBCompliances OBJECT IDENTIFIER ::= {snmpMPDMIBConformance 1}
snmpMPDMIBGroups      OBJECT IDENTIFIER ::= {snmpMPDMIBConformance 2}

-- Compliance statements

snmpMPDCompliance MODULE-COMPLIANCE
   STATUS       current
   DESCRIPTION "The compliance statement for SNMP entities which
        implement the SNMP-MPD-MIB.
           "

   MODULE    -- this module
       MANDATORY-GROUPS { snmpMPDGroup }

   ::= { snmpMPDMIBCompliances 1 }

snmpMPDGroup OBJECT-GROUP
   OBJECTS {
         snmpUnknownSecurityModels,
         snmpInvalidMsgs,
         snmpUnknownPDUHandlers
       }
   STATUS       current
   DESCRIPTION "A collection of objects providing for remote
        monitoring of the SNMP Message Processing and
        Dispatching process.
           "
   ::= { snmpMPDMIBGroups 1 }

END


SNMP-NOTIFICATION-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-IDENTITY,
   OBJECT-TYPE,
   snmpModules
       FROM SNMPv2-SMI

   RowStatus,
   StorageType
       FROM SNMPv2-TC

   SnmpAdminString
       FROM SNMP-FRAMEWORK-MIB

   SnmpTagValue,
   snmpTargetParamsName
       FROM SNMP-TARGET-MIB

   MODULE-COMPLIANCE,
   OBJECT-GROUP
       FROM SNMPv2-CONF;

snmpNotificationMIB MODULE-IDENTITY
   LAST-UPDATED "9808040000Z"
   ORGANIZATION "IETF SNMPv3 Working Group"
   CONTACT-INFO
       "WG-email:   snmpv3@lists.tislabs.com
    Subscribe:  majordomo@lists.tislabs.com
            In message body:  subscribe snmpv3

    Chair:      Russ Mundy
            Trusted Information Systems
    Postal:     3060 Washington Rd
            Glenwood MD 21738
            USA
    EMail:      mundy@tislabs.com
    Phone:      +1-301-854-6889

    Co-editor:  David B. Levi
            SNMP Research, Inc.
    Postal:     3001 Kimberlin Heights Road
            Knoxville, TN 37920-9716
    EMail:      levi@snmp.com
    Phone:      +1 423 573 1434

    Co-editor:  Paul Meyer
            Secure Computing Corporation
    Postal:     2675 Long Lake Road
            Roseville, MN 55113
    EMail:      paul_meyer@securecomputing.com
    Phone:      +1 651 628 1592

    Co-editor:  Bob Stewart
            Cisco Systems, Inc.
    Postal:     170 West Tasman Drive
            San Jose, CA 95134-1706
    EMail:      bstewart@cisco.com
    Phone:      +1 603 654 2686"
   DESCRIPTION
       "This MIB module defines MIB objects which provide
    mechanisms to remotely configure the parameters
    used by an SNMP entity for the generation of
    notifications."
   REVISION    "9808040000Z"
   DESCRIPTION "Clarifications, published as
        RFC2573"
   REVISION    "9707140000Z"
   DESCRIPTION "The initial revision, published as RFC2273."
   ::= { snmpModules 13 }

snmpNotifyObjects       OBJECT IDENTIFIER ::=
                     { snmpNotificationMIB 1 }
snmpNotifyConformance   OBJECT IDENTIFIER ::=
                     { snmpNotificationMIB 3 }

--
--
-- The snmpNotifyObjects group
--
--

snmpNotifyTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpNotifyEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "This table is used to select management targets which should
    receive notifications, as well as the type of notification
    which should be sent to each selected management target."
   ::= { snmpNotifyObjects 1 }

snmpNotifyEntry OBJECT-TYPE
   SYNTAX      SnmpNotifyEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "An entry in this table selects a set of management targets
    which should receive notifications, as well as the type of
    notification which should be sent to each selected
    management target.

    Entries in the snmpNotifyTable are created and
    deleted using the snmpNotifyRowStatus object."
   INDEX { IMPLIED snmpNotifyName }
   ::= { snmpNotifyTable 1 }

SnmpNotifyEntry ::= SEQUENCE {
   snmpNotifyName         SnmpAdminString,
   snmpNotifyTag          SnmpTagValue,
   snmpNotifyType         INTEGER,
   snmpNotifyStorageType  StorageType,
   snmpNotifyRowStatus    RowStatus
}

snmpNotifyName OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The locally arbitrary, but unique identifier associated
    with this snmpNotifyEntry."
   ::= { snmpNotifyEntry 1 }

snmpNotifyTag OBJECT-TYPE
   SYNTAX      SnmpTagValue
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object contains a single tag value which is used
    to select entries in the snmpTargetAddrTable.  Any entry
    in the snmpTargetAddrTable which contains a tag value
    which is equal to the value of an instance of this
    object is selected.  If this object contains a value
    of zero length, no entries are selected."
   DEFVAL { "" }
   ::= { snmpNotifyEntry 2 }

snmpNotifyType OBJECT-TYPE
   SYNTAX      INTEGER {
           trap(1),
           inform(2)
           }
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object determines the type of notification to
    be generated for entries in the snmpTargetAddrTable
    selected by the corresponding instance of
    snmpNotifyTag.  This value is only used when
    generating notifications, and is ignored when
    using the snmpTargetAddrTable for other purposes.

    If the value of this object is trap(1), then any
    messages generated for selected rows will contain
    Unconfirmed-Class PDUs.

    If the value of this object is inform(2), then any
    messages generated for selected rows will contain
    Confirmed-Class PDUs.

    Note that if an SNMP entity only supports
    generation of Unconfirmed-Class PDUs (and not
    Confirmed-Class PDUs), then this object may be
    read-only."
   DEFVAL { trap }
   ::= { snmpNotifyEntry 3 }
snmpNotifyStorageType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type for this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpNotifyEntry 4 }

snmpNotifyRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5)."
   ::= { snmpNotifyEntry 5 }

snmpNotifyFilterProfileTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpNotifyFilterProfileEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "This table is used to associate a notification filter
    profile with a particular set of target parameters."
   ::= { snmpNotifyObjects 2 }

snmpNotifyFilterProfileEntry OBJECT-TYPE
   SYNTAX      SnmpNotifyFilterProfileEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "An entry in this table indicates the name of the filter
    profile to be used when generating notifications using
    the corresponding entry in the snmpTargetParamsTable.

    Entries in the snmpNotifyFilterProfileTable are created
    and deleted using the snmpNotifyFilterProfileRowStatus
    object."
   INDEX { IMPLIED snmpTargetParamsName }
   ::= { snmpNotifyFilterProfileTable 1 }

SnmpNotifyFilterProfileEntry ::= SEQUENCE {
   snmpNotifyFilterProfileName         SnmpAdminString,
   snmpNotifyFilterProfileStorType     StorageType,
   snmpNotifyFilterProfileRowStatus    RowStatus
}

snmpNotifyFilterProfileName OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The name of the filter profile to be used when generating
    notifications using the corresponding entry in the
    snmpTargetAddrTable."
   ::= { snmpNotifyFilterProfileEntry 1 }

snmpNotifyFilterProfileStorType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type of this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpNotifyFilterProfileEntry 2 }

snmpNotifyFilterProfileRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5).

    Until instances of all corresponding columns are
    appropriately configured, the value of the
    corresponding instance of the
    snmpNotifyFilterProfileRowStatus column is 'notReady'.

    In particular, a newly created row cannot be made
    active until the corresponding instance of
    snmpNotifyFilterProfileName has been set."
   ::= { snmpNotifyFilterProfileEntry 3 }

snmpNotifyFilterTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpNotifyFilterEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The table of filter profiles.  Filter profiles are used
    to determine whether particular management targets should
    receive particular notifications.

    When a notification is generated, it must be compared
    with the filters associated with each management target
    which is configured to receive notifications, in order to
    determine whether it may be sent to each such management
    target.

    A more complete discussion of notification filtering
    can be found in section 6. of [RFC2573]."
   ::= { snmpNotifyObjects 3 }

snmpNotifyFilterEntry OBJECT-TYPE
   SYNTAX      SnmpNotifyFilterEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "An element of a filter profile.

    Entries in the snmpNotifyFilterTable are created and
    deleted using the snmpNotifyFilterRowStatus object."
   INDEX {         snmpNotifyFilterProfileName,
       IMPLIED snmpNotifyFilterSubtree }
   ::= { snmpNotifyFilterTable 1 }

SnmpNotifyFilterEntry ::= SEQUENCE {
   snmpNotifyFilterSubtree           OBJECT IDENTIFIER,
   snmpNotifyFilterMask              OCTET STRING,
   snmpNotifyFilterType              INTEGER,
   snmpNotifyFilterStorageType       StorageType,
   snmpNotifyFilterRowStatus         RowStatus
}

snmpNotifyFilterSubtree OBJECT-TYPE
   SYNTAX      OBJECT IDENTIFIER
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The MIB subtree which, when combined with the corresponding
    instance of snmpNotifyFilterMask, defines a family of
    subtrees which are included in or excluded from the
    filter profile."
   ::= { snmpNotifyFilterEntry 1 }

snmpNotifyFilterMask OBJECT-TYPE
   SYNTAX      OCTET STRING (SIZE(0..16))
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The bit mask which, in combination with the corresponding
    instance of snmpNotifyFilterSubtree, defines a family of
    subtrees which are included in or excluded from the
    filter profile.

    Each bit of this bit mask corresponds to a
    sub-identifier of snmpNotifyFilterSubtree, with the
    most significant bit of the i-th octet of this octet
    string value (extended if necessary, see below)
    corresponding to the (8*i - 7)-th sub-identifier, and
    the least significant bit of the i-th octet of this
    octet string corresponding to the (8*i)-th
    sub-identifier, where i is in the range 1 through 16.

    Each bit of this bit mask specifies whether or not
    the corresponding sub-identifiers must match when
    determining if an OBJECT IDENTIFIER matches this
    family of filter subtrees; a '1' indicates that an
    exact match must occur; a '0' indicates 'wild card',
    i.e., any sub-identifier value matches.

    Thus, the OBJECT IDENTIFIER X of an object instance
    is contained in a family of filter subtrees if, for
    each sub-identifier of the value of
    snmpNotifyFilterSubtree, either:

      the i-th bit of snmpNotifyFilterMask is 0, or

      the i-th sub-identifier of X is equal to the i-th
      sub-identifier of the value of
      snmpNotifyFilterSubtree.

    If the value of this bit mask is M bits long and
    there are more than M sub-identifiers in the
    corresponding instance of snmpNotifyFilterSubtree,
    then the bit mask is extended with 1's to be the
    required length.

    Note that when the value of this object is the
    zero-length string, this extension rule results in
    a mask of all-1's being used (i.e., no 'wild card'),
    and the family of filter subtrees is the one
    subtree uniquely identified by the corresponding
    instance of snmpNotifyFilterSubtree."
   DEFVAL { ''H }
   ::= { snmpNotifyFilterEntry 2 }

snmpNotifyFilterType OBJECT-TYPE
   SYNTAX      INTEGER {
           included(1),
           excluded(2)
           }
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object indicates whether the family of filter subtrees
    defined by this entry are included in or excluded from a
    filter.  A more detailed discussion of the use of this
    object can be found in section 6. of [RFC2573]."
   DEFVAL { included }
   ::= { snmpNotifyFilterEntry 3 }

snmpNotifyFilterStorageType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type of this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpNotifyFilterEntry 4 }

snmpNotifyFilterRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5)."
   ::= { snmpNotifyFilterEntry 5 }

--
--
-- Conformance information
--
--
snmpNotifyCompliances OBJECT IDENTIFIER ::=
                       { snmpNotifyConformance 1 }
snmpNotifyGroups      OBJECT IDENTIFIER ::=
                       { snmpNotifyConformance 2 }

--
--
-- Compliance statements
--
--

snmpNotifyBasicCompliance MODULE-COMPLIANCE
   STATUS      current
   DESCRIPTION
       "The compliance statement for minimal SNMP entities which
    implement only SNMP Unconfirmed-Class notifications and
    read-create operations on only the snmpTargetAddrTable."
   MODULE SNMP-TARGET-MIB
       MANDATORY-GROUPS { snmpTargetBasicGroup }

       OBJECT snmpTargetParamsMPModel
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required."

       OBJECT snmpTargetParamsSecurityModel
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required."

       OBJECT snmpTargetParamsSecurityName
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required."

       OBJECT snmpTargetParamsSecurityLevel
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required."

       OBJECT snmpTargetParamsStorageType
       SYNTAX INTEGER {
       readOnly(5)
       }
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required.
        Support of the values other(1), volatile(2),
        nonVolatile(3), and permanent(4) is not required."

       OBJECT snmpTargetParamsRowStatus
       SYNTAX INTEGER {
       active(1)
       }
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access to the
        snmpTargetParamsTable is not required.
        Support of the values notInService(2), notReady(3),
        createAndGo(4), createAndWait(5), and destroy(6) is
        not required."

   MODULE -- This Module
       MANDATORY-GROUPS { snmpNotifyGroup }

       OBJECT snmpNotifyTag
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required."

       OBJECT snmpNotifyType
       SYNTAX INTEGER {
       trap(1)
       }
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required.
        Support of the value notify(2) is not required."

       OBJECT snmpNotifyStorageType
       SYNTAX INTEGER {
       readOnly(5)
       }
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access is not required.
        Support of the values other(1), volatile(2),
        nonVolatile(3), and permanent(4) is not required."

       OBJECT snmpNotifyRowStatus
       SYNTAX INTEGER {
       active(1)
       }
       MIN-ACCESS    read-only
       DESCRIPTION
       "Create/delete/modify access to the
        snmpNotifyTable is not required.
        Support of the values notInService(2), notReady(3),
        createAndGo(4), createAndWait(5), and destroy(6) is
        not required."

   ::= { snmpNotifyCompliances 1 }

snmpNotifyBasicFiltersCompliance MODULE-COMPLIANCE
   STATUS      current
   DESCRIPTION
       "The compliance statement for SNMP entities which implement
    SNMP Unconfirmed-Class notifications with filtering, and
    read-create operations on all related tables."
   MODULE SNMP-TARGET-MIB
       MANDATORY-GROUPS { snmpTargetBasicGroup }
   MODULE -- This Module
       MANDATORY-GROUPS { snmpNotifyGroup,
              snmpNotifyFilterGroup }
   ::= { snmpNotifyCompliances 2 }

snmpNotifyFullCompliance MODULE-COMPLIANCE
   STATUS      current
   DESCRIPTION
       "The compliance statement for SNMP entities which either
    implement only SNMP Confirmed-Class notifications, or both
    SNMP Unconfirmed-Class and Confirmed-Class notifications,
    plus filtering and read-create operations on all related
    tables."
   MODULE SNMP-TARGET-MIB
       MANDATORY-GROUPS { snmpTargetBasicGroup,
              snmpTargetResponseGroup }
   MODULE -- This Module
       MANDATORY-GROUPS { snmpNotifyGroup,
              snmpNotifyFilterGroup }
   ::= { snmpNotifyCompliances 3 }

snmpNotifyGroup OBJECT-GROUP
   OBJECTS {
       snmpNotifyTag,
       snmpNotifyType,
       snmpNotifyStorageType,
       snmpNotifyRowStatus
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects for selecting which management
    targets are used for generating notifications, and the
    type of notification to be generated for each selected
    management target."
   ::= { snmpNotifyGroups 1 }

snmpNotifyFilterGroup OBJECT-GROUP
   OBJECTS {
       snmpNotifyFilterProfileName,
       snmpNotifyFilterProfileStorType,
       snmpNotifyFilterProfileRowStatus,
       snmpNotifyFilterMask,
       snmpNotifyFilterType,
       snmpNotifyFilterStorageType,
       snmpNotifyFilterRowStatus
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects providing remote configuration
    of notification filters."
   ::= { snmpNotifyGroups 2 }

END


SNMP-PROXY-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-IDENTITY,
   OBJECT-TYPE,
   snmpModules
       FROM SNMPv2-SMI

   RowStatus,
   StorageType
       FROM SNMPv2-TC

   SnmpEngineID,
   SnmpAdminString
       FROM SNMP-FRAMEWORK-MIB

   SnmpTagValue
       FROM SNMP-TARGET-MIB

   MODULE-COMPLIANCE,
   OBJECT-GROUP
       FROM SNMPv2-CONF;

snmpProxyMIB MODULE-IDENTITY
   LAST-UPDATED "9808040000Z"
   ORGANIZATION "IETF SNMPv3 Working Group"
   CONTACT-INFO
       "WG-email:   snmpv3@lists.tislabs.com
    Subscribe:  majordomo@lists.tislabs.com
            In message body:  subscribe snmpv3

    Chair:      Russ Mundy
            Trusted Information Systems
    Postal:     3060 Washington Rd
            Glenwood MD 21738
            USA
    EMail:      mundy@tislabs.com
    Phone:      +1-301-854-6889

    Co-editor:  David B. Levi
            SNMP Research, Inc.
    Postal:     3001 Kimberlin Heights Road
            Knoxville, TN 37920-9716
    EMail:      levi@snmp.com
    Phone:      +1 423 573 1434

    Co-editor:  Paul Meyer
            Secure Computing Corporation
    Postal:     2675 Long Lake Road
            Roseville, MN 55113
    EMail:      paul_meyer@securecomputing.com
    Phone:      +1 651 628 1592

    Co-editor:  Bob Stewart
            Cisco Systems, Inc.
    Postal:     170 West Tasman Drive
            San Jose, CA 95134-1706
    EMail:      bstewart@cisco.com
    Phone:      +1 603 654 2686"
   DESCRIPTION
       "This MIB module defines MIB objects which provide
    mechanisms to remotely configure the parameters
    used by a proxy forwarding application."
   REVISION    "9808040000Z"
   DESCRIPTION "Clarifications, published as
        RFC2573."
   REVISION    "9707140000Z"
   DESCRIPTION "The initial revision, published as RFC2273."
   ::= { snmpModules 14 }

snmpProxyObjects        OBJECT IDENTIFIER ::= { snmpProxyMIB 1 }
snmpProxyConformance    OBJECT IDENTIFIER ::= { snmpProxyMIB 3 }

--
--
-- The snmpProxyObjects group
--
--

snmpProxyTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpProxyEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The table of translation parameters used by proxy forwarder
    applications for forwarding SNMP messages."
   ::= { snmpProxyObjects 2 }

snmpProxyEntry OBJECT-TYPE
   SYNTAX      SnmpProxyEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "A set of translation parameters used by a proxy forwarder
    application for forwarding SNMP messages.

    Entries in the snmpProxyTable are created and deleted
    using the snmpProxyRowStatus object."
   INDEX { IMPLIED snmpProxyName }
   ::= { snmpProxyTable 1 }

SnmpProxyEntry ::= SEQUENCE {
   snmpProxyName               SnmpAdminString,
   snmpProxyType               INTEGER,
   snmpProxyContextEngineID    SnmpEngineID,
   snmpProxyContextName        SnmpAdminString,
   snmpProxyTargetParamsIn     SnmpAdminString,
   snmpProxySingleTargetOut    SnmpAdminString,
   snmpProxyMultipleTargetOut  SnmpTagValue,
   snmpProxyStorageType        StorageType,
   snmpProxyRowStatus          RowStatus
}

snmpProxyName OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The locally arbitrary, but unique identifier associated
    with this snmpProxyEntry."
   ::= { snmpProxyEntry 1 }

snmpProxyType OBJECT-TYPE
   SYNTAX      INTEGER {
           read(1),
           write(2),
           trap(3),
           inform(4)
           }
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The type of message that may be forwarded using
    the translation parameters defined by this entry."
   ::= { snmpProxyEntry 2 }

snmpProxyContextEngineID OBJECT-TYPE
   SYNTAX      SnmpEngineID
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The contextEngineID contained in messages that
    may be forwarded using the translation parameters
    defined by this entry."
   ::= { snmpProxyEntry 3 }

snmpProxyContextName OBJECT-TYPE
   SYNTAX      SnmpAdminString
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The contextName contained in messages that may be
    forwarded using the translation parameters defined
    by this entry.

    This object is optional, and if not supported, the
    contextName contained in a message is ignored when
    selecting an entry in the snmpProxyTable."
   ::= { snmpProxyEntry 4 }

snmpProxyTargetParamsIn OBJECT-TYPE
   SYNTAX      SnmpAdminString
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object selects an entry in the snmpTargetParamsTable.
    The selected entry is used to determine which row of the
    snmpProxyTable to use for forwarding received messages."
   ::= { snmpProxyEntry 5 }

snmpProxySingleTargetOut OBJECT-TYPE
   SYNTAX      SnmpAdminString
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object selects a management target defined in the
    snmpTargetAddrTable (in the SNMP-TARGET-MIB).  The
    selected target is defined by an entry in the
    snmpTargetAddrTable whose index value (snmpTargetAddrName)
    is equal to this object.

    This object is only used when selection of a single
    target is required (i.e. when forwarding an incoming
    read or write request)."
   ::= { snmpProxyEntry 6 }

snmpProxyMultipleTargetOut OBJECT-TYPE
   SYNTAX      SnmpTagValue
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object selects a set of management targets defined
    in the snmpTargetAddrTable (in the SNMP-TARGET-MIB).

    This object is only used when selection of multiple
    targets is required (i.e. when forwarding an incoming
    notification)."
   ::= { snmpProxyEntry 7 }

snmpProxyStorageType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type of this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpProxyEntry 8 }

snmpProxyRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5).

    The following objects may not be modified while the
    value of this object is active(1):
        - snmpProxyType
        - snmpProxyContextEngineID
        - snmpProxyContextName
        - snmpProxyTargetParamsIn
        - snmpProxySingleTargetOut
        - snmpProxyMultipleTargetOut"
   ::= { snmpProxyEntry 9 }

--
--
-- Conformance information
--
--

snmpProxyCompliances OBJECT IDENTIFIER ::=
                    { snmpProxyConformance 1 }
snmpProxyGroups      OBJECT IDENTIFIER ::=
                    { snmpProxyConformance 2 }

--
--
-- Compliance statements
--
--

snmpProxyCompliance MODULE-COMPLIANCE
   STATUS      current
   DESCRIPTION
       "The compliance statement for SNMP entities which include
    a proxy forwarding application."
   MODULE SNMP-TARGET-MIB
       MANDATORY-GROUPS { snmpTargetBasicGroup,
              snmpTargetResponseGroup }
   MODULE -- This Module
       MANDATORY-GROUPS { snmpProxyGroup }
   ::= { snmpProxyCompliances 1 }

snmpProxyGroup OBJECT-GROUP
   OBJECTS {
       snmpProxyType,
       snmpProxyContextEngineID,
       snmpProxyContextName,
       snmpProxyTargetParamsIn,
       snmpProxySingleTargetOut,
       snmpProxyMultipleTargetOut,
       snmpProxyStorageType,
       snmpProxyRowStatus
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects providing remote configuration of
    management target translation parameters for use by
    proxy forwarder applications."
   ::= { snmpProxyGroups 3 }

END


SNMP-TARGET-MIB DEFINITIONS ::= BEGIN

IMPORTS
   MODULE-IDENTITY,
   OBJECT-TYPE,
   snmpModules,
   Counter32,
   Integer32

       FROM SNMPv2-SMI

   TEXTUAL-CONVENTION,
   TDomain,
   TAddress,
   TimeInterval,
   RowStatus,
   StorageType,
   TestAndIncr
       FROM SNMPv2-TC

   SnmpSecurityModel,
   SnmpMessageProcessingModel,
   SnmpSecurityLevel,
   SnmpAdminString
       FROM SNMP-FRAMEWORK-MIB

   MODULE-COMPLIANCE,
   OBJECT-GROUP
       FROM SNMPv2-CONF;

snmpTargetMIB MODULE-IDENTITY
   LAST-UPDATED "9808040000Z"
   ORGANIZATION "IETF SNMPv3 Working Group"
   CONTACT-INFO
       "WG-email:   snmpv3@lists.tislabs.com
    Subscribe:  majordomo@lists.tislabs.com
            In message body:  subscribe snmpv3

    Chair:      Russ Mundy
            Trusted Information Systems
    Postal:     3060 Washington Rd
            Glenwood MD 21738
            USA
    EMail:      mundy@tislabs.com
    Phone:      +1-301-854-6889

    Co-editor:  David B. Levi
            SNMP Research, Inc.
    Postal:     3001 Kimberlin Heights Road
            Knoxville, TN 37920-9716
    EMail:      levi@snmp.com
    Phone:      +1 423 573 1434

    Co-editor:  Paul Meyer
            Secure Computing Corporation
    Postal:     2675 Long Lake Road
            Roseville, MN 55113
    EMail:      paul_meyer@securecomputing.com
    Phone:      +1 651 628 1592

    Co-editor:  Bob Stewart
            Cisco Systems, Inc.
    Postal:     170 West Tasman Drive
            San Jose, CA 95134-1706
    EMail:      bstewart@cisco.com
    Phone:      +1 603 654 2686"
   DESCRIPTION
       "This MIB module defines MIB objects which provide
    mechanisms to remotely configure the parameters used
    by an SNMP entity for the generation of SNMP messages."
   REVISION    "9808040000Z"
   DESCRIPTION "Clarifications, published as
        RFC2573."
   REVISION    "9707140000Z"
   DESCRIPTION "The initial revision, published as RFC2273."
   ::= { snmpModules 12 }

snmpTargetObjects       OBJECT IDENTIFIER ::= { snmpTargetMIB 1 }
snmpTargetConformance   OBJECT IDENTIFIER ::= { snmpTargetMIB 3 }

SnmpTagValue ::= TEXTUAL-CONVENTION
   DISPLAY-HINT "255a"
   STATUS       current
   DESCRIPTION
       "An octet string containing a tag value.
    Tag values are preferably in human-readable form.

    To facilitate internationalization, this information
    is represented using the ISO/IEC IS 10646-1 character
    set, encoded as an octet string using the UTF-8
    character encoding scheme described in RFC 2279.

    Since additional code points are added by amendments
    to the 10646 standard from time to time,
    implementations must be prepared to encounter any code
    point from 0x00000000 to 0x7fffffff.

    The use of control codes should be avoided, and certain
    control codes are not allowed as described below.

    For code points not directly supported by user
    interface hardware or software, an alternative means
    of entry and display, such as hexadecimal, may be
    provided.

    For information encoded in 7-bit US-ASCII, the UTF-8
    representation is identical to the US-ASCII encoding.

    Note that when this TC is used for an object that
    is used or envisioned to be used as an index, then a
    SIZE restriction must be specified so that the number
    of sub-identifiers for any object instance does not
    exceed the limit of 128, as defined by [RFC1905].

    An object of this type contains a single tag value
    which is used to select a set of entries in a table.

    A tag value is an arbitrary string of octets, but
    may not contain a delimiter character.  Delimiter
    characters are defined to be one of the following:

        -  An ASCII space character (0x20).

        -  An ASCII TAB character (0x09).

        -  An ASCII carriage return (CR) character (0x0D).

        -  An ASCII line feed (LF) character (0x0B).

    Delimiter characters are used to separate tag values
    in a tag list.  An object of this type may only
    contain a single tag value, and so delimiter
    characters are not allowed in a value of this type.

    Some examples of valid tag values are:

        - 'acme'

        - 'router'

        - 'host'

    The use of a tag value to select table entries is
    application and MIB specific."
   SYNTAX       OCTET STRING (SIZE (0..255))

SnmpTagList ::= TEXTUAL-CONVENTION
   DISPLAY-HINT "255a"
   STATUS       current
   DESCRIPTION
       "An octet string containing a list of tag values.
    Tag values are preferably in human-readable form.

    To facilitate internationalization, this information
    is represented using the ISO/IEC IS 10646-1 character
    set, encoded as an octet string using the UTF-8
    character encoding scheme described in RFC 2279.

    Since additional code points are added by amendments
    to the 10646 standard from time to time,
    implementations must be prepared to encounter any code
    point from 0x00000000 to 0x7fffffff.

    The use of control codes should be avoided, except as
    described below.

    For code points not directly supported by user
    interface hardware or software, an alternative means
    of entry and display, such as hexadecimal, may be
    provided.

    For information encoded in 7-bit US-ASCII, the UTF-8
    representation is identical to the US-ASCII encoding.

    An object of this type contains a list of tag values
    which are used to select a set of entries in a table.

    A tag value is an arbitrary string of octets, but
    may not contain a delimiter character.  Delimiter
    characters are defined to be one of the following:

        -  An ASCII space character (0x20).

        -  An ASCII TAB character (0x09).

        -  An ASCII carriage return (CR) character (0x0D).

        -  An ASCII line feed (LF) character (0x0B).

    Delimiter characters are used to separate tag values
    in a tag list.  Only a single delimiter character may
    occur between two tag values.  A tag value may not
    have a zero length.  These constraints imply certain
    restrictions on the contents of this object:

        - There cannot be a leading or trailing delimiter
          character.

        - There cannot be multiple adjacent delimiter
          characters.

    Some examples of valid tag lists are:

        - An empty string

        - 'acme router'

        - 'host managerStation'

    Note that although a tag value may not have a length of
    zero, an empty string is still valid.  This indicates
    an empty list (i.e. there are no tag values in the list).

    The use of the tag list to select table entries is
    application and MIB specific.  Typically, an application
    will provide one or more tag values, and any entry
    which contains some combination of these tag values
    will be selected."
   SYNTAX       OCTET STRING (SIZE (0..255))

--
--
-- The snmpTargetObjects group
--
--

snmpTargetSpinLock OBJECT-TYPE
   SYNTAX      TestAndIncr
   MAX-ACCESS  read-write
   STATUS      current
   DESCRIPTION
       "This object is used to facilitate modification of table
    entries in the SNMP-TARGET-MIB module by multiple
    managers.  In particular, it is useful when modifying
    the value of the snmpTargetAddrTagList object.

    The procedure for modifying the snmpTargetAddrTagList
    object is as follows:

        1.  Retrieve the value of snmpTargetSpinLock and
        of snmpTargetAddrTagList.

        2.  Generate a new value for snmpTargetAddrTagList.

        3.  Set the value of snmpTargetSpinLock to the
        retrieved value, and the value of
        snmpTargetAddrTagList to the new value.  If
        the set fails for the snmpTargetSpinLock
        object, go back to step 1."
   ::= { snmpTargetObjects 1 }

snmpTargetAddrTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpTargetAddrEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "A table of transport addresses to be used in the generation
    of SNMP messages."
   ::= { snmpTargetObjects 2 }

snmpTargetAddrEntry OBJECT-TYPE
   SYNTAX      SnmpTargetAddrEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "A transport address to be used in the generation
    of SNMP operations.

    Entries in the snmpTargetAddrTable are created and
    deleted using the snmpTargetAddrRowStatus object."
   INDEX { IMPLIED snmpTargetAddrName }
   ::= { snmpTargetAddrTable 1 }

SnmpTargetAddrEntry ::= SEQUENCE {
   snmpTargetAddrName         SnmpAdminString,
   snmpTargetAddrTDomain      TDomain,
   snmpTargetAddrTAddress     TAddress,
   snmpTargetAddrTimeout      TimeInterval,
   snmpTargetAddrRetryCount   Integer32,
   snmpTargetAddrTagList      SnmpTagList,
   snmpTargetAddrParams       SnmpAdminString,
   snmpTargetAddrStorageType  StorageType,
   snmpTargetAddrRowStatus    RowStatus
}

snmpTargetAddrName OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The locally arbitrary, but unique identifier associated
    with this snmpTargetAddrEntry."
   ::= { snmpTargetAddrEntry 1 }

snmpTargetAddrTDomain OBJECT-TYPE
   SYNTAX      TDomain
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object indicates the transport type of the address
    contained in the snmpTargetAddrTAddress object."
   ::= { snmpTargetAddrEntry 2 }

snmpTargetAddrTAddress OBJECT-TYPE
   SYNTAX      TAddress
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object contains a transport address.  The format of
    this address depends on the value of the
    snmpTargetAddrTDomain object."
   ::= { snmpTargetAddrEntry 3 }

snmpTargetAddrTimeout OBJECT-TYPE
   SYNTAX      TimeInterval
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object should reflect the expected maximum round
    trip time for communicating with the transport address
    defined by this row.  When a message is sent to this
    address, and a response (if one is expected) is not
    received within this time period, an implementation
    may assume that the response will not be delivered.

    Note that the time interval that an application waits
    for a response may actually be derived from the value
    of this object.  The method for deriving the actual time
    interval is implementation dependent.  One such method
    is to derive the expected round trip time based on a
    particular retransmission algorithm and on the number
    of timeouts which have occurred.  The type of message may
    also be considered when deriving expected round trip
    times for retransmissions.  For example, if a message is
    being sent with a securityLevel that indicates both
    authentication and privacy, the derived value may be
    increased to compensate for extra processing time spent
    during authentication and encryption processing."
   DEFVAL { 1500 }
   ::= { snmpTargetAddrEntry 4 }

snmpTargetAddrRetryCount OBJECT-TYPE
   SYNTAX      Integer32 (0..255)
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object specifies a default number of retries to be
    attempted when a response is not received for a generated
    message.  An application may provide its own retry count,
    in which case the value of this object is ignored."
   DEFVAL { 3 }
   ::= { snmpTargetAddrEntry 5 }

snmpTargetAddrTagList OBJECT-TYPE
   SYNTAX      SnmpTagList
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "This object contains a list of tag values which are
    used to select target addresses for a particular
    operation."
   DEFVAL { "" }
   ::= { snmpTargetAddrEntry 6 }

snmpTargetAddrParams OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The value of this object identifies an entry in the
    snmpTargetParamsTable.  The identified entry
    contains SNMP parameters to be used when generating
    messages to be sent to this transport address."
   ::= { snmpTargetAddrEntry 7 }

snmpTargetAddrStorageType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type for this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpTargetAddrEntry 8 }

snmpTargetAddrRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5).

    Until instances of all corresponding columns are
    appropriately configured, the value of the
    corresponding instance of the snmpTargetAddrRowStatus
    column is 'notReady'.

    In particular, a newly created row cannot be made
    active until the corresponding instances of
    snmpTargetAddrTDomain, snmpTargetAddrTAddress, and
    snmpTargetAddrParams have all been set.

    The following objects may not be modified while the
    value of this object is active(1):
        - snmpTargetAddrTDomain
        - snmpTargetAddrTAddress
    An attempt to set these objects while the value of
    snmpTargetAddrRowStatus is active(1) will result in
    an inconsistentValue error."
   ::= { snmpTargetAddrEntry 9 }

snmpTargetParamsTable OBJECT-TYPE
   SYNTAX      SEQUENCE OF SnmpTargetParamsEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "A table of SNMP target information to be used
    in the generation of SNMP messages."
   ::= { snmpTargetObjects 3 }

snmpTargetParamsEntry OBJECT-TYPE
   SYNTAX      SnmpTargetParamsEntry
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "A set of SNMP target information.

    Entries in the snmpTargetParamsTable are created and
    deleted using the snmpTargetParamsRowStatus object."
   INDEX { IMPLIED snmpTargetParamsName }
   ::= { snmpTargetParamsTable 1 }

SnmpTargetParamsEntry ::= SEQUENCE {
   snmpTargetParamsName           SnmpAdminString,
   snmpTargetParamsMPModel        SnmpMessageProcessingModel,
   snmpTargetParamsSecurityModel  SnmpSecurityModel,
   snmpTargetParamsSecurityName   SnmpAdminString,
   snmpTargetParamsSecurityLevel  SnmpSecurityLevel,
   snmpTargetParamsStorageType    StorageType,
   snmpTargetParamsRowStatus      RowStatus
}

snmpTargetParamsName OBJECT-TYPE
   SYNTAX      SnmpAdminString (SIZE(1..32))
   MAX-ACCESS  not-accessible
   STATUS      current
   DESCRIPTION
       "The locally arbitrary, but unique identifier associated
    with this snmpTargetParamsEntry."
   ::= { snmpTargetParamsEntry 1 }

snmpTargetParamsMPModel OBJECT-TYPE
   SYNTAX      SnmpMessageProcessingModel
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The Message Processing Model to be used when generating
    SNMP messages using this entry."
   ::= { snmpTargetParamsEntry 2 }

snmpTargetParamsSecurityModel OBJECT-TYPE
   SYNTAX      SnmpSecurityModel (1..2147483647)
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The Security Model to be used when generating SNMP
     messages using this entry.  An implementation may
     choose to return an inconsistentValue error if an
     attempt is made to set this variable to a value
     for a security model which the implementation does
     not support."
   ::= { snmpTargetParamsEntry 3 }

snmpTargetParamsSecurityName OBJECT-TYPE
   SYNTAX      SnmpAdminString
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The securityName which identifies the Principal on
    whose behalf SNMP messages will be generated using
    this entry."
   ::= { snmpTargetParamsEntry 4 }

snmpTargetParamsSecurityLevel OBJECT-TYPE
   SYNTAX      SnmpSecurityLevel
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The Level of Security to be used when generating
    SNMP messages using this entry."
   ::= { snmpTargetParamsEntry 5 }

snmpTargetParamsStorageType OBJECT-TYPE
   SYNTAX      StorageType
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The storage type for this conceptual row."
   DEFVAL { nonVolatile }
   ::= { snmpTargetParamsEntry 6 }

snmpTargetParamsRowStatus OBJECT-TYPE
   SYNTAX      RowStatus
   MAX-ACCESS  read-create
   STATUS      current
   DESCRIPTION
       "The status of this conceptual row.

    To create a row in this table, a manager must
    set this object to either createAndGo(4) or
    createAndWait(5).

    Until instances of all corresponding columns are
    appropriately configured, the value of the
    corresponding instance of the snmpTargetParamsRowStatus
    column is 'notReady'.

    In particular, a newly created row cannot be made
    active until the corresponding
    snmpTargetParamsMPModel,
    snmpTargetParamsSecurityModel,
    snmpTargetParamsSecurityName,
    and snmpTargetParamsSecurityLevel have all been set.
    The following objects may not be modified while the
    value of this object is active(1):
        - snmpTargetParamsMPModel
        - snmpTargetParamsSecurityModel
        - snmpTargetParamsSecurityName
        - snmpTargetParamsSecurityLevel
    An attempt to set these objects while the value of
    snmpTargetParamsRowStatus is active(1) will result in
    an inconsistentValue error."
   ::= { snmpTargetParamsEntry 7 }

snmpUnavailableContexts OBJECT-TYPE
   SYNTAX       Counter32
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION
       "The total number of packets received by the SNMP
    engine which were dropped because the context
    contained in the message was unavailable."
   ::= { snmpTargetObjects 4 }

snmpUnknownContexts OBJECT-TYPE
   SYNTAX       Counter32
   MAX-ACCESS   read-only
   STATUS       current
   DESCRIPTION
       "The total number of packets received by the SNMP
    engine which were dropped because the context
    contained in the message was unknown."
   ::= { snmpTargetObjects 5 }

--
--
-- Conformance information
--
--

snmpTargetCompliances OBJECT IDENTIFIER ::=
                       { snmpTargetConformance 1 }
snmpTargetGroups      OBJECT IDENTIFIER ::=
                       { snmpTargetConformance 2 }

--
--
-- Compliance statements
--
--
snmpTargetCommandResponderCompliance MODULE-COMPLIANCE
   STATUS      current
   DESCRIPTION
       "The compliance statement for SNMP entities which include
    a command responder application."
   MODULE -- This Module
       MANDATORY-GROUPS { snmpTargetCommandResponderGroup }
   ::= { snmpTargetCompliances 1 }

snmpTargetBasicGroup OBJECT-GROUP
   OBJECTS {
       snmpTargetSpinLock,
       snmpTargetAddrTDomain,
       snmpTargetAddrTAddress,
       snmpTargetAddrTagList,
       snmpTargetAddrParams,
       snmpTargetAddrStorageType,
       snmpTargetAddrRowStatus,
       snmpTargetParamsMPModel,
       snmpTargetParamsSecurityModel,
       snmpTargetParamsSecurityName,
       snmpTargetParamsSecurityLevel,
       snmpTargetParamsStorageType,
       snmpTargetParamsRowStatus
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects providing basic remote
    configuration of management targets."
   ::= { snmpTargetGroups 1 }

snmpTargetResponseGroup OBJECT-GROUP
   OBJECTS {
       snmpTargetAddrTimeout,
       snmpTargetAddrRetryCount
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects providing remote configuration
    of management targets for applications which generate
    SNMP messages for which a response message would be
    expected."
   ::= { snmpTargetGroups 2 }

snmpTargetCommandResponderGroup OBJECT-GROUP
   OBJECTS {
       snmpUnavailableContexts,
       snmpUnknownContexts
   }
   STATUS      current
   DESCRIPTION
       "A collection of objects required for command responder
    applications, used for counting error conditions."
   ::= { snmpTargetGroups 3 }

END


SNMP-USER-BASED-SM-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE,
    OBJECT-IDENTITY,
    snmpModules, Counter32                FROM SNMPv2-SMI
    TEXTUAL-CONVENTION, TestAndIncr,
    RowStatus, RowPointer,
    StorageType, AutonomousType           FROM SNMPv2-TC
    MODULE-COMPLIANCE, OBJECT-GROUP       FROM SNMPv2-CONF
    SnmpAdminString, SnmpEngineID,
    snmpAuthProtocols, snmpPrivProtocols  FROM SNMP-FRAMEWORK-MIB;

snmpUsmMIB MODULE-IDENTITY
    LAST-UPDATED "9901200000Z"            -- 20 Jan 1999, midnight
    ORGANIZATION "SNMPv3 Working Group"
    CONTACT-INFO "WG-email:   snmpv3@lists.tislabs.com
                  Subscribe:  majordomo@lists.tislabs.com
                              In msg body:  subscribe snmpv3

                  Chair:      Russ Mundy
                              Trusted Information Systems
                  postal:     3060 Washington Rd
                              Glenwood MD 21738
                              USA
                  email:      mundy@tislabs.com
                  phone:      +1-301-854-6889

                  Co-editor   Uri Blumenthal
                              IBM T. J. Watson Research
                  postal:     30 Saw Mill River Pkwy,
                              Hawthorne, NY 10532
                              USA
                  email:      uri@watson.ibm.com
                  phone:      +1-914-784-7964

                  Co-editor:  Bert Wijnen
                              IBM T. J. Watson Research
                  postal:     Schagen 33
                              3461 GL Linschoten
                              Netherlands
                  email:      wijnen@vnet.ibm.com
                  phone:      +31-348-432-794
                 "
    DESCRIPTION  "The management information definitions for the
                  SNMP User-based Security Model.
                 "
--  Revision history

    REVISION     "9901200000Z"            -- 20 Jan 1999, midnight
    DESCRIPTION  "Clarifications, published as RFC2574"

    REVISION     "9711200000Z"            -- 20 Nov 1997, midnight
    DESCRIPTION  "Initial version, published as RFC2274"

    ::= { snmpModules 15 }

-- Administrative assignments ****************************************

usmMIBObjects     OBJECT IDENTIFIER ::= { snmpUsmMIB 1 }
usmMIBConformance OBJECT IDENTIFIER ::= { snmpUsmMIB 2 }

-- Identification of Authentication and Privacy Protocols ************

usmNoAuthProtocol OBJECT-IDENTITY
    STATUS        current
    DESCRIPTION  "No Authentication Protocol."
    ::= { snmpAuthProtocols 1 }

usmHMACMD5AuthProtocol OBJECT-IDENTITY
    STATUS        current
    DESCRIPTION  "The HMAC-MD5-96 Digest Authentication Protocol."
    REFERENCE    "- H. Krawczyk, M. Bellare, R. Canetti HMAC:
                    Keyed-Hashing for Message Authentication,
                    RFC2104, Feb 1997.
                  - Rivest, R., Message Digest Algorithm MD5, RFC1321.
                 "
    ::= { snmpAuthProtocols 2 }

usmHMACSHAAuthProtocol OBJECT-IDENTITY
    STATUS        current
    DESCRIPTION  "The HMAC-SHA-96 Digest Authentication Protocol."
    REFERENCE    "- H. Krawczyk, M. Bellare, R. Canetti, HMAC:
                    Keyed-Hashing for Message Authentication,
                    RFC2104, Feb 1997.
                  - Secure Hash Algorithm. NIST FIPS 180-1.
                 "
    ::= { snmpAuthProtocols 3 }

usmNoPrivProtocol OBJECT-IDENTITY
    STATUS        current
    DESCRIPTION  "No Privacy Protocol."
    ::= { snmpPrivProtocols 1 }

usmDESPrivProtocol OBJECT-IDENTITY
    STATUS        current
    DESCRIPTION  "The CBC-DES Symmetric Encryption Protocol."
    REFERENCE    "- Data Encryption Standard, National Institute of
                    Standards and Technology.  Federal Information
                    Processing Standard (FIPS) Publication 46-1.
                    Supersedes FIPS Publication 46,
                    (January, 1977; reaffirmed January, 1988).

                  - Data Encryption Algorithm, American National
                    Standards Institute.  ANSI X3.92-1981,
                    (December, 1980).

                  - DES Modes of Operation, National Institute of
                    Standards and Technology.  Federal Information
                    Processing Standard (FIPS) Publication 81,
                    (December, 1980).

                  - Data Encryption Algorithm - Modes of Operation,
                    American National Standards Institute.
                    ANSI X3.106-1983, (May 1983).
                 "
    ::= { snmpPrivProtocols 2 }

-- Textual Conventions ***********************************************

KeyChange ::=     TEXTUAL-CONVENTION
   STATUS         current
   DESCRIPTION
         "Every definition of an object with this syntax must identify
          a protocol P, a secret key K, and a hash algorithm H
          that produces output of L octets.

          The object's value is a manager-generated, partially-random
          value which, when modified, causes the value of the secret
          key K, to be modified via a one-way function.

          The value of an instance of this object is the concatenation
          of two components: first a 'random' component and then a
          'delta' component.

          The lengths of the random and delta components
          are given by the corresponding value of the protocol P;
          if P requires K to be a fixed length, the length of both the
          random and delta components is that fixed length; if P
          allows the length of K to be variable up to a particular
          maximum length, the length of the random component is that
          maximum length and the length of the delta component is any
          length less than or equal to that maximum length.
          For example, usmHMACMD5AuthProtocol requires K to be a fixed
          length of 16 octets and L - of 16 octets.
          usmHMACSHAAuthProtocol requires K to be a fixed length of
          20 octets and L - of 20 octets. Other protocols may define
          other sizes, as deemed appropriate.

          When a requester wants to change the old key K to a new
          key keyNew on a remote entity, the 'random' component is
          obtained from either a true random generator, or from a
          pseudorandom generator, and the 'delta' component is
          computed as follows:

           - a temporary variable is initialized to the existing value
             of K;
           - if the length of the keyNew is greater than L octets,
             then:
              - the random component is appended to the value of the
                temporary variable, and the result is input to the
                the hash algorithm H to produce a digest value, and
                the temporary variable is set to this digest value;
              - the value of the temporary variable is XOR-ed with
                the first (next) L-octets (16 octets in case of MD5)
                of the keyNew to produce the first (next) L-octets
                (16 octets in case of MD5) of the 'delta' component.
              - the above two steps are repeated until the unused
                portion of the keyNew component is L octets or less,
           - the random component is appended to the value of the
             temporary variable, and the result is input to the
             hash algorithm H to produce a digest value;
           - this digest value, truncated if necessary to be the same
             length as the unused portion of the keyNew, is XOR-ed
             with the unused portion of the keyNew to produce the
             (final portion of the) 'delta' component.

           For example, using MD5 as the hash algorithm H:

              iterations = (lenOfDelta - 1)/16; /* integer division */
              temp = keyOld;
              for (i = 0; i < iterations; i++) {
                  temp = MD5 (temp || random);
                  delta[i*16 .. (i*16)+15] =
                         temp XOR keyNew[i*16 .. (i*16)+15];
              }
              temp = MD5 (temp || random);
              delta[i*16 .. lenOfDelta-1] =
                     temp XOR keyNew[i*16 .. lenOfDelta-1];

          The 'random' and 'delta' components are then concatenated as
          described above, and the resulting octet string is sent to
          the recipient as the new value of an instance of this object.

          At the receiver side, when an instance of this object is set
          to a new value, then a new value of K is computed as follows:

           - a temporary variable is initialized to the existing value
             of K;
           - if the length of the delta component is greater than L
             octets, then:
              - the random component is appended to the value of the
                temporary variable, and the result is input to the
                hash algorithm H to produce a digest value, and the
                temporary variable is set to this digest value;
              - the value of the temporary variable is XOR-ed with
                the first (next) L-octets (16 octets in case of MD5)
                of the delta component to produce the first (next)
                L-octets (16 octets in case of MD5) of the new value
                of K.
              - the above two steps are repeated until the unused
                portion of the delta component is L octets or less,
           - the random component is appended to the value of the
             temporary variable, and the result is input to the
             hash algorithm H to produce a digest value;
           - this digest value, truncated if necessary to be the same
             length as the unused portion of the delta component, is
             XOR-ed with the unused portion of the delta component to
             produce the (final portion of the) new value of K.

           For example, using MD5 as the hash algorithm H:

              iterations = (lenOfDelta - 1)/16; /* integer division */
              temp = keyOld;
              for (i = 0; i < iterations; i++) {
                  temp = MD5 (temp || random);
                  keyNew[i*16 .. (i*16)+15] =
                         temp XOR delta[i*16 .. (i*16)+15];
              }
              temp = MD5 (temp || random);
              keyNew[i*16 .. lenOfDelta-1] =
                     temp XOR delta[i*16 .. lenOfDelta-1];

          The value of an object with this syntax, whenever it is
          retrieved by the management protocol, is always the zero
          length string.

          Note that the keyOld and keyNew are the localized keys.

          Note that it is probably wise that when an SNMP entity sends
          a SetRequest to change a key, that it keeps a copy of the old
          key until it has confirmed that the key change actually
          succeeded.
         "
    SYNTAX       OCTET STRING

-- Statistics for the User-based Security Model **********************

usmStats         OBJECT IDENTIFIER ::= { usmMIBObjects 1 }

usmStatsUnsupportedSecLevels OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they requested a
                 securityLevel that was unknown to the SNMP engine
                 or otherwise unavailable.
                "
    ::= { usmStats 1 }

usmStatsNotInTimeWindows OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they appeared
                 outside of the authoritative SNMP engine's window.
                "
    ::= { usmStats 2 }

usmStatsUnknownUserNames OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they referenced a
                 user that was not known to the SNMP engine.
                "
    ::= { usmStats 3 }

usmStatsUnknownEngineIDs OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they referenced an
                 snmpEngineID that was not known to the SNMP engine.
                "
    ::= { usmStats 4 }

usmStatsWrongDigests OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they didn't
                 contain the expected digest value.
                "
    ::= { usmStats 5 }

usmStatsDecryptionErrors OBJECT-TYPE
    SYNTAX       Counter32
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "The total number of packets received by the SNMP
                 engine which were dropped because they could not be
                 decrypted.
                "
    ::= { usmStats 6 }

-- The usmUser Group ************************************************

usmUser          OBJECT IDENTIFIER ::= { usmMIBObjects 2 }

usmUserSpinLock  OBJECT-TYPE
    SYNTAX       TestAndIncr
    MAX-ACCESS   read-write
    STATUS       current
    DESCRIPTION "An advisory lock used to allow several cooperating
                 Command Generator Applications to coordinate their
                 use of facilities to alter secrets in the
                 usmUserTable.
                "
    ::= { usmUser 1 }

-- The table of valid users for the User-based Security Model ********

usmUserTable     OBJECT-TYPE
    SYNTAX       SEQUENCE OF UsmUserEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The table of users configured in the SNMP engine's
                 Local Configuration Datastore (LCD).

                 To create a new user (i.e., to instantiate a new
                 conceptual row in this table), it is recommended to
                 follow this procedure:

                   1)  GET(usmUserSpinLock.0) and save in sValue.
                   2)  SET(usmUserSpinLock.0=sValue,
                           usmUserCloneFrom=templateUser,
                           usmUserStatus=createAndWait)
                       You should use a template user to clone from
                       which has the proper auth/priv protocol defined.

                 If the new user is to use privacy:

                   3)  generate the keyChange value based on the secret
                       privKey of the clone-from user and the secret key
                       to be used for the new user. Let us call this
                       pkcValue.
                   4)  GET(usmUserSpinLock.0) and save in sValue.
                   5)  SET(usmUserSpinLock.0=sValue,
                           usmUserPrivKeyChange=pkcValue
                           usmUserPublic=randomValue1)
                   6)  GET(usmUserPulic) and check it has randomValue1.
                       If not, repeat steps 4-6.

                 If the new user will never use privacy:

                   7)  SET(usmUserPrivProtocol=usmNoPrivProtocol)

                 If the new user is to use authentication:

                   8)  generate the keyChange value based on the secret
                       authKey of the clone-from user and the secret key
                       to be used for the new user. Let us call this
                       akcValue.
                   9)  GET(usmUserSpinLock.0) and save in sValue.
                   10) SET(usmUserSpinLock.0=sValue,
                           usmUserAuthKeyChange=akcValue
                           usmUserPublic=randomValue2)
                   11) GET(usmUserPulic) and check it has randomValue2.
                       If not, repeat steps 9-11.

                 If the new user will never use authentication:

                   12) SET(usmUserAuthProtocol=usmNoAuthProtocol)

                 Finally, activate the new user:

                   13) SET(usmUserStatus=active)

                 The new user should now be available and ready to be
                 used for SNMPv3 communication. Note however that access
                 to MIB data must be provided via configuration of the
                 SNMP-VIEW-BASED-ACM-MIB.

                 The use of usmUserSpinlock is to avoid conflicts with
                 another SNMP command responder application which may
                 also be acting on the usmUserTable.
                "
    ::= { usmUser 2 }

usmUserEntry     OBJECT-TYPE
    SYNTAX       UsmUserEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "A user configured in the SNMP engine's Local
                 Configuration Datastore (LCD) for the User-based
                 Security Model.
                "
    INDEX       { usmUserEngineID,
                  usmUserName
                }
    ::= { usmUserTable 1 }

UsmUserEntry ::= SEQUENCE
    {
        usmUserEngineID         SnmpEngineID,
        usmUserName             SnmpAdminString,
        usmUserSecurityName     SnmpAdminString,
        usmUserCloneFrom        RowPointer,
        usmUserAuthProtocol     AutonomousType,
        usmUserAuthKeyChange    KeyChange,
        usmUserOwnAuthKeyChange KeyChange,
        usmUserPrivProtocol     AutonomousType,
        usmUserPrivKeyChange    KeyChange,
        usmUserOwnPrivKeyChange KeyChange,
        usmUserPublic           OCTET STRING,
        usmUserStorageType      StorageType,
        usmUserStatus           RowStatus
    }

usmUserEngineID  OBJECT-TYPE
    SYNTAX       SnmpEngineID
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "An SNMP engine's administratively-unique identifier.

                 In a simple agent, this value is always that agent's
                 own snmpEngineID value.

                 The value can also take the value of the snmpEngineID
                 of a remote SNMP engine with which this user can
                 communicate.
                "
    ::= { usmUserEntry 1 }

usmUserName      OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(1..32))
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "A human readable string representing the name of
                 the user.

                 This is the (User-based Security) Model dependent
                 security ID.
                "
    ::= { usmUserEntry 2 }

usmUserSecurityName OBJECT-TYPE
    SYNTAX       SnmpAdminString
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "A human readable string representing the user in
                 Security Model independent format.

                 The default transformation of the User-based Security
                 Model dependent security ID to the securityName and
                 vice versa is the identity function so that the
                 securityName is the same as the userName.
                "
    ::= { usmUserEntry 3 }

usmUserCloneFrom OBJECT-TYPE
    SYNTAX       RowPointer
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "A pointer to another conceptual row in this
                 usmUserTable.  The user in this other conceptual
                 row is called the clone-from user.

                 When a new user is created (i.e., a new conceptual
                 row is instantiated in this table), the privacy and
                 authentication parameters of the new user must be
                 cloned from its clone-from user. These parameters are:
                   - authentication protocol (usmUserAuthProtocol)
                   - privacy protocol (usmUserPrivProtocol)
                 They will be copied regardless of what the current
                 value is.

                 Cloning also causes the initial values of the secret
                 authentication key (authKey) and the secret encryption
                 key (privKey) of the new user to be set to the same
                 value as the corresponding secret of the clone-from
                 user.

                 The first time an instance of this object is set by
                 a management operation (either at or after its
                 instantiation), the cloning process is invoked.
                 Subsequent writes are successful but invoke no
                 action to be taken by the receiver.
                 The cloning process fails with an 'inconsistentName'
                 error if the conceptual row representing the
                 clone-from user does not exist or is not in an active
                 state when the cloning process is invoked.

                 When this object is read, the ZeroDotZero OID
                 is returned.
                "
    ::= { usmUserEntry 4 }

usmUserAuthProtocol OBJECT-TYPE
    SYNTAX       AutonomousType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "An indication of whether messages sent on behalf of
                 this user to/from the SNMP engine identified by
                 usmUserEngineID, can be authenticated, and if so,
                 the type of authentication protocol which is used.

                 An instance of this object is created concurrently
                 with the creation of any other object instance for
                 the same user (i.e., as part of the processing of
                 the set operation which creates the first object
                 instance in the same conceptual row).

                 If an initial set operation (i.e. at row creation time)
                 tries to set a value for an unknown or unsupported
                 protocol, then a 'wrongValue' error must be returned.

                 The value will be overwritten/set when a set operation
                 is performed on the corresponding instance of
                 usmUserCloneFrom.

                 Once instantiated, the value of such an instance of
                 this object can only be changed via a set operation to
                 the value of the usmNoAuthProtocol.

                 If a set operation tries to change the value of an
                 existing instance of this object to any value other
                 than usmNoAuthProtocol, then an 'inconsistentValue'
                 error must be returned.

                 If a set operation tries to set the value to the
                 usmNoAuthProtocol while the usmUserPrivProtocol value
                 in the same row is not equal to usmNoPrivProtocol,
                 then an 'inconsistentValue' error must be returned.
                 That means that an SNMP command generator application
                 must first ensure that the usmUserPrivProtocol is set
                 to the usmNoPrivProtocol value before it can set
                 the usmUserAuthProtocol value to usmNoAuthProtocol.
                "
    DEFVAL      { usmNoAuthProtocol }
    ::= { usmUserEntry 5 }

usmUserAuthKeyChange OBJECT-TYPE
    SYNTAX       KeyChange   -- typically (SIZE (0 | 32)) for HMACMD5
                             -- typically (SIZE (0 | 40)) for HMACSHA
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "An object, which when modified, causes the secret
                 authentication key used for messages sent on behalf
                 of this user to/from the SNMP engine identified by
                 usmUserEngineID, to be modified via a one-way
                 function.

                 The associated protocol is the usmUserAuthProtocol.
                 The associated secret key is the user's secret
                 authentication key (authKey). The associated hash
                 algorithm is the algorithm used by the user's
                 usmUserAuthProtocol.

                 When creating a new user, it is an 'inconsistentName'
                 error for a set operation to refer to this object
                 unless it is previously or concurrently initialized
                 through a set operation on the corresponding instance
                 of usmUserCloneFrom.

                 When the value of the corresponding usmUserAuthProtocol
                 is usmNoAuthProtocol, then a set is successful, but
                 effectively is a no-op.

                 When this object is read, the zero-length (empty)
                 string is returned.

                 The recommended way to do a key change is as follows:

                   1) GET(usmUserSpinLock.0) and save in sValue.
                   2) generate the keyChange value based on the old
                      (existing) secret key and the new secret key,
                      let us call this kcValue.

                 If you do the key change on behalf of another user:

                   3) SET(usmUserSpinLock.0=sValue,
                          usmUserAuthKeyChange=kcValue
                          usmUserPublic=randomValue)

                 If you do the key change for yourself:

                   4) SET(usmUserSpinLock.0=sValue,
                          usmUserOwnAuthKeyChange=kcValue
                          usmUserPublic=randomValue)

                 If you get a response with error-status of noError,
                 then the SET succeeded and the new key is active.
                 If you do not get a response, then you can issue a
                 GET(usmUserPublic) and check if the value is equal
                 to the randomValue you did send in the SET. If so, then
                 the key change succeeded and the new key is active
                 (probably the response got lost). If not, then the SET
                 request probably never reached the target and so you
                 can start over with the procedure above.
                "
    DEFVAL      { ''H }    -- the empty string
    ::= { usmUserEntry 6 }

usmUserOwnAuthKeyChange OBJECT-TYPE
    SYNTAX       KeyChange   -- typically (SIZE (0 | 32)) for HMACMD5
                             -- typically (SIZE (0 | 40)) for HMACSHA
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "Behaves exactly as usmUserAuthKeyChange, with one
                 notable difference: in order for the set operation
                 to succeed, the usmUserName of the operation
                 requester must match the usmUserName that
                 indexes the row which is targeted by this
                 operation.
                 In addition, the USM security model must be
                 used for this operation.

                 The idea here is that access to this column can be
                 public, since it will only allow a user to change
                 his own secret authentication key (authKey).
                 Note that this can only be done once the row is active.

                 When a set is received and the usmUserName of the
                 requester is not the same as the umsUserName that
                 indexes the row which is targeted by this operation,
                 then a 'noAccess' error must be returned.

                 When a set is received and the security model in use
                 is not USM, then a 'noAccess' error must be returned.
                "
    DEFVAL      { ''H }    -- the empty string
    ::= { usmUserEntry 7 }

usmUserPrivProtocol OBJECT-TYPE
    SYNTAX       AutonomousType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "An indication of whether messages sent on behalf of
                 this user to/from the SNMP engine identified by
                 usmUserEngineID, can be protected from disclosure,
                 and if so, the type of privacy protocol which is used.

                 An instance of this object is created concurrently
                 with the creation of any other object instance for
                 the same user (i.e., as part of the processing of
                 the set operation which creates the first object
                 instance in the same conceptual row).

                 If an initial set operation (i.e. at row creation time)
                 tries to set a value for an unknown or unsupported
                 protocol, then a 'wrongValue' error must be returned.

                 The value will be overwritten/set when a set operation
                 is performed on the corresponding instance of
                 usmUserCloneFrom.

                 Once instantiated, the value of such an instance of
                 this object can only be changed via a set operation to
                 the value of the usmNoPrivProtocol.

                 If a set operation tries to change the value of an
                 existing instance of this object to any value other
                 than usmNoPrivProtocol, then an 'inconsistentValue'
                 error must be returned.

                 Note that if any privacy protocol is used, then you
                 must also use an authentication protocol. In other
                 words, if usmUserPrivProtocol is set to anything else
                 than usmNoPrivProtocol, then the corresponding instance
                 of usmUserAuthProtocol cannot have a value of
                 usmNoAuthProtocol. If it does, then an
                 'inconsistentValue' error must be returned.
                "
    DEFVAL      { usmNoPrivProtocol }
    ::= { usmUserEntry 8 }

usmUserPrivKeyChange OBJECT-TYPE
    SYNTAX       KeyChange  -- typically (SIZE (0 | 32)) for DES
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "An object, which when modified, causes the secret
                 encryption key used for messages sent on behalf
                 of this user to/from the SNMP engine identified by
                 usmUserEngineID, to be modified via a one-way
                 function.

                 The associated protocol is the usmUserPrivProtocol.
                 The associated secret key is the user's secret
                 privacy key (privKey). The associated hash
                 algorithm is the algorithm used by the user's
                 usmUserAuthProtocol.

                 When creating a new user, it is an 'inconsistentName'
                 error for a set operation to refer to this object
                 unless it is previously or concurrently initialized
                 through a set operation on the corresponding instance
                 of usmUserCloneFrom.

                 When the value of the corresponding usmUserPrivProtocol
                 is usmNoPrivProtocol, then a set is successful, but
                 effectively is a no-op.

                 When this object is read, the zero-length (empty)
                 string is returned.
                 See the description clause of usmUserAuthKeyChange for
                 a recommended procedure to do a key change.
                "
    DEFVAL      { ''H }    -- the empty string
    ::= { usmUserEntry 9 }

usmUserOwnPrivKeyChange OBJECT-TYPE
    SYNTAX       KeyChange  -- typically (SIZE (0 | 32)) for DES
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "Behaves exactly as usmUserPrivKeyChange, with one
                 notable difference: in order for the Set operation
                 to succeed, the usmUserName of the operation
                 requester must match the usmUserName that indexes
                 the row which is targeted by this operation.
                 In addition, the USM security model must be
                 used for this operation.

                 The idea here is that access to this column can be
                 public, since it will only allow a user to change
                 his own secret privacy key (privKey).
                 Note that this can only be done once the row is active.

                 When a set is received and the usmUserName of the
                 requester is not the same as the umsUserName that
                 indexes the row which is targeted by this operation,
                 then a 'noAccess' error must be returned.

                 When a set is received and the security model in use
                 is not USM, then a 'noAccess' error must be returned.
                "
    DEFVAL      { ''H }    -- the empty string
    ::= { usmUserEntry 10 }

usmUserPublic    OBJECT-TYPE
    SYNTAX       OCTET STRING (SIZE(0..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "A publicly-readable value which can be written as part
                 of the procedure for changing a user's secret
                 authentication and/or privacy key, and later read to
                 determine whether the change of the secret was
                 effected.
                "
    DEFVAL      { ''H }  -- the empty string
    ::= { usmUserEntry 11 }

usmUserStorageType OBJECT-TYPE
    SYNTAX       StorageType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The storage type for this conceptual row.

                 Conceptual rows having the value 'permanent' must
                 allow write-access at a minimum to:

                 - usmUserAuthKeyChange, usmUserOwnAuthKeyChange
                   and usmUserPublic for a user who employs
                   authentication, and
                 - usmUserPrivKeyChange, usmUserOwnPrivKeyChange
                   and usmUserPublic for a user who employs
                   privacy.

                 Note that any user who employs authentication or
                 privacy must allow its secret(s) to be updated and
                 thus cannot be 'readOnly'.

                 If an initial set operation tries to set the value to
                 'readOnly' for a user who employs authentication or
                 privacy, then an 'inconsistentValue' error must be
                 returned.  Note that if the value has been previously
                 set (implicit or explicit) to any value, then the rules
                 as defined in the StorageType Textual Convention apply.

                 It is an implementation issue to decide if a SET for
                 a readOnly or permanent row is accepted at all. In some
                 contexts this may make sense, in others it may not. If
                 a SET for a readOnly or permanent row is not accepted
                 at all, then a 'wrongValue' error must be returned.
                "
    DEFVAL      { nonVolatile }
    ::= { usmUserEntry 12 }

usmUserStatus    OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The status of this conceptual row.

                 Until instances of all corresponding columns are
                 appropriately configured, the value of the
                 corresponding instance of the usmUserStatus column
                 is 'notReady'.

                 In particular, a newly created row for a user who
                 employs authentication, cannot be made active until the
                 corresponding usmUserCloneFrom and usmUserAuthKeyChange
                 have been set.

                 Further, a newly created row for a user who also
                 employs privacy, cannot be made active until the
                 usmUserPrivKeyChange has been set.

                 The RowStatus TC [RFC2579] requires that this
                 DESCRIPTION clause states under which circumstances
                 other objects in this row can be modified:

                 The value of this object has no effect on whether
                 other objects in this conceptual row can be modified,
                 except for usmUserOwnAuthKeyChange and
                 usmUserOwnPrivKeyChange. For these 2 objects, the
                 value of usmUserStatus MUST be active.
                "
    ::= { usmUserEntry 13 }

-- Conformance Information *******************************************

usmMIBCompliances OBJECT IDENTIFIER ::= { usmMIBConformance 1 }
usmMIBGroups      OBJECT IDENTIFIER ::= { usmMIBConformance 2 }

-- Compliance statements

usmMIBCompliance MODULE-COMPLIANCE
    STATUS       current
    DESCRIPTION "The compliance statement for SNMP engines which
                 implement the SNMP-USER-BASED-SM-MIB.
                "

    MODULE       -- this module
        MANDATORY-GROUPS { usmMIBBasicGroup }

        OBJECT           usmUserAuthProtocol
        MIN-ACCESS       read-only
        DESCRIPTION     "Write access is not required."

        OBJECT           usmUserPrivProtocol
        MIN-ACCESS       read-only
        DESCRIPTION     "Write access is not required."

    ::= { usmMIBCompliances 1 }

-- Units of compliance
usmMIBBasicGroup OBJECT-GROUP
    OBJECTS     {
                  usmStatsUnsupportedSecLevels,
                  usmStatsNotInTimeWindows,
                  usmStatsUnknownUserNames,
                  usmStatsUnknownEngineIDs,
                  usmStatsWrongDigests,
                  usmStatsDecryptionErrors,
                  usmUserSpinLock,
                  usmUserSecurityName,
                  usmUserCloneFrom,
                  usmUserAuthProtocol,
                  usmUserAuthKeyChange,
                  usmUserOwnAuthKeyChange,
                  usmUserPrivProtocol,
                  usmUserPrivKeyChange,
                  usmUserOwnPrivKeyChange,
                  usmUserPublic,
                  usmUserStorageType,
                  usmUserStatus
                }
    STATUS       current
    DESCRIPTION "A collection of objects providing for configuration
                 of an SNMP engine which implements the SNMP
                 User-based Security Model.
                "
    ::= { usmMIBGroups 1 }

END


SNMP-VIEW-BASED-ACM-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-COMPLIANCE, OBJECT-GROUP       FROM SNMPv2-CONF
    MODULE-IDENTITY, OBJECT-TYPE,
    snmpModules                           FROM SNMPv2-SMI
    TestAndIncr,
    RowStatus, StorageType                FROM SNMPv2-TC
    SnmpAdminString,
    SnmpSecurityLevel,
    SnmpSecurityModel                     FROM SNMP-FRAMEWORK-MIB;

snmpVacmMIB       MODULE-IDENTITY
    LAST-UPDATED "9901200000Z"            -- 20 Jan 1999, midnight
    ORGANIZATION "SNMPv3 Working Group"
    CONTACT-INFO "WG-email:   snmpv3@lists.tislabs.com
                  Subscribe:  majordomo@lists.tislabs.com
                              In message body:  subscribe snmpv3

                  Chair:      Russ Mundy
                              Trusted Information Systems
                  postal:     3060 Washington Rd
                              Glenwood MD 21738
                              USA
                  email:      mundy@tislabs.com
                  phone:      +1-301-854-6889

                  Co-editor:  Bert Wijnen
                              IBM T.J. Watson Research
                  postal:     Schagen 33
                              3461 GL Linschoten
                              Netherlands
                  email:      wijnen@vnet.ibm.com
                  phone:      +31-348-432-794

                  Co-editor:  Randy Presuhn
                              BMC Software, Inc
                  postal:     965 Stewart Drive
                              Sunnyvale, CA 94086
                              USA
                  email:      randy_presuhn@bmc.com
                  phone:      +1-408-616-3100

                  Co-editor:  Keith McCloghrie
                              Cisco Systems, Inc.
                  postal:     170 West Tasman Drive
                              San Jose, CA  95134-1706
                              USA
                  email:      kzm@cisco.com
                  phone:      +1-408-526-5260
                 "
    DESCRIPTION  "The management information definitions for the
                  View-based Access Control Model for SNMP.
                 "
--  Revision history
    REVISION     "9901200000Z"            -- 20 Jan 1999, midnight
    DESCRIPTION  "Clarifications, published as RFC2575"

    REVISION     "9711200000Z"            -- 20 Nov 1997, midnight
    DESCRIPTION  "Initial version, published as RFC2275"

    ::= { snmpModules 16 }

-- Administrative assignments ****************************************

vacmMIBObjects      OBJECT IDENTIFIER ::= { snmpVacmMIB 1 }
vacmMIBConformance  OBJECT IDENTIFIER ::= { snmpVacmMIB 2 }

-- Information about Local Contexts **********************************

vacmContextTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF VacmContextEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The table of locally available contexts.

                 This table provides information to SNMP Command
                 Generator applications so that they can properly
                 configure the vacmAccessTable to control access to
                 all contexts at the SNMP entity.

                 This table may change dynamically if the SNMP entity
                 allows that contexts are added/deleted dynamically
                 (for instance when its configuration changes). Such
                 changes would happen only if the management
                 instrumentation at that SNMP entity recognizes more
                 (or fewer) contexts.

                 The presence of entries in this table and of entries
                 in the vacmAccessTable are independent.  That is, a
                 context identified by an entry in this table is not
                 necessarily referenced by any entries in the
                 vacmAccessTable; and the context(s) referenced by an
                 entry in the vacmAccessTable does not necessarily
                 currently exist and thus need not be identified by an
                 entry in this table.

                 This table must be made accessible via the default
                 context so that Command Responder applications have
                 a standard way of retrieving the information.

                 This table is read-only. It cannot be configured via
                 SNMP.
                "
    ::= { vacmMIBObjects 1 }

vacmContextEntry OBJECT-TYPE
    SYNTAX       VacmContextEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "Information about a particular context."
    INDEX       {
                  vacmContextName
                }
    ::= { vacmContextTable 1 }

VacmContextEntry ::= SEQUENCE
    {
        vacmContextName SnmpAdminString
    }

vacmContextName  OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   read-only
    STATUS       current
    DESCRIPTION "A human readable name identifying a particular
                 context at a particular SNMP entity.

                 The empty contextName (zero length) represents the
                 default context.
                "
    ::= { vacmContextEntry 1 }

-- Information about Groups ******************************************

vacmSecurityToGroupTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF VacmSecurityToGroupEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "This table maps a combination of securityModel and
                 securityName into a groupName which is used to define
                 an access control policy for a group of principals.
                "
    ::= { vacmMIBObjects 2 }

vacmSecurityToGroupEntry OBJECT-TYPE
    SYNTAX       VacmSecurityToGroupEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "An entry in this table maps the combination of a
                 securityModel and securityName into a groupName.
                "
    INDEX       {
                  vacmSecurityModel,
                  vacmSecurityName
                }
    ::= { vacmSecurityToGroupTable 1 }

VacmSecurityToGroupEntry ::= SEQUENCE
    {
        vacmSecurityModel               SnmpSecurityModel,
        vacmSecurityName                SnmpAdminString,
        vacmGroupName                   SnmpAdminString,
        vacmSecurityToGroupStorageType  StorageType,
        vacmSecurityToGroupStatus       RowStatus
    }

vacmSecurityModel OBJECT-TYPE
    SYNTAX       SnmpSecurityModel(1..2147483647)
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The Security Model, by which the vacmSecurityName
                 referenced by this entry is provided.

                 Note, this object may not take the 'any' (0) value.
                "
    ::= { vacmSecurityToGroupEntry 1 }

vacmSecurityName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(1..32))
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The securityName for the principal, represented in a
                 Security Model independent format, which is mapped by
                 this entry to a groupName.
                "
    ::= { vacmSecurityToGroupEntry 2 }

vacmGroupName    OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(1..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The name of the group to which this entry (e.g., the
                 combination of securityModel and securityName)
                 belongs.

                 This groupName is used as index into the
                 vacmAccessTable to select an access control policy.
                 However, a value in this table does not imply that an
                 instance with the value exists in table vacmAccesTable.
                "
    ::= { vacmSecurityToGroupEntry 3 }

vacmSecurityToGroupStorageType OBJECT-TYPE
    SYNTAX       StorageType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The storage type for this conceptual row.
                 Conceptual rows having the value 'permanent' need not
                 allow write-access to any columnar objects in the row.
                "
    DEFVAL      { nonVolatile }
    ::= { vacmSecurityToGroupEntry 4 }

vacmSecurityToGroupStatus OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The status of this conceptual row.

                 Until instances of all corresponding columns are
                 appropriately configured, the value of the
                 corresponding instance of the vacmSecurityToGroupStatus
                 column is 'notReady'.

                 In particular, a newly created row cannot be made
                 active until a value has been set for vacmGroupName.

                 The  RowStatus TC [RFC2579] requires that this
                 DESCRIPTION clause states under which circumstances
                 other objects in this row can be modified:

                 The value of this object has no effect on whether
                 other objects in this conceptual row can be modified.
                "
    ::= { vacmSecurityToGroupEntry 5 }

-- Information about Access Rights ***********************************

vacmAccessTable  OBJECT-TYPE
    SYNTAX       SEQUENCE OF VacmAccessEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The table of access rights for groups.

                 Each entry is indexed by a groupName, a contextPrefix,
                 a securityModel and a securityLevel.  To determine
                 whether access is allowed, one entry from this table
                 needs to be selected and the proper viewName from that
                 entry must be used for access control checking.

                 To select the proper entry, follow these steps:

                 1) the set of possible matches is formed by the
                    intersection of the following sets of entries:
                      the set of entries with identical vacmGroupName
                      the union of these two sets:
                       - the set with identical vacmAccessContextPrefix
                       - the set of entries with vacmAccessContextMatch
                         value of 'prefix' and matching
                         vacmAccessContextPrefix
                      intersected with the union of these two sets:
                       - the set of entries with identical
                         vacmSecurityModel
                       - the set of entries with vacmSecurityModel
                         value of 'any'
                      intersected with the set of entries with
                      vacmAccessSecurityLevel value less than or equal
                      to the requested securityLevel

                 2) if this set has only one member, we're done
                    otherwise, it comes down to deciding how to weight
                    the preferences between ContextPrefixes,
                    SecurityModels, and SecurityLevels as follows:
                    a) if the subset of entries with securityModel
                       matching the securityModel in the message is
                       not empty, then discard the rest.
                    b) if the subset of entries with
                       vacmAccessContextPrefix matching the contextName
                       in the message is not empty,
                       then discard the rest
                    c) discard all entries with ContextPrefixes shorter
                       than the longest one remaining in the set
                    d) select the entry with the highest securityLevel

                 Please note that for securityLevel noAuthNoPriv, all
                 groups are really equivalent since the assumption that
                 the securityName has been authenticated does not hold.
                "
    ::= { vacmMIBObjects 4 }

vacmAccessEntry  OBJECT-TYPE
    SYNTAX       VacmAccessEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "An access right configured in the Local Configuration
                 Datastore (LCD) authorizing access to an SNMP context.

                 Entries in this table can use an instance value for
                 object vacmGroupName even if no entry in table
                 vacmAccessSecurityToGroupTable has a corresponding
                 value for object vacmGroupName.
                "
    INDEX       { vacmGroupName,
                  vacmAccessContextPrefix,
                  vacmAccessSecurityModel,
                  vacmAccessSecurityLevel
                }
    ::= { vacmAccessTable 1 }

VacmAccessEntry ::= SEQUENCE
    {
        vacmAccessContextPrefix    SnmpAdminString,
        vacmAccessSecurityModel    SnmpSecurityModel,
        vacmAccessSecurityLevel    SnmpSecurityLevel,
        vacmAccessContextMatch     INTEGER,
        vacmAccessReadViewName     SnmpAdminString,
        vacmAccessWriteViewName    SnmpAdminString,
        vacmAccessNotifyViewName   SnmpAdminString,
        vacmAccessStorageType      StorageType,
        vacmAccessStatus           RowStatus
    }

vacmAccessContextPrefix OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "In order to gain the access rights allowed by this
                 conceptual row, a contextName must match exactly
                 (if the value of vacmAccessContextMatch is 'exact')
                 or partially (if the value of vacmAccessContextMatch
                 is 'prefix') to the value of the instance of this
                 object.
                "
    ::= { vacmAccessEntry 1 }

vacmAccessSecurityModel OBJECT-TYPE
    SYNTAX       SnmpSecurityModel
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "In order to gain the access rights allowed by this
                 conceptual row, this securityModel must be in use.
                "
    ::= { vacmAccessEntry 2 }

vacmAccessSecurityLevel OBJECT-TYPE
    SYNTAX       SnmpSecurityLevel
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The minimum level of security required in order to
                 gain the access rights allowed by this conceptual
                 row.  A securityLevel of noAuthNoPriv is less than
                 authNoPriv which in turn is less than authPriv.

                 If multiple entries are equally indexed except for
                 this vacmAccessSecurityLevel index, then the entry
                 which has the highest value for
                 vacmAccessSecurityLevel is selected.
                "
    ::= { vacmAccessEntry 3 }

vacmAccessContextMatch OBJECT-TYPE
    SYNTAX       INTEGER
                { exact (1), -- exact match of prefix and contextName
                  prefix (2) -- Only match to the prefix
                }
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "If the value of this object is exact(1), then all
                 rows where the contextName exactly matches
                 vacmAccessContextPrefix are selected.

                 If the value of this object is prefix(2), then all
                 rows where the contextName whose starting octets
                 exactly match vacmAccessContextPrefix are selected.
                 This allows for a simple form of wildcarding.
                "
    DEFVAL      { exact }
    ::= { vacmAccessEntry 4 }

vacmAccessReadViewName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The value of an instance of this object identifies
                 the MIB view of the SNMP context to which this
                 conceptual row authorizes read access.

                 The identified MIB view is that one for which the
                 vacmViewTreeFamilyViewName has the same value as the
                 instance of this object; if the value is the empty
                 string or if there is no active MIB view having this
                 value of vacmViewTreeFamilyViewName, then no access
                 is granted.
                "
    DEFVAL      { ''H }   -- the empty string
    ::= { vacmAccessEntry 5 }

vacmAccessWriteViewName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The value of an instance of this object identifies
                 the MIB view of the SNMP context to which this
                 conceptual row authorizes write access.

                 The identified MIB view is that one for which the
                 vacmViewTreeFamilyViewName has the same value as the
                 instance of this object; if the value is the empty
                 string or if there is no active MIB view having this
                 value of vacmViewTreeFamilyViewName, then no access
                 is granted.
                "
    DEFVAL      { ''H }   -- the empty string
    ::= { vacmAccessEntry 6 }

vacmAccessNotifyViewName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(0..32))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The value of an instance of this object identifies
                 the MIB view of the SNMP context to which this
                 conceptual row authorizes access for notifications.

                 The identified MIB view is that one for which the
                 vacmViewTreeFamilyViewName has the same value as the
                 instance of this object; if the value is the empty
                 string or if there is no active MIB view having this
                 value of vacmViewTreeFamilyViewName, then no access
                 is granted.
                "
    DEFVAL      { ''H }   -- the empty string
    ::= { vacmAccessEntry 7 }

vacmAccessStorageType OBJECT-TYPE
    SYNTAX       StorageType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The storage type for this conceptual row.

                 Conceptual rows having the value 'permanent' need not
                 allow write-access to any columnar objects in the row.
                "
    DEFVAL      { nonVolatile }
    ::= { vacmAccessEntry 8 }

vacmAccessStatus OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The status of this conceptual row.

                 The  RowStatus TC [RFC2579] requires that this
                 DESCRIPTION clause states under which circumstances
                 other objects in this row can be modified:

                 The value of this object has no effect on whether
                 other objects in this conceptual row can be modified.
                "
    ::= { vacmAccessEntry 9 }

-- Information about MIB views ***************************************

-- Support for instance-level granularity is optional.
--
-- In some implementations, instance-level access control
-- granularity may come at a high performance cost.  Managers
-- should avoid requesting such configurations unnecessarily.

vacmMIBViews     OBJECT IDENTIFIER ::= { vacmMIBObjects 5 }

vacmViewSpinLock OBJECT-TYPE
    SYNTAX       TestAndIncr
    MAX-ACCESS   read-write
    STATUS       current
    DESCRIPTION "An advisory lock used to allow cooperating SNMP
                 Command Generator applications to coordinate their
                 use of the Set operation in creating or modifying
                 views.

                 When creating a new view or altering an existing
                 view, it is important to understand the potential
                 interactions with other uses of the view.  The
                 vacmViewSpinLock should be retrieved.  The name of
                 the view to be created should be determined to be
                 unique by the SNMP Command Generator application by
                 consulting the vacmViewTreeFamilyTable.  Finally,
                 the named view may be created (Set), including the
                 advisory lock.
                 If another SNMP Command Generator application has
                 altered the views in the meantime, then the spin
                 lock's value will have changed, and so this creation
                 will fail because it will specify the wrong value for
                 the spin lock.

                 Since this is an advisory lock, the use of this lock
                 is not enforced.
                "
    ::= { vacmMIBViews 1 }

vacmViewTreeFamilyTable OBJECT-TYPE
    SYNTAX       SEQUENCE OF VacmViewTreeFamilyEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "Locally held information about families of subtrees
                 within MIB views.

                 Each MIB view is defined by two sets of view subtrees:
                   - the included view subtrees, and
                   - the excluded view subtrees.
                 Every such view subtree, both the included and the
                 excluded ones, is defined in this table.

                 To determine if a particular object instance is in
                 a particular MIB view, compare the object instance's
                 OBJECT IDENTIFIER with each of the MIB view's active
                 entries in this table.  If none match, then the
                 object instance is not in the MIB view.  If one or
                 more match, then the object instance is included in,
                 or excluded from, the MIB view according to the
                 value of vacmViewTreeFamilyType in the entry whose
                 value of vacmViewTreeFamilySubtree has the most
                 sub-identifiers.  If multiple entries match and have
                 the same number of sub-identifiers (when wildcarding
                 is specified with the value of vacmViewTreeFamilyMask),
                 then the lexicographically greatest instance of
                 vacmViewTreeFamilyType determines the inclusion or
                 exclusion.

                 An object instance's OBJECT IDENTIFIER X matches an
                 active entry in this table when the number of
                 sub-identifiers in X is at least as many as in the
                 value of vacmViewTreeFamilySubtree for the entry,
                 and each sub-identifier in the value of
                 vacmViewTreeFamilySubtree matches its corresponding
                 sub-identifier in X.  Two sub-identifiers match
                 either if the corresponding bit of the value of
                 vacmViewTreeFamilyMask for the entry is zero (the
                 'wild card' value), or if they are equal.

                 A 'family' of subtrees is the set of subtrees defined
                 by a particular combination of values of
                 vacmViewTreeFamilySubtree and vacmViewTreeFamilyMask.
                 In the case where no 'wild card' is defined in the
                 vacmViewTreeFamilyMask, the family of subtrees reduces
                 to a single subtree.

                 When creating or changing MIB views, an SNMP Command
                 Generator application should utilize the
                 vacmViewSpinLock to try to avoid collisions. See
                 DESCRIPTION clause of vacmViewSpinLock.

                 When creating MIB views, it is strongly advised that
                 first the 'excluded' vacmViewTreeFamilyEntries are
                 created and then the 'included' entries.

                 When deleting MIB views, it is strongly advised that
                 first the 'included' vacmViewTreeFamilyEntries are
                 deleted and then the 'excluded' entries.

                 If a create for an entry for instance-level access
                 control is received and the implementation does not
                 support instance-level granularity, then an
                 inconsistentName error must be returned.
                "
    ::= { vacmMIBViews 2 }

vacmViewTreeFamilyEntry OBJECT-TYPE
    SYNTAX       VacmViewTreeFamilyEntry
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "Information on a particular family of view subtrees
                 included in or excluded from a particular SNMP
                 context's MIB view.

                 Implementations must not restrict the number of
                 families of view subtrees for a given MIB view,
                 except as dictated by resource constraints on the
                 overall number of entries in the
                 vacmViewTreeFamilyTable.

                 If no conceptual rows exist in this table for a given
                 MIB view (viewName), that view may be thought of as
                 consisting of the empty set of view subtrees.
                "
    INDEX       { vacmViewTreeFamilyViewName,
                  vacmViewTreeFamilySubtree
                }
    ::= { vacmViewTreeFamilyTable 1 }

VacmViewTreeFamilyEntry ::= SEQUENCE
    {
        vacmViewTreeFamilyViewName     SnmpAdminString,
        vacmViewTreeFamilySubtree      OBJECT IDENTIFIER,
        vacmViewTreeFamilyMask         OCTET STRING,
        vacmViewTreeFamilyType         INTEGER,
        vacmViewTreeFamilyStorageType  StorageType,
        vacmViewTreeFamilyStatus       RowStatus
    }

vacmViewTreeFamilyViewName OBJECT-TYPE
    SYNTAX       SnmpAdminString (SIZE(1..32))
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The human readable name for a family of view subtrees.
                "
    ::= { vacmViewTreeFamilyEntry 1 }

vacmViewTreeFamilySubtree OBJECT-TYPE
    SYNTAX       OBJECT IDENTIFIER
    MAX-ACCESS   not-accessible
    STATUS       current
    DESCRIPTION "The MIB subtree which when combined with the
                 corresponding instance of vacmViewTreeFamilyMask
                 defines a family of view subtrees.
                "
    ::= { vacmViewTreeFamilyEntry 2 }

vacmViewTreeFamilyMask OBJECT-TYPE
    SYNTAX       OCTET STRING (SIZE (0..16))
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The bit mask which, in combination with the
                 corresponding instance of vacmViewTreeFamilySubtree,
                 defines a family of view subtrees.

                 Each bit of this bit mask corresponds to a
                 sub-identifier of vacmViewTreeFamilySubtree, with the
                 most significant bit of the i-th octet of this octet
                 string value (extended if necessary, see below)
                 corresponding to the (8*i - 7)-th sub-identifier, and
                 the least significant bit of the i-th octet of this
                 octet string corresponding to the (8*i)-th
                 sub-identifier, where i is in the range 1 through 16.

                 Each bit of this bit mask specifies whether or not
                 the corresponding sub-identifiers must match when
                 determining if an OBJECT IDENTIFIER is in this
                 family of view subtrees; a '1' indicates that an
                 exact match must occur; a '0' indicates 'wild card',
                 i.e., any sub-identifier value matches.

                 Thus, the OBJECT IDENTIFIER X of an object instance
                 is contained in a family of view subtrees if, for
                 each sub-identifier of the value of
                 vacmViewTreeFamilySubtree, either:

                   the i-th bit of vacmViewTreeFamilyMask is 0, or

                   the i-th sub-identifier of X is equal to the i-th
                   sub-identifier of the value of
                   vacmViewTreeFamilySubtree.

                 If the value of this bit mask is M bits long and
                 there are more than M sub-identifiers in the
                 corresponding instance of vacmViewTreeFamilySubtree,
                 then the bit mask is extended with 1's to be the
                 required length.

                 Note that when the value of this object is the
                 zero-length string, this extension rule results in
                 a mask of all-1's being used (i.e., no 'wild card'),
                 and the family of view subtrees is the one view
                 subtree uniquely identified by the corresponding
                 instance of vacmViewTreeFamilySubtree.

                 Note that masks of length greater than zero length
                 do not need to be supported. In this case this
                 object is made read-only.
                "
    DEFVAL      { ''H }
    ::= { vacmViewTreeFamilyEntry 3 }

vacmViewTreeFamilyType OBJECT-TYPE
    SYNTAX       INTEGER  { included(1), excluded(2) }
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "Indicates whether the corresponding instances of
                 vacmViewTreeFamilySubtree and vacmViewTreeFamilyMask
                 define a family of view subtrees which is included in
                 or excluded from the MIB view.
                "
    DEFVAL      { included }
    ::= { vacmViewTreeFamilyEntry 4 }

vacmViewTreeFamilyStorageType OBJECT-TYPE
    SYNTAX       StorageType
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The storage type for this conceptual row.

                 Conceptual rows having the value 'permanent' need not
                 allow write-access to any columnar objects in the row.
                "
    DEFVAL      { nonVolatile }
    ::= { vacmViewTreeFamilyEntry 5 }

vacmViewTreeFamilyStatus OBJECT-TYPE
    SYNTAX       RowStatus
    MAX-ACCESS   read-create
    STATUS       current
    DESCRIPTION "The status of this conceptual row.

                 The  RowStatus TC [RFC2579] requires that this
                 DESCRIPTION clause states under which circumstances
                 other objects in this row can be modified:

                 The value of this object has no effect on whether
                 other objects in this conceptual row can be modified.
                "
    ::= { vacmViewTreeFamilyEntry 6 }

-- Conformance information *******************************************

vacmMIBCompliances  OBJECT IDENTIFIER ::= { vacmMIBConformance 1 }
vacmMIBGroups       OBJECT IDENTIFIER ::= { vacmMIBConformance 2 }

-- Compliance statements *********************************************

vacmMIBCompliance MODULE-COMPLIANCE
    STATUS       current
    DESCRIPTION "The compliance statement for SNMP engines which
                 implement the SNMP View-based Access Control Model
                 configuration MIB.
                "
    MODULE -- this module
        MANDATORY-GROUPS { vacmBasicGroup }

        OBJECT        vacmAccessContextMatch
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmAccessReadViewName
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmAccessWriteViewName
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmAccessNotifyViewName
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmAccessStorageType
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmAccessStatus
        MIN-ACCESS    read-only
        DESCRIPTION  "Create/delete/modify access to the
                      vacmAccessTable is not required.
                     "

        OBJECT        vacmViewTreeFamilyMask
        WRITE-SYNTAX  OCTET STRING (SIZE (0))
        MIN-ACCESS    read-only
        DESCRIPTION  "Support for configuration via SNMP of subtree
                      families using wild-cards is not required.
                     "

        OBJECT        vacmViewTreeFamilyType
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmViewTreeFamilyStorageType
        MIN-ACCESS    read-only
        DESCRIPTION  "Write access is not required."

        OBJECT        vacmViewTreeFamilyStatus
        MIN-ACCESS    read-only
        DESCRIPTION  "Create/delete/modify access to the
                      vacmViewTreeFamilyTable is not required.
                     "
    ::= { vacmMIBCompliances 1 }

-- Units of conformance **********************************************

vacmBasicGroup OBJECT-GROUP
    OBJECTS {
              vacmContextName,
              vacmGroupName,
              vacmSecurityToGroupStorageType,
              vacmSecurityToGroupStatus,
              vacmAccessContextMatch,
              vacmAccessReadViewName,
              vacmAccessWriteViewName,
              vacmAccessNotifyViewName,
              vacmAccessStorageType,
              vacmAccessStatus,
              vacmViewSpinLock,
              vacmViewTreeFamilyMask,
              vacmViewTreeFamilyType,
              vacmViewTreeFamilyStorageType,
              vacmViewTreeFamilyStatus
            }
    STATUS       current
    DESCRIPTION "A collection of objects providing for remote
                 configuration of an SNMP engine which implements
                 the SNMP View-based Access Control Model.
                "
    ::= { vacmMIBGroups 1 }

END


SNMPv2-CONF DEFINITIONS ::= BEGIN

-- IMPORTS ObjectName, NotificationName, ObjectSyntax
--                                                FROM SNMPv2-SMI;

-- definitions for conformance groups

END


SNMPv2-MIB DEFINITIONS ::= BEGIN

IMPORTS
    NOTIFICATION-GROUP, OBJECT-GROUP, MODULE-COMPLIANCE
        FROM SNMPv2-CONF
    TimeStamp, TestAndIncr, DisplayString
        FROM SNMPv2-TC
    mib-2, snmpModules, Counter32, TimeTicks, NOTIFICATION-TYPE, OBJECT-TYPE,
    MODULE-IDENTITY
        FROM SNMPv2-SMI;

snmpMIB MODULE-IDENTITY
    LAST-UPDATED "9511090000Z"
    ORGANIZATION "IETF SNMPv2 Working Group"
    CONTACT-INFO
                 "Marshall T. Rose

          Postal: Dover Beach Consulting, Inc.
                  420 Whisman Court
                  Mountain View, CA  94043-2186
                  US

             Tel: +1 415 968 1052

          E-mail: mrose@dbc.mtview.ca.us"
    DESCRIPTION
        "The MIB module for SNMPv2 entities."
    REVISION     "9304010000Z"
    DESCRIPTION
        "The initial revision of this MIB module was published as
         RFC 1450."
    ::= { snmpModules  1 }

snmpMIBObjects ::= { snmpMIB  1 }

system ::= { mib-2  1 }

sysDescr OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of the entity.  This value should
         include the full name and version identification of the
         system's hardware type, software operating-system, and
         networking software."
    ::= { system  1 }

sysObjectID OBJECT-TYPE
    SYNTAX     OBJECT IDENTIFIER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The vendor's authoritative identification of the network
         management subsystem contained in the entity.  This value is
         allocated within the SMI enterprises subtree (1.3.6.1.4.1)
         and provides an easy and unambiguous means for determining
         `what kind of box' is being managed.  For example, if vendor
         `Flintstones, Inc.' was assigned the subtree
         1.3.6.1.4.1.4242, it could assign the identifier
         1.3.6.1.4.1.4242.1.1 to its `Fred Router'."
    ::= { system  2 }

sysUpTime OBJECT-TYPE
    SYNTAX     TimeTicks
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The time (in hundredths of a second) since the network
         management portion of the system was last re-initialized."
    ::= { system  3 }

sysContact OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The textual identification of the contact person for this
         managed node, together with information on how to contact
         this person.  If no contact information is known, the value
         is the zero-length string."
    ::= { system  4 }

sysName OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "An administratively-assigned name for this managed node.
         By convention, this is the node's fully-qualified domain
         name.  If the name is unknown, the value is the zero-length
         string."
    ::= { system  5 }

sysLocation OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The physical location of this node (e.g., `telephone
         closet, 3rd floor').  If the location is unknown, the value
         is the zero-length string."
    ::= { system  6 }

sysServices OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A value which indicates the set of services that this
         entity may potentially offers.  The value is a sum.  This
         sum initially takes the value zero, Then, for each layer, L,
         in the range 1 through 7, that this node performs
         transactions for, 2 raised to (L - 1) is added to the sum.
         For example, a node which performs only routing functions
         would have a value of 4 (2^(3-1)).  In contrast, a node
         which is a host offering application services would have a
         value of 72 (2^(4-1) + 2^(7-1)).  Note that in the context
         of the Internet suite of protocols, values should be
         calculated accordingly:

              layer      functionality
                1        physical (e.g., repeaters)
                2        datalink/subnetwork (e.g., bridges)
                3        internet (e.g., supports the IP)
                4        end-to-end  (e.g., supports the TCP)
                7        applications (e.g., supports the SMTP)

         For systems including OSI protocols, layers 5 and 6 may also
         be counted."
    ::= { system  7 }

sysORLastChange OBJECT-TYPE
    SYNTAX     TimeStamp
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of sysUpTime at the time of the most recent
         change in state or value of any instance of sysORID."
    ::= { system  8 }

sysORTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF SysOREntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The (conceptual) table listing the capabilities of the
         local SNMPv2 entity acting in an agent role with respect to
         various MIB modules.  SNMPv2 entities having dynamically-
         configurable support of MIB modules will have a
         dynamically-varying number of conceptual rows."
    ::= { system  9 }

sysOREntry OBJECT-TYPE
    SYNTAX     SysOREntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "An entry (conceptual row) in the sysORTable."
    INDEX      { sysORIndex }
    ::= { sysORTable  1 }

SysOREntry ::=
    SEQUENCE {
        sysORIndex
            INTEGER,

        sysORID
            OBJECT IDENTIFIER,

        sysORDescr
            DisplayString,

        sysORUpTime
            TimeStamp
    }

sysORIndex OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "The auxiliary variable used for identifying instances of
         the columnar objects in the sysORTable."
    ::= { sysOREntry  1 }

sysORID OBJECT-TYPE
    SYNTAX     OBJECT IDENTIFIER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "An authoritative identification of a capabilities statement
         with respect to various MIB modules supported by the local
         SNMPv2 entity acting in an agent role."
    ::= { sysOREntry  2 }

sysORDescr OBJECT-TYPE
    SYNTAX     DisplayString
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "A textual description of the capabilities identified by the
         corresponding instance of sysORID."
    ::= { sysOREntry  3 }

sysORUpTime OBJECT-TYPE
    SYNTAX     TimeStamp
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The value of sysUpTime at the time this conceptual row was
         last instanciated."
    ::= { sysOREntry  4 }

snmp ::= { mib-2  11 }

snmpInPkts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of messages delivered to the SNMP entity
         from the transport service."
    ::= { snmp  1 }

snmpInBadVersions OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of SNMP messages which were delivered to
         the SNMP entity and were for an unsupported SNMP version."
    ::= { snmp  3 }

snmpInBadCommunityNames OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of SNMP messages delivered to the SNMP
         entity which used a SNMP community name not known to said
         entity."
    ::= { snmp  4 }

snmpInBadCommunityUses OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of SNMP messages delivered to the SNMP
         entity which represented an SNMP operation which was not
         allowed by the SNMP community named in the message."
    ::= { snmp  5 }

snmpInASNParseErrs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of ASN.1 or BER errors encountered by the
         SNMP entity when decoding received SNMP messages."
    ::= { snmp  6 }

snmpEnableAuthenTraps OBJECT-TYPE
    SYNTAX     INTEGER {
                 enabled(1),
                 disabled(2)
               }
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "Indicates whether the SNMP entity is permitted to generate
         authenticationFailure traps.  The value of this object
         overrides any configuration information; as such, it
         provides a means whereby all authenticationFailure traps may
         be disabled.

         Note that it is strongly recommended that this object be
         stored in non-volatile memory so that it remains constant
         across re-initializations of the network management system."
    ::= { snmp  30 }

snmpSilentDrops OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of GetRequest-PDUs, GetNextRequest-PDUs,
         GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs
         delivered to the SNMP entity which were silently dropped
         because the size of a reply containing an alternate
         Response-PDU with an empty variable-bindings field was
         greater than either a local constraint or the maximum
         message size associated with the originator of the request."
    ::= { snmp  31 }

snmpProxyDrops OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of GetRequest-PDUs, GetNextRequest-PDUs,
         GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs
         delivered to the SNMP entity which were silently dropped
         because the transmission of the (possibly translated)
         message to a proxy target failed in a manner (other than a
         time-out) such that no Response-PDU could be returned."
    ::= { snmp  32 }

snmpTrap ::= { snmpMIBObjects  4 }

snmpTrapOID OBJECT-TYPE
    SYNTAX     OBJECT IDENTIFIER
    MAX-ACCESS accessible-for-notify
    STATUS     current
    DESCRIPTION
        "The authoritative identification of the notification
         currently being sent.  This variable occurs as the second
         varbind in every SNMPv2-Trap-PDU and InformRequest-PDU."
    ::= { snmpTrap  1 }

snmpTrapEnterprise OBJECT-TYPE
    SYNTAX     OBJECT IDENTIFIER
    MAX-ACCESS accessible-for-notify
    STATUS     current
    DESCRIPTION
        "The authoritative identification of the enterprise
         associated with the trap currently being sent.  When a
         SNMPv2 proxy agent is mapping an RFC1157 Trap-PDU into a
         SNMPv2-Trap-PDU, this variable occurs as the last varbind."
    ::= { snmpTrap  3 }

snmpTraps ::= { snmpMIBObjects  5 }

coldStart NOTIFICATION-TYPE
    STATUS     current
    DESCRIPTION
        "A coldStart trap signifies that the SNMPv2 entity, acting
         in an agent role, is reinitializing itself and that its
         configuration may have been altered."
    ::= { snmpTraps  1 }

warmStart NOTIFICATION-TYPE
    STATUS     current
    DESCRIPTION
        "A warmStart trap signifies that the SNMPv2 entity, acting
         in an agent role, is reinitializing itself such that its
         configuration is unaltered."
    ::= { snmpTraps  2 }

authenticationFailure NOTIFICATION-TYPE
    STATUS     current
    DESCRIPTION
        "An authenticationFailure trap signifies that the SNMPv2
         entity, acting in an agent role, has received a protocol
         message that is not properly authenticated.  While all
         implementations of the SNMPv2 must be capable of generating
         this trap, the snmpEnableAuthenTraps object indicates
         whether this trap will be generated."
    ::= { snmpTraps  5 }

snmpSet ::= { snmpMIBObjects  6 }

snmpSetSerialNo OBJECT-TYPE
    SYNTAX     TestAndIncr
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "An advisory lock used to allow several cooperating SNMPv2
         entities, all acting in a manager role, to coordinate their
         use of the SNMPv2 set operation.

         This object is used for coarse-grain coordination.  To
         achieve fine-grain coordination, one or more similar objects
         might be defined within each MIB group, as appropriate."
    ::= { snmpSet  1 }

snmpMIBConformance ::= { snmpMIB  2 }

snmpMIBCompliances ::= { snmpMIBConformance  1 }

snmpMIBGroups ::= { snmpMIBConformance  2 }

snmpBasicCompliance MODULE-COMPLIANCE
    STATUS     current
    DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement the SNMPv2 MIB."

    MODULE           -- this module
    MANDATORY-GROUPS {
                             snmpGroup,
                             snmpSetGroup,
                             systemGroup,
                             snmpBasicNotificationsGroup
                           }
        GROUP        snmpCommunityGroup
        DESCRIPTION
        "This group is mandatory for SNMPv2 entities which
         support community-based authentication."
    ::= { snmpMIBCompliances  2 }

snmpGroup OBJECT-GROUP
    OBJECTS    {
                 snmpInPkts,
                 snmpInBadVersions,
                 snmpInASNParseErrs,
                 snmpSilentDrops,
                 snmpProxyDrops,
                 snmpEnableAuthenTraps
               }
    STATUS     current
    DESCRIPTION
        "A collection of objects providing basic instrumentation and
         control of an SNMPv2 entity."
    ::= { snmpMIBGroups  8 }

snmpCommunityGroup OBJECT-GROUP
    OBJECTS    { snmpInBadCommunityNames,  snmpInBadCommunityUses }
    STATUS     current
    DESCRIPTION
        "A collection of objects providing basic instrumentation of
         a SNMPv2 entity which supports community-based
         authentication."
    ::= { snmpMIBGroups  9 }

snmpSetGroup OBJECT-GROUP
    OBJECTS    { snmpSetSerialNo }
    STATUS     current
    DESCRIPTION
        "A collection of objects which allow several cooperating
         SNMPv2 entities, all acting in a manager role, to coordinate
         their use of the SNMPv2 set operation."
    ::= { snmpMIBGroups  5 }

systemGroup OBJECT-GROUP
    OBJECTS    {
                 sysDescr,
                 sysObjectID,
                 sysUpTime,
                 sysContact,
                 sysName,
                 sysLocation,
                 sysServices,
                 sysORLastChange,
                 sysORID,
                 sysORUpTime,
                 sysORDescr
               }
    STATUS     current
    DESCRIPTION
        "The system group defines objects which are common to all
         managed systems."
    ::= { snmpMIBGroups  6 }

-- snmpBasicNotificationsGroup NOTIFICATION-GROUP
--     OBJECTS    { coldStart,  authenticationFailure }
--     STATUS     current
--     DESCRIPTION
--         "The two notifications which an SNMPv2 entity is required to
--          implement."
--     ::= { snmpMIBGroups  7 }

snmpOutPkts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Messages which were
         passed from the SNMP protocol entity to the
         transport service."
    ::= { snmp  2 }

snmpInTooBigs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         delivered to the SNMP protocol entity and for
         which the value of the error-status field is
         `tooBig'."
    ::= { snmp  8 }

snmpInNoSuchNames OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         delivered to the SNMP protocol entity and for
         which the value of the error-status field is
         `noSuchName'."
    ::= { snmp  9 }

snmpInBadValues OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         delivered to the SNMP protocol entity and for
         which the value of the error-status field is
         `badValue'."
    ::= { snmp  10 }

snmpInReadOnlys OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number valid SNMP PDUs which were
         delivered to the SNMP protocol entity and for
         which the value of the error-status field is
         `readOnly'.  It should be noted that it is a
         protocol error to generate an SNMP PDU which
         contains the value `readOnly' in the error-status
         field, as such this object is provided as a means
         of detecting incorrect implementations of the
         SNMP."
    ::= { snmp  11 }

snmpInGenErrs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         delivered to the SNMP protocol entity and for
         which the value of the error-status field is
         `genErr'."
    ::= { snmp  12 }

snmpInTotalReqVars OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of MIB objects which have been
         retrieved successfully by the SNMP protocol entity
         as the result of receiving valid SNMP Get-Request
         and Get-Next PDUs."
    ::= { snmp  13 }

snmpInTotalSetVars OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of MIB objects which have been
         altered successfully by the SNMP protocol entity
         as the result of receiving valid SNMP Set-Request
         PDUs."
    ::= { snmp  14 }

snmpInGetRequests OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Request PDUs which
         have been accepted and processed by the SNMP
         protocol entity."
    ::= { snmp  15 }

snmpInGetNexts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Next PDUs which have
         been accepted and processed by the SNMP protocol
         entity."
    ::= { snmp  16 }

snmpInSetRequests OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Set-Request PDUs which
         have been accepted and processed by the SNMP
         protocol entity."
    ::= { snmp  17 }

snmpInGetResponses OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Response PDUs which
         have been accepted and processed by the SNMP
         protocol entity."
    ::= { snmp  18 }

snmpInTraps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Trap PDUs which have
         been accepted and processed by the SNMP protocol
         entity."
    ::= { snmp  19 }

snmpOutTooBigs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         generated by the SNMP protocol entity and for
         which the value of the error-status field is
         `tooBig.'"
    ::= { snmp  20 }

snmpOutNoSuchNames OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         generated by the SNMP protocol entity and for
         which the value of the error-status is
         `noSuchName'."
    ::= { snmp  21 }

snmpOutBadValues OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         generated by the SNMP protocol entity and for
         which the value of the error-status field is
         `badValue'."
    ::= { snmp  22 }

snmpOutGenErrs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP PDUs which were
         generated by the SNMP protocol entity and for
         which the value of the error-status field is
         `genErr'."
    ::= { snmp  24 }

snmpOutGetRequests OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Request PDUs which
         have been generated by the SNMP protocol entity."
    ::= { snmp  25 }

snmpOutGetNexts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Next PDUs which have
         been generated by the SNMP protocol entity."
    ::= { snmp  26 }

snmpOutSetRequests OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Set-Request PDUs which
         have been generated by the SNMP protocol entity."
    ::= { snmp  27 }

snmpOutGetResponses OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Get-Response PDUs which
         have been generated by the SNMP protocol entity."
    ::= { snmp  28 }

snmpOutTraps OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     obsolete
    DESCRIPTION
        "The total number of SNMP Trap PDUs which have
         been generated by the SNMP protocol entity."
    ::= { snmp  29 }

snmpObsoleteGroup OBJECT-GROUP
    OBJECTS    {
                 snmpOutPkts,
                 snmpInTooBigs,
                 snmpInNoSuchNames,
                 snmpInBadValues,
                 snmpInReadOnlys,
                 snmpInGenErrs,
                 snmpInTotalReqVars,
                 snmpInTotalSetVars,
                 snmpInGetRequests,
                 snmpInGetNexts,
                 snmpInSetRequests,
                 snmpInGetResponses,
                 snmpInTraps,
                 snmpOutTooBigs,
                 snmpOutNoSuchNames,
                 snmpOutBadValues,
                 snmpOutGenErrs,
                 snmpOutGetRequests,
                 snmpOutGetNexts,
                 snmpOutSetRequests,
                 snmpOutGetResponses,
                 snmpOutTraps
               }
    STATUS     obsolete
    DESCRIPTION
        "A collection of objects from RFC 1213 made obsolete by this
         MIB."
    ::= { snmpMIBGroups  10 }

END


SNMPv2-SMI DEFINITIONS ::= BEGIN

-- the path to the root

org            OBJECT IDENTIFIER ::= { iso 3 }  --  "iso" = 1
dod            OBJECT IDENTIFIER ::= { org 6 }
internet       OBJECT IDENTIFIER ::= { dod 1 }

directory      OBJECT IDENTIFIER ::= { internet 1 }

mgmt           OBJECT IDENTIFIER ::= { internet 2 }
mib-2          OBJECT IDENTIFIER ::= { mgmt 1 }
transmission   OBJECT IDENTIFIER ::= { mib-2 10 }

experimental   OBJECT IDENTIFIER ::= { internet 3 }

private        OBJECT IDENTIFIER ::= { internet 4 }
enterprises    OBJECT IDENTIFIER ::= { private 1 }

security       OBJECT IDENTIFIER ::= { internet 5 }

snmpV2         OBJECT IDENTIFIER ::= { internet 6 }

-- transport domains
snmpDomains    OBJECT IDENTIFIER ::= { snmpV2 1 }

-- transport proxies
snmpProxys     OBJECT IDENTIFIER ::= { snmpV2 2 }

-- module identities
snmpModules    OBJECT IDENTIFIER ::= { snmpV2 3 }

-- Extended UTCTime, to allow dates with four-digit years
-- (Note that this definition of ExtUTCTime is not to be IMPORTed
--  by MIB modules.)
ExtUTCTime ::= OCTET STRING(SIZE(11 | 13))
    -- format is YYMMDDHHMMZ or YYYYMMDDHHMMZ
    --   where: YY   - last two digits of year (only years
    --                 between 1900-1999)
    --          YYYY - last four digits of the year (any year)
    --          MM   - month (01 through 12)
    --          DD   - day of month (01 through 31)
    --          HH   - hours (00 through 23)
    --          MM   - minutes (00 through 59)
    --          Z    - denotes GMT (the ASCII character Z)
    --
    -- For example, "9502192015Z" and "199502192015Z" represent
    -- 8:15pm GMT on 19 February 1995. Years after 1999 must use
    -- the four digit year format. Years 1900-1999 may use the
    -- two or four digit format.

-- definitions for information modules

-- names of objects
-- (Note that these definitions of ObjectName and NotificationName
--  are not to be IMPORTed by MIB modules.)

-- syntax of objects

-- the "base types" defined here are:
--   3 built-in ASN.1 types: INTEGER, OCTET STRING, OBJECT IDENTIFIER
--   8 application-defined types: Integer32, IpAddress, Counter32,
--              Gauge32, Unsigned32, TimeTicks, Opaque, and Counter64

-- definitions of administrative identifiers

zeroDotZero    OBJECT-IDENTITY
    STATUS     current
    DESCRIPTION
            "A value used for null identifiers."
    ::= { 0 0 }

END


SNMPv2-TC DEFINITIONS ::= BEGIN

IMPORTS
    TimeTicks         FROM SNMPv2-SMI;

-- definition of textual conventions

DisplayString ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "255a"
    STATUS       current
    DESCRIPTION
            "Represents textual information taken from the NVT ASCII
            character set, as defined in pages 4, 10-11 of RFC 854.

            To summarize RFC 854, the NVT ASCII repertoire specifies:

              - the use of character codes 0-127 (decimal)

              - the graphics characters (32-126) are interpreted as
                US ASCII

              - NUL, LF, CR, BEL, BS, HT, VT and FF have the special
                meanings specified in RFC 854

              - the other 25 codes have no standard interpretation

              - the sequence 'CR LF' means newline

              - the sequence 'CR NUL' means carriage-return

              - an 'LF' not preceded by a 'CR' means moving to the
                same column on the next line.

              - the sequence 'CR x' for any x other than LF or NUL is
                illegal.  (Note that this also means that a string may
                end with either 'CR LF' or 'CR NUL', but not with CR.)

            Any object defined using this syntax may not exceed 255
            characters in length."
    SYNTAX       OCTET STRING (SIZE (0..255))

PhysAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "1x:"
    STATUS       current
    DESCRIPTION
            "Represents media- or physical-level addresses."
    SYNTAX       OCTET STRING

MacAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "1x:"
    STATUS       current
    DESCRIPTION
            "Represents an 802 MAC address represented in the
            `canonical' order defined by IEEE 802.1a, i.e., as if it
            were transmitted least significant bit first, even though
            802.5 (in contrast to other 802.x protocols) requires MAC
            addresses to be transmitted most significant bit first."
    SYNTAX       OCTET STRING (SIZE (6))

TruthValue ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents a boolean value."
    SYNTAX       INTEGER { true(1), false(2) }

TestAndIncr ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents integer-valued information used for atomic
            operations.  When the management protocol is used to specify
            that an object instance having this syntax is to be
            modified, the new value supplied via the management protocol
            must precisely match the value presently held by the
            instance.  If not, the management protocol set operation
            fails with an error of `inconsistentValue'.  Otherwise, if
            the current value is the maximum value of 2^31-1 (2147483647
            decimal), then the value held by the instance is wrapped to
            zero; otherwise, the value held by the instance is
            incremented by one.  (Note that regardless of whether the
            management protocol set operation succeeds, the variable-
            binding in the request and response PDUs are identical.)

            The value of the ACCESS clause for objects having this
            syntax is either `read-write' or `read-create'.  When an
            instance of a columnar object having this syntax is created,
            any value may be supplied via the management protocol.

            When the network management portion of the system is re-
            initialized, the value of every object instance having this
            syntax must either be incremented from its value prior to
            the re-initialization, or (if the value prior to the re-
            initialization is unknown) be set to a pseudo-randomly
            generated value."
    SYNTAX       INTEGER (0..2147483647)

AutonomousType ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents an independently extensible type identification
            value.  It may, for example, indicate a particular sub-tree
            with further MIB definitions, or define a particular type of
            protocol or hardware."
    SYNTAX       OBJECT IDENTIFIER

InstancePointer ::= TEXTUAL-CONVENTION
    STATUS       obsolete
    DESCRIPTION
            "A pointer to either a specific instance of a MIB object or
            a conceptual row of a MIB table in the managed device.  In
            the latter case, by convention, it is the name of the
            particular instance of the first accessible columnar object
            in the conceptual row.

            The two uses of this textual convention are replaced by
            VariablePointer and RowPointer, respectively."
    SYNTAX       OBJECT IDENTIFIER

VariablePointer ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "A pointer to a specific object instance.  For example,
            sysContact.0 or ifInOctets.3."
    SYNTAX       OBJECT IDENTIFIER

RowPointer ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents a pointer to a conceptual row.  The value is the
            name of the instance of the first accessible columnar object
            in the conceptual row.

            For example, ifIndex.3 would point to the 3rd row in the
            ifTable (note that if ifIndex were not-accessible, then
            ifDescr.3 would be used instead)."
    SYNTAX       OBJECT IDENTIFIER

RowStatus ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "The RowStatus textual convention is used to manage the
            creation and deletion of conceptual rows, and is used as the
            value of the SYNTAX clause for the status column of a
            conceptual row (as described in Section 7.7.1 of [2].)

            The status column has six defined values:

                 - `active', which indicates that the conceptual row is
                 available for use by the managed device;

                 - `notInService', which indicates that the conceptual
                 row exists in the agent, but is unavailable for use by
                 the managed device (see NOTE below); 'notInService' has
                 no implication regarding the internal consistency of
                 the row, availability of resources, or consistency with
                 the current state of the managed device;

                 - `notReady', which indicates that the conceptual row
                 exists in the agent, but is missing information
                 necessary in order to be available for use by the
                 managed device (i.e., one or more required columns in
                 the conceptual row have not been instanciated);

                 - `createAndGo', which is supplied by a management
                 station wishing to create a new instance of a
                 conceptual row and to have its status automatically set
                 to active, making it available for use by the managed
                 device;

                 - `createAndWait', which is supplied by a management
                 station wishing to create a new instance of a
                 conceptual row (but not make it available for use by
                 the managed device); and,

                 - `destroy', which is supplied by a management station
                 wishing to delete all of the instances associated with
                 an existing conceptual row.

            Whereas five of the six values (all except `notReady') may
            be specified in a management protocol set operation, only
            three values will be returned in response to a management
            protocol retrieval operation:  `notReady', `notInService' or
            `active'.  That is, when queried, an existing conceptual row
            has only three states:  it is either available for use by
            the managed device (the status column has value `active');
            it is not available for use by the managed device, though
            the agent has sufficient information to attempt to make it
            so (the status column has value `notInService'); or, it is
            not available for use by the managed device, and an attempt
            to make it so would fail because the agent has insufficient
            information (the state column has value `notReady').

                                     NOTE WELL

                 This textual convention may be used for a MIB table,
                 irrespective of whether the values of that table's
                 conceptual rows are able to be modified while it is
                 active, or whether its conceptual rows must be taken
                 out of service in order to be modified.  That is, it is
                 the responsibility of the DESCRIPTION clause of the
                 status column to specify whether the status column must
                 not be `active' in order for the value of some other
                 column of the same conceptual row to be modified.  If
                 such a specification is made, affected columns may be
                 changed by an SNMP set PDU if the RowStatus would not
                 be equal to `active' either immediately before or after
                 processing the PDU.  In other words, if the PDU also
                 contained a varbind that would change the RowStatus
                 value, the column in question may be changed if the
                 RowStatus was not equal to `active' as the PDU was
                 received, or if the varbind sets the status to a value
                 other than 'active'.

            Also note that whenever any elements of a row exist, the
            RowStatus column must also exist.

            To summarize the effect of having a conceptual row with a
            status column having a SYNTAX clause value of RowStatus,
            consider the following state diagram:

                                         STATE
              +--------------+-----------+-------------+-------------
              |      A       |     B     |      C      |      D
              |              |status col.|status column|
              |status column |    is     |      is     |status column
    ACTION    |does not exist|  notReady | notInService|  is active
--------------+--------------+-----------+-------------+-------------
set status    |noError    ->D|inconsist- |inconsistent-|inconsistent-
column to     |       or     |   entValue|        Value|        Value
createAndGo   |inconsistent- |           |             |
              |         Value|           |             |
--------------+--------------+-----------+-------------+-------------
set status    |noError  see 1|inconsist- |inconsistent-|inconsistent-
column to     |       or     |   entValue|        Value|        Value
createAndWait |wrongValue    |           |             |
--------------+--------------+-----------+-------------+-------------
set status    |inconsistent- |inconsist- |noError      |noError
column to     |         Value|   entValue|             |
active        |              |           |             |
              |              |     or    |             |
              |              |           |             |
              |              |see 2   ->D|see 8     ->D|          ->D
--------------+--------------+-----------+-------------+-------------
set status    |inconsistent- |inconsist- |noError      |noError   ->C
column to     |         Value|   entValue|             |
notInService  |              |           |             |
              |              |     or    |             |      or
              |              |           |             |
              |              |see 3   ->C|          ->C|see 6
--------------+--------------+-----------+-------------+-------------
set status    |noError       |noError    |noError      |noError   ->A
column to     |              |           |             |      or
destroy       |           ->A|        ->A|          ->A|see 7
--------------+--------------+-----------+-------------+-------------
set any other |see 4         |noError    |noError      |see 5
column to some|              |           |             |
value         |              |      see 1|          ->C|          ->D
--------------+--------------+-----------+-------------+-------------

            (1) goto B or C, depending on information available to the
            agent.

            (2) if other variable bindings included in the same PDU,
            provide values for all columns which are missing but
            required, and all columns have acceptable values, then
            return noError and goto D.

            (3) if other variable bindings included in the same PDU,
            provide legal values for all columns which are missing but
            required, then return noError and goto C.

            (4) at the discretion of the agent, the return value may be
            either:

                 inconsistentName:  because the agent does not choose to
                 create such an instance when the corresponding
                 RowStatus instance does not exist, or

                 inconsistentValue:  if the supplied value is
                 inconsistent with the state of some other MIB object's
                 value, or

                 noError: because the agent chooses to create the
                 instance.

            If noError is returned, then the instance of the status
            column must also be created, and the new state is B or C,
            depending on the information available to the agent.  If
            inconsistentName or inconsistentValue is returned, the row
            remains in state A.

            (5) depending on the MIB definition for the column/table,
            either noError or inconsistentValue may be returned.

            (6) the return value can indicate one of the following
            errors:

                 wrongValue: because the agent does not support
                 notInService (e.g., an agent which does not support
                 createAndWait), or

                 inconsistentValue: because the agent is unable to take
                 the row out of service at this time, perhaps because it
                 is in use and cannot be de-activated.

            (7) the return value can indicate the following error:

                 inconsistentValue: because the agent is unable to
                 remove the row at this time, perhaps because it is in
                 use and cannot be de-activated.

            (8) the transition to D can fail, e.g., if the values of the
            conceptual row are inconsistent, then the error code would
            be inconsistentValue.

            NOTE: Other processing of (this and other varbinds of) the
            set request may result in a response other than noError
            being returned, e.g., wrongValue, noCreation, etc.

                              Conceptual Row Creation

            There are four potential interactions when creating a
            conceptual row:  selecting an instance-identifier which is
            not in use; creating the conceptual row; initializing any
            objects for which the agent does not supply a default; and,
            making the conceptual row available for use by the managed
            device.

            Interaction 1: Selecting an Instance-Identifier

            The algorithm used to select an instance-identifier varies
            for each conceptual row.  In some cases, the instance-
            identifier is semantically significant, e.g., the
            destination address of a route, and a management station
            selects the instance-identifier according to the semantics.

            In other cases, the instance-identifier is used solely to
            distinguish conceptual rows, and a management station
            without specific knowledge of the conceptual row might
            examine the instances present in order to determine an
            unused instance-identifier.  (This approach may be used, but
            it is often highly sub-optimal; however, it is also a
            questionable practice for a naive management station to
            attempt conceptual row creation.)

            Alternately, the MIB module which defines the conceptual row
            might provide one or more objects which provide assistance
            in determining an unused instance-identifier.  For example,
            if the conceptual row is indexed by an integer-value, then
            an object having an integer-valued SYNTAX clause might be
            defined for such a purpose, allowing a management station to
            issue a management protocol retrieval operation.  In order
            to avoid unnecessary collisions between competing management
            stations, `adjacent' retrievals of this object should be
            different.

            Finally, the management station could select a pseudo-random
            number to use as the index.  In the event that this index
            was already in use and an inconsistentValue was returned in
            response to the management protocol set operation, the
            management station should simply select a new pseudo-random
            number and retry the operation.

            A MIB designer should choose between the two latter
            algorithms based on the size of the table (and therefore the
            efficiency of each algorithm).  For tables in which a large
            number of entries are expected, it is recommended that a MIB
            object be defined that returns an acceptable index for
            creation.  For tables with small numbers of entries, it is
            recommended that the latter pseudo-random index mechanism be
            used.

            Interaction 2: Creating the Conceptual Row

            Once an unused instance-identifier has been selected, the
            management station determines if it wishes to create and
            activate the conceptual row in one transaction or in a
            negotiated set of interactions.

            Interaction 2a: Creating and Activating the Conceptual Row

            The management station must first determine the column
            requirements, i.e., it must determine those columns for
            which it must or must not provide values.  Depending on the
            complexity of the table and the management station's
            knowledge of the agent's capabilities, this determination
            can be made locally by the management station.  Alternately,
            the management station issues a management protocol get
            operation to examine all columns in the conceptual row that
            it wishes to create.  In response, for each column, there
            are three possible outcomes:

                 - a value is returned, indicating that some other
                 management station has already created this conceptual
                 row.  We return to interaction 1.

                 - the exception `noSuchInstance' is returned,
                 indicating that the agent implements the object-type
                 associated with this column, and that this column in at
                 least one conceptual row would be accessible in the MIB
                 view used by the retrieval were it to exist. For those
                 columns to which the agent provides read-create access,
                 the `noSuchInstance' exception tells the management
                 station that it should supply a value for this column
                 when the conceptual row is to be created.

                 - the exception `noSuchObject' is returned, indicating
                 that the agent does not implement the object-type
                 associated with this column or that there is no
                 conceptual row for which this column would be
                 accessible in the MIB view used by the retrieval.  As
                 such, the management station can not issue any
                 management protocol set operations to create an
                 instance of this column.

            Once the column requirements have been determined, a
            management protocol set operation is accordingly issued.
            This operation also sets the new instance of the status
            column to `createAndGo'.

            When the agent processes the set operation, it verifies that
            it has sufficient information to make the conceptual row
            available for use by the managed device.  The information
            available to the agent is provided by two sources:  the
            management protocol set operation which creates the
            conceptual row, and, implementation-specific defaults
            supplied by the agent (note that an agent must provide
            implementation-specific defaults for at least those objects
            which it implements as read-only).  If there is sufficient
            information available, then the conceptual row is created, a
            `noError' response is returned, the status column is set to
            `active', and no further interactions are necessary (i.e.,
            interactions 3 and 4 are skipped).  If there is insufficient
            information, then the conceptual row is not created, and the
            set operation fails with an error of `inconsistentValue'.
            On this error, the management station can issue a management
            protocol retrieval operation to determine if this was
            because it failed to specify a value for a required column,
            or, because the selected instance of the status column
            already existed.  In the latter case, we return to
            interaction 1.  In the former case, the management station
            can re-issue the set operation with the additional
            information, or begin interaction 2 again using
            `createAndWait' in order to negotiate creation of the
            conceptual row.

                                     NOTE WELL

                 Regardless of the method used to determine the column
                 requirements, it is possible that the management
                 station might deem a column necessary when, in fact,
                 the agent will not allow that particular columnar
                 instance to be created or written.  In this case, the
                 management protocol set operation will fail with an
                 error such as `noCreation' or `notWritable'.  In this
                 case, the management station decides whether it needs
                 to be able to set a value for that particular columnar
                 instance.  If not, the management station re-issues the
                 management protocol set operation, but without setting
                 a value for that particular columnar instance;
                 otherwise, the management station aborts the row
                 creation algorithm.

            Interaction 2b: Negotiating the Creation of the Conceptual
            Row

            The management station issues a management protocol set
            operation which sets the desired instance of the status
            column to `createAndWait'.  If the agent is unwilling to
            process a request of this sort, the set operation fails with
            an error of `wrongValue'.  (As a consequence, such an agent
            must be prepared to accept a single management protocol set
            operation, i.e., interaction 2a above, containing all of the
            columns indicated by its column requirements.)  Otherwise,
            the conceptual row is created, a `noError' response is
            returned, and the status column is immediately set to either
            `notInService' or `notReady', depending on whether it has
            sufficient information to (attempt to) make the conceptual
            row available for use by the managed device.  If there is
            sufficient information available, then the status column is
            set to `notInService'; otherwise, if there is insufficient
            information, then the status column is set to `notReady'.
            Regardless, we proceed to interaction 3.

            Interaction 3: Initializing non-defaulted Objects

            The management station must now determine the column
            requirements.  It issues a management protocol get operation
            to examine all columns in the created conceptual row.  In
            the response, for each column, there are three possible
            outcomes:

                 - a value is returned, indicating that the agent
                 implements the object-type associated with this column
                 and had sufficient information to provide a value.  For
                 those columns to which the agent provides read-create
                 access (and for which the agent allows their values to
                 be changed after their creation), a value return tells
                 the management station that it may issue additional
                 management protocol set operations, if it desires, in
                 order to change the value associated with this column.

                 - the exception `noSuchInstance' is returned,
                 indicating that the agent implements the object-type
                 associated with this column, and that this column in at
                 least one conceptual row would be accessible in the MIB
                 view used by the retrieval were it to exist. However,
                 the agent does not have sufficient information to
                 provide a value, and until a value is provided, the
                 conceptual row may not be made available for use by the
                 managed device.  For those columns to which the agent
                 provides read-create access, the `noSuchInstance'
                 exception tells the management station that it must
                 issue additional management protocol set operations, in
                 order to provide a value associated with this column.

                 - the exception `noSuchObject' is returned, indicating
                 that the agent does not implement the object-type
                 associated with this column or that there is no
                 conceptual row for which this column would be
                 accessible in the MIB view used by the retrieval.  As
                 such, the management station can not issue any
                 management protocol set operations to create an
                 instance of this column.

            If the value associated with the status column is
            `notReady', then the management station must first deal with
            all `noSuchInstance' columns, if any.  Having done so, the
            value of the status column becomes `notInService', and we
            proceed to interaction 4.

            Interaction 4: Making the Conceptual Row Available

            Once the management station is satisfied with the values
            associated with the columns of the conceptual row, it issues
            a management protocol set operation to set the status column
            to `active'.  If the agent has sufficient information to
            make the conceptual row available for use by the managed
            device, the management protocol set operation succeeds (a
            `noError' response is returned).  Otherwise, the management
            protocol set operation fails with an error of
            `inconsistentValue'.

                                     NOTE WELL

                 A conceptual row having a status column with value
                 `notInService' or `notReady' is unavailable to the
                 managed device.  As such, it is possible for the
                 managed device to create its own instances during the
                 time between the management protocol set operation
                 which sets the status column to `createAndWait' and the
                 management protocol set operation which sets the status
                 column to `active'.  In this case, when the management
                 protocol set operation is issued to set the status
                 column to `active', the values held in the agent
                 supersede those used by the managed device.

            If the management station is prevented from setting the
            status column to `active' (e.g., due to management station
            or network failure) the conceptual row will be left in the
            `notInService' or `notReady' state, consuming resources
            indefinitely.  The agent must detect conceptual rows that
            have been in either state for an abnormally long period of
            time and remove them.  It is the responsibility of the
            DESCRIPTION clause of the status column to indicate what an
            abnormally long period of time would be.  This period of
            time should be long enough to allow for human response time
            (including `think time') between the creation of the
            conceptual row and the setting of the status to `active'.
            In the absence of such information in the DESCRIPTION
            clause, it is suggested that this period be approximately 5
            minutes in length.  This removal action applies not only to
            newly-created rows, but also to previously active rows which
            are set to, and left in, the notInService state for a
            prolonged period exceeding that which is considered normal
            for such a conceptual row.

                             Conceptual Row Suspension

            When a conceptual row is `active', the management station
            may issue a management protocol set operation which sets the
            instance of the status column to `notInService'.  If the
            agent is unwilling to do so, the set operation fails with an
            error of `wrongValue' or `inconsistentValue'.  Otherwise,
            the conceptual row is taken out of service, and a `noError'
            response is returned.  It is the responsibility of the
            DESCRIPTION clause of the status column to indicate under
            what circumstances the status column should be taken out of
            service (e.g., in order for the value of some other column
            of the same conceptual row to be modified).

                              Conceptual Row Deletion

            For deletion of conceptual rows, a management protocol set
            operation is issued which sets the instance of the status
            column to `destroy'.  This request may be made regardless of
            the current value of the status column (e.g., it is possible
            to delete conceptual rows which are either `notReady',
            `notInService' or `active'.)  If the operation succeeds,
            then all instances associated with the conceptual row are
            immediately removed."
    SYNTAX       INTEGER {
                     -- the following two values are states:
                     -- these values may be read or written
                     active(1),
                     notInService(2),

                     -- the following value is a state:
                     -- this value may be read, but not written
                     notReady(3),

                     -- the following three values are
                     -- actions: these values may be written,
                     --   but are never read
                     createAndGo(4),
                     createAndWait(5),
                     destroy(6)
                 }

TimeStamp ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "The value of the sysUpTime object at which a specific
            occurrence happened.  The specific occurrence must be
            defined in the description of any object defined using this
            type.

            If sysUpTime is reset to zero as a result of a re-
            initialization of the network management (sub)system, then
            the values of all TimeStamp objects are also reset.
            However, after approximately 497 days without a re-
            initialization, the sysUpTime object will reach 2^^32-1 and
            then increment around to zero; in this case, existing values
            of TimeStamp objects do not change.  This can lead to
            ambiguities in the value of TimeStamp objects."
    SYNTAX       TimeTicks

TimeInterval ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "A period of time, measured in units of 0.01 seconds."
    SYNTAX       INTEGER (0..2147483647)

DateAndTime ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
    STATUS       current
    DESCRIPTION
            "A date-time specification.

            field  octets  contents                  range
            -----  ------  --------                  -----
              1      1-2   year*                     0..65536
              2       3    month                     1..12
              3       4    day                       1..31
              4       5    hour                      0..23
              5       6    minutes                   0..59
              6       7    seconds                   0..60
                           (use 60 for leap-second)
              7       8    deci-seconds              0..9
              8       9    direction from UTC        '+' / '-'
              9      10    hours from UTC*           0..13
             10      11    minutes from UTC          0..59

            * Notes:
            - the value of year is in network-byte order
            - daylight saving time in New Zealand is +13

            For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
            displayed as:

                             1992-5-26,13:30:15.0,-4:0

            Note that if only local time is known, then timezone
            information (fields 8-10) is not present."
    SYNTAX       OCTET STRING (SIZE (8 | 11))

StorageType ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Describes the memory realization of a conceptual row.  A
            row which is volatile(2) is lost upon reboot.  A row which
            is either nonVolatile(3), permanent(4) or readOnly(5), is
            backed up by stable storage.  A row which is permanent(4)
            can be changed but not deleted.  A row which is readOnly(5)
            cannot be changed nor deleted.

            If the value of an object with this syntax is either
            permanent(4) or readOnly(5), it cannot be written.
            Conversely, if the value is either other(1), volatile(2) or
            nonVolatile(3), it cannot be modified to be permanent(4) or
            readOnly(5).  (All illegal modifications result in a
            'wrongValue' error.)

            Every usage of this textual convention is required to
            specify the columnar objects which a permanent(4) row must
            at a minimum allow to be writable."
    SYNTAX       INTEGER {
                     other(1),       -- eh?
                     volatile(2),    -- e.g., in RAM
                     nonVolatile(3), -- e.g., in NVRAM
                     permanent(4),   -- e.g., partially in ROM
                     readOnly(5)     -- e.g., completely in ROM
                 }

TDomain ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
          "Denotes a kind of transport service.

          Some possible values, such as snmpUDPDomain, are defined in
          the SNMPv2-TM MIB module.  Other possible values are defined
          in other MIB modules."
    REFERENCE    "The SNMPv2-TM MIB module is defined in RFC 1906."
    SYNTAX       OBJECT IDENTIFIER

TAddress ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
          "Denotes a transport service address.

          A TAddress value is always interpreted within the context of a
          TDomain value.  Thus, each definition of a TDomain value must
          be accompanied by a definition of a textual convention for use
          with that TDomain.  Some possible textual conventions, such as
          SnmpUDPAddress for snmpUDPDomain, are defined in the SNMPv2-TM
          MIB module.  Other possible textual conventions are defined in
          other MIB modules."
    REFERENCE    "The SNMPv2-TM MIB module is defined in RFC 1906."
    SYNTAX       OCTET STRING (SIZE (1..255))

END


SNMPv2-TM DEFINITIONS ::= BEGIN

IMPORTS
    TEXTUAL-CONVENTION
        FROM SNMPv2-TC
    snmpProxys, snmpDomains, OBJECT-IDENTITY
        FROM SNMPv2-SMI;

snmpUDPDomain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The SNMPv2 over UDP transport domain.  The corresponding
         transport address is of type SnmpUDPAddress."
    ::= { snmpDomains  1 }

SnmpUDPAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "1d.1d.1d.1d/2d"
    STATUS       current
    DESCRIPTION
        "Represents a UDP address:

            octets   contents        encoding
             1-4     IP-address      network-byte order
             5-6     UDP-port        network-byte order
         "
    SYNTAX       OCTET STRING

snmpCLNSDomain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The SNMPv2 over CLNS transport domain.  The corresponding
         transport address is of type SnmpOSIAddress."
    ::= { snmpDomains  2 }

snmpCONSDomain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The SNMPv2 over CONS transport domain.  The corresponding
         transport address is of type SnmpOSIAddress."
    ::= { snmpDomains  3 }

SnmpOSIAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "*1x:/1x:"
    STATUS       current
    DESCRIPTION
        "Represents an OSI transport-address:

            octets   contents           encoding
               1     length of NSAP     'n' as an unsigned-integer
                                           (either 0 or from 3 to 20)
            2..(n+1) NSAP                concrete binary representation
            (n+2)..m TSEL                string of (up to 64) octets
         "
    SYNTAX       OCTET STRING

snmpDDPDomain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The SNMPv2 over DDP transport domain.  The corresponding
         transport address is of type SnmpNBPAddress."
    ::= { snmpDomains  4 }

SnmpNBPAddress ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
        "Represents an NBP name:

              octets        contents          encoding
                 1          length of object  'n' as an unsigned integer
               2..(n+1)     object            string of (up to 32) octets
                n+2         length of type    'p' as an unsigned integer
           (n+3)..(n+2+p)   type              string of (up to 32) octets
               n+3+p        length of zone    'q' as an unsigned integer
         (n+4+p)..(n+3+p+q) zone              string of (up to 32) octets

         For comparison purposes, strings are case-insensitive All
         strings may contain any octet other than 255 (hex ff)."
    SYNTAX       OCTET STRING

snmpIPXDomain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The SNMPv2 over IPX transport domain.  The corresponding
         transport address is of type SnmpIPXAddress."
    ::= { snmpDomains  5 }

SnmpIPXAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "4x.1x:1x:1x:1x:1x:1x.2d"
    STATUS       current
    DESCRIPTION
        "Represents an IPX address:

            octets   contents            encoding
             1-4     network-number      network-byte order
             5-10    physical-address    network-byte order
            11-12    socket-number       network-byte order
         "
    SYNTAX       OCTET STRING

rfc1157Proxy ::= { snmpProxys  1 }

rfc1157Domain OBJECT-IDENTITY
    STATUS       current
    DESCRIPTION
        "The transport domain for SNMPv1 over UDP.  The
         corresponding transport address is of type SnmpUDPAddress."
    ::= { rfc1157Proxy  1 }

END


TCP-MIB DEFINITIONS ::= BEGIN

IMPORTS
    OBJECT-GROUP, MODULE-COMPLIANCE
        FROM SNMPv2-CONF
    mib-2, IpAddress, Counter32, Gauge32, Integer32, OBJECT-TYPE, MODULE-IDENTITY
        FROM SNMPv2-SMI;

tcpMIB MODULE-IDENTITY
    LAST-UPDATED "9411010000Z"
    ORGANIZATION "IETF SNMPv2 Working Group"
    CONTACT-INFO
                 "Keith McCloghrie

          Postal: Cisco Systems, Inc.
                  170 West Tasman Drive
                  San Jose, CA  95134-1706
                  US

          Phone:  +1 408 526 5260
          Email:  kzm@cisco.com"
    DESCRIPTION
        "The MIB module for managing TCP implementations."
    REVISION     "9103310000Z"
    DESCRIPTION
        "The initial revision of this MIB module was part of MIB-
         II."
    ::= { mib-2  49 }

tcp OBJECT IDENTIFIER ::= { mib-2  6 }

tcpRtoAlgorithm OBJECT-TYPE
    SYNTAX     INTEGER {
                 other(1),
                 constant(2),
                 rsre(3),
                 vanj(4)
               }
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The algorithm used to determine the timeout value used for
         retransmitting unacknowledged octets."
    ::= { tcp  1 }

tcpRtoMin OBJECT-TYPE
    SYNTAX     Integer32
    UNITS      "milliseconds"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The minimum value permitted by a TCP implementation for the
         retransmission timeout, measured in milliseconds.  More
         refined semantics for objects of this type depend upon the
         algorithm used to determine the retransmission timeout.  In
         particular, when the timeout algorithm is rsre(3), an object
         of this type has the semantics of the LBOUND quantity
         described in RFC 793."
    ::= { tcp  2 }

tcpRtoMax OBJECT-TYPE
    SYNTAX     Integer32
    UNITS      "milliseconds"
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The maximum value permitted by a TCP implementation for the

         retransmission timeout, measured in milliseconds.  More
         refined semantics for objects of this type depend upon the
         algorithm used to determine the retransmission timeout.  In
         particular, when the timeout algorithm is rsre(3), an object
         of this type has the semantics of the UBOUND quantity
         described in RFC 793."
    ::= { tcp  3 }

tcpMaxConn OBJECT-TYPE
    SYNTAX     Integer32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The limit on the total number of TCP connections the entity
         can support.  In entities where the maximum number of
         connections is dynamic, this object should contain the value
         -1."
    ::= { tcp  4 }

tcpActiveOpens OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of times TCP connections have made a direct
         transition to the SYN-SENT state from the CLOSED state."
    ::= { tcp  5 }

tcpPassiveOpens OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of times TCP connections have made a direct
         transition to the SYN-RCVD state from the LISTEN state."
    ::= { tcp  6 }

tcpAttemptFails OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of times TCP connections have made a direct
         transition to the CLOSED state from either the SYN-SENT
         state or the SYN-RCVD state, plus the number of times TCP
         connections have made a direct transition to the LISTEN
         state from the SYN-RCVD state."
    ::= { tcp  7 }

tcpEstabResets OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of times TCP connections have made a direct
         transition to the CLOSED state from either the ESTABLISHED
         state or the CLOSE-WAIT state."
    ::= { tcp  8 }

tcpCurrEstab OBJECT-TYPE
    SYNTAX     Gauge32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of TCP connections for which the current state
         is either ESTABLISHED or CLOSE- WAIT."
    ::= { tcp  9 }

tcpInSegs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of segments received, including those
         received in error.  This count includes segments received on
         currently established connections."
    ::= { tcp  10 }

tcpOutSegs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of segments sent, including those on
         current connections but excluding those containing only
         retransmitted octets."
    ::= { tcp  11 }

tcpRetransSegs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of segments retransmitted - that is, the
         number of TCP segments transmitted containing one or more
         previously transmitted octets."
    ::= { tcp  12 }

tcpConnTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF TcpConnEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A table containing TCP connection-specific information."
    ::= { tcp  13 }

tcpConnEntry OBJECT-TYPE
    SYNTAX     TcpConnEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A conceptual row of the tcpConnTable containing information
         about a particular current TCP connection.  Each row of this
         table is transient, in that it ceases to exist when (or soon
         after) the connection makes the transition to the CLOSED
         state."
    INDEX      {
                 tcpConnLocalAddress,
                 tcpConnLocalPort,
                 tcpConnRemAddress,
                 tcpConnRemPort
               }
    ::= { tcpConnTable  1 }

TcpConnEntry ::=
    SEQUENCE {
        tcpConnState
            INTEGER,

        tcpConnLocalAddress
            IpAddress,

        tcpConnLocalPort
            INTEGER,

        tcpConnRemAddress
            IpAddress,

        tcpConnRemPort
            INTEGER
    }

tcpConnState OBJECT-TYPE
    SYNTAX     INTEGER {
                 closed(1),
                 listen(2),
                 synSent(3),
                 synReceived(4),
                 established(5),
                 finWait1(6),
                 finWait2(7),
                 closeWait(8),
                 lastAck(9),
                 closing(10),
                 timeWait(11),
                 deleteTCB(12)
               }
    MAX-ACCESS read-write
    STATUS     current
    DESCRIPTION
        "The state of this TCP connection.

         The only value which may be set by a management station is
         deleteTCB(12).  Accordingly, it is appropriate for an agent
         to return a `badValue' response if a management station
         attempts to set this object to any other value.

         If a management station sets this object to the value
         deleteTCB(12), then this has the effect of deleting the TCB
         (as defined in RFC 793) of the corresponding connection on
         the managed node, resulting in immediate termination of the
         connection.

         As an implementation-specific option, a RST segment may be
         sent from the managed node to the other TCP endpoint (note
         however that RST segments are not sent reliably)."
    ::= { tcpConnEntry  1 }

tcpConnLocalAddress OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The local IP address for this TCP connection.  In the case
         of a connection in the listen state which is willing to
         accept connections for any IP interface associated with the
         node, the value 0.0.0.0 is used."
    ::= { tcpConnEntry  2 }

tcpConnLocalPort OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The local port number for this TCP connection."
    ::= { tcpConnEntry  3 }

tcpConnRemAddress OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The remote IP address for this TCP connection."
    ::= { tcpConnEntry  4 }

tcpConnRemPort OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The remote port number for this TCP connection."
    ::= { tcpConnEntry  5 }

tcpInErrs OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of segments received in error (e.g., bad
         TCP checksums)."
    ::= { tcp  14 }

tcpOutRsts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of TCP segments sent containing the RST flag."
    ::= { tcp  15 }

tcpMIBConformance ::= { tcpMIB  2 }

tcpMIBCompliances ::= { tcpMIBConformance  1 }

tcpMIBGroups ::= { tcpMIBConformance  2 }

tcpMIBCompliance MODULE-COMPLIANCE
    STATUS     current
    DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement TCP."

    MODULE           -- this module
    MANDATORY-GROUPS { tcpGroup }
    ::= { tcpMIBCompliances  1 }

tcpGroup OBJECT-GROUP
    OBJECTS    {
                 tcpRtoAlgorithm,
                 tcpRtoMin,
                 tcpRtoMax,
                 tcpMaxConn,
                 tcpActiveOpens,
                 tcpPassiveOpens,
                 tcpAttemptFails,
                 tcpEstabResets,
                 tcpCurrEstab,
                 tcpInSegs,
                 tcpOutSegs,
                 tcpRetransSegs,
                 tcpConnState,
                 tcpConnLocalAddress,
                 tcpConnLocalPort,
                 tcpConnRemAddress,
                 tcpConnRemPort,
                 tcpInErrs,
                 tcpOutRsts
               }
    STATUS     current
    DESCRIPTION
        "The tcp group of objects providing for management of TCP
         entities."
    ::= { tcpMIBGroups  1 }

END


UCD-DEMO-MIB DEFINITIONS ::= BEGIN

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, Integer32	FROM SNMPv2-SMI
    ucdavis					FROM UCD-SNMP-MIB;

ucdDemoMIB MODULE-IDENTITY
    LAST-UPDATED "9912090000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
    "The ucd-snmp-coders mailing list is the best place to
     write for public questions about the ucd-snmp
     project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

     Primary Author: Wes Hardaker

     postal:     IT-DCAS
                     UCDavis
                 Davis CA  95616
         phone:      +1 530 754-7571
         email:      wjhardaker@ucdavis.edu"
    DESCRIPTION
    "The UCD-SNMP Demonstration MIB."
    REVISION	 "9912090000Z"
    DESCRIPTION
    "SMIv2 version converted from older MIB definitions."
    ::= { ucdavis 14 }

ucdDemoMIBObjects OBJECT IDENTIFIER ::= { ucdDemoMIB 1 }

ucdDemoPublic OBJECT IDENTIFIER ::= { ucdDemoMIBObjects 1 }

ucdDemoResetKeys OBJECT-TYPE
    SYNTAX	Integer32 (0..2147483647)
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "A set of value 1 to this object resets the
     demonstration user's auth and priv keys to the
     keys based on the P->Ku->Kul transformation of the
     value of the ucdDemoPasspharse object.

     Values other than 1 are ignored."
    ::= { ucdDemoPublic 1 }

ucdDemoPublicString OBJECT-TYPE
    SYNTAX	OCTET STRING (SIZE(0..1024))
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "A publicly settable string that can be set for testing
     snmpsets.  This value has no real usage other than
     testing purposes."
    ::= { ucdDemoPublic 2 }

ucdDemoUserList OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The list of users affected by the ucdDemoResetKeys object."
    ::= { ucdDemoPublic 3 }

ucdDemoPassphrase  OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The demo passphrase that ucdDemoResetKeys changes each
     users localized key to based on the P->Ku->Kul transformation."
    ::= { ucdDemoPublic 4 }

END


UCD-DISKIO-MIB DEFINITIONS ::= BEGIN

--
-- Derived from the original VEST-INTERNETT-MIB. Open issues:
--
-- (a) where to register this MIB?
-- (b) use not-accessible for diskIOIndex?
--

IMPORTS
    MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32
        FROM SNMPv2-SMI
    DisplayString
        FROM SNMPv2-TC
    ucdExperimental
        FROM UCD-SNMP-MIB;

ucdDiskIOMIB MODULE-IDENTITY
    LAST-UPDATED "200001260000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
        "The ucd-snmp-coders mailing list is the best place
         to write for public questions about the ucd-snmp
         project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

         Primary Contact: Wes Hardaker

         postal:    IT-DCAS
                    UCDavis
                    Davis CA  95616
         phone:     +1 530 754-7571
         email:     wjhardaker@ucdavis.edu"
    DESCRIPTION
        "This MIB module defines objects for disk IO statistics."
    REVISION     "200001260000Z"
    DESCRIPTION
        "SMIv2 version derived from older definitions contained
         in the VEST-INTERNETT-MIB module."
    ::= { ucdExperimental 15 }

diskIOTable OBJECT-TYPE
    SYNTAX      SEQUENCE OF DiskIOEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "Table of IO devices and how much data they have read/written."
    ::= { ucdDiskIOMIB 1 }

diskIOEntry OBJECT-TYPE
    SYNTAX      DiskIOEntry
    MAX-ACCESS  not-accessible
    STATUS      current
    DESCRIPTION
        "An entry containing a device and its statistics."
    INDEX       { diskIOIndex }
    ::= { diskIOTable 1 }

DiskIOEntry ::= SEQUENCE {
    diskIOIndex         Integer32,
    diskIODevice        DisplayString,
    diskIONRead         Counter32,
    diskIONWritten      Counter32,
    diskIOReads         Counter32,
    diskIOWrites        Counter32
}

diskIOIndex OBJECT-TYPE
    SYNTAX      Integer32 (0..65535)
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "Reference index for each observed device."
    ::= { diskIOEntry 1 }

diskIODevice OBJECT-TYPE
    SYNTAX      DisplayString
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The name of the device we are counting/checking."
    ::= { diskIOEntry 2 }

diskIONRead OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of bytes read from this device since boot."
    ::= { diskIOEntry 3 }

diskIONWritten OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of bytes written to this device since boot."
    ::= { diskIOEntry 4 }

diskIOReads OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of read accesses from this device since boot."
    ::= { diskIOEntry 5 }

diskIOWrites OBJECT-TYPE
    SYNTAX      Counter32
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION
        "The number of write accesses to this device since boot."
    ::= { diskIOEntry 6 }

END


UCD-DLMOD-MIB DEFINITIONS ::= BEGIN

-- Why do we have dlmodNextIndex if the dlmodTable is read-write?
-- What exactly is the dlmodName and dlmodPath?
-- Should there not be a timestamp associated with dlmodError?
-- What exactly do the dlmodStatus enumerations mean?

IMPORTS
    OBJECT-TYPE, MODULE-IDENTITY, Integer32	FROM SNMPv2-SMI
    DisplayString				FROM SNMPv2-TC
    ucdExperimental				FROM UCD-SNMP-MIB;

ucdDlmodMIB MODULE-IDENTITY
    LAST-UPDATED "9912100000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
        "The ucd-snmp-coders mailing list is the best place
     to write for public questions about the ucd-snmp
     project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

         Primary Author: Wes Hardaker

         postal:    IT-DCAS
                    UCDavis
                    Davis CA  95616
         phone:     +1 530 754-7571
         email:     wjhardaker@ucdavis.edu"
    DESCRIPTION
    "This file defines the MIB objects for dynamic
     loadable MIB modules."
    REVISION	 "9912100000Z"
    DESCRIPTION
    "SMIv2 version converted from older MIB definitions."
    ::= { ucdExperimental 14 }

dlmodNextIndex OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The index number of next appropiate unassigned entry
     in the dlmodTable."
    ::= { ucdDlmodMIB 1 }

dlmodTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF DlmodEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table of dlmodEntry."
    ::= { ucdDlmodMIB 2 }

dlmodEntry OBJECT-TYPE
    SYNTAX	DlmodEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "The parameters of dynamically loaded MIB module."
    INDEX	{ dlmodIndex }
    ::= { dlmodTable 1 }

DlmodEntry ::= SEQUENCE {
    dlmodIndex	Integer32,
    dlmodName	DisplayString,
    dlmodPath	DisplayString,
    dlmodError	DisplayString,
    dlmodStatus	INTEGER
}

dlmodIndex OBJECT-TYPE
    SYNTAX	Integer32 (1..65535)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "An index that uniqely indenties an entry in the dlmodTable."
    ::= { dlmodEntry 1 }

dlmodName OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "The module name."
    ::= { dlmodEntry 2 }

dlmodPath OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "The path of the module executable file."
    ::= { dlmodEntry 3 }

dlmodError OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The last error from dlmod_load_module."
    ::= { dlmodEntry 4 }

dlmodStatus OBJECT-TYPE
    SYNTAX	INTEGER {
            loaded(1),
            unloaded(2),
            error(3),
            load(4),
            unload(5),
            create(6),
            delete(7)
        }
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "The current status of the loaded module."
    ::= { dlmodEntry 5 }

END


UCD-IPFILTER-MIB DEFINITIONS ::= BEGIN

IMPORTS
    OBJECT-TYPE, MODULE-IDENTITY, Counter32, Integer32
    FROM SNMPv2-SMI
    ucdExperimental
    FROM UCD-SNMP-MIB;

ucdIpFilter MODULE-IDENTITY
    LAST-UPDATED "9912150000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
        "The ucd-snmp-coders mailing list is the best place
     to write for public questions about the ucd-snmp
     project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

         Primary Contact: Wes Hardaker

         postal:    IT-DCAS
                    UCDavis
                    Davis CA  95616
         phone:     +1 530 754-7571
         email:     wjhardaker@ucdavis.edu"
    DESCRIPTION
    "This module defines MIB components for reading information
     from the IP Filter. This would let you only read its rules
     and counters.

         IP Filter by Darren Reed <darrenr@pobox.com>
         IP Filter web page URL http://coombs.anu.edu.au/~avalon/
         ipf-mod.pl module by Yaroslav Terletsky <ts@polynet.lviv.ua>
         IP Filter UCD-SNMP module URL
         ftp://ftp.polynet.lviv.ua/pub/UNIX/security/ipf/ucd-snmp-ipf-mod.tgz
         Yaroslav Terletsky <ts@polynet.lviv.ua>"
    REVISION	 "9912150000Z"
    DESCRIPTION
    "SMIv2 version converted from an older MIB definition."
    ::= { ucdExperimental 2 }

ipfInTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF IpfInEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table with IP Filter incoming rules and statistics."
    ::= { ucdIpFilter 1 }

ipfInEntry OBJECT-TYPE
    SYNTAX	IpfInEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "IP Filter incoming rules table entry."
    INDEX	{ ipfInIndex }
    ::= { ipfInTable 1 }

IpfInEntry ::= SEQUENCE {
    ipfInIndex	Integer32,
    ipfInRule	OCTET STRING,
    ipfInHits	Counter32
}

ipfInIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference index for each incoming IP Filter rule."
    ::= { ipfInEntry 1 }

ipfInRule OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Textual representation of the incoming IP Filter rule."
    ::= { ipfInEntry 2 }

ipfInHits OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Hits of the incoming IP Filter rule."
    ::= { ipfInEntry 3 }

ipfOutTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF IpfOutEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table with IP Filter outgoing rules and statistic."
    ::= { ucdIpFilter 2 }

ipfOutEntry OBJECT-TYPE
    SYNTAX	IpfOutEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "IP Filter outgoing rules table entry."
    INDEX	{ ipfOutIndex }
    ::= { ipfOutTable 1 }

IpfOutEntry ::= SEQUENCE {
    ipfOutIndex	Integer32,
    ipfOutRule	OCTET STRING,
    ipfOutHits	Counter32
}

ipfOutIndex OBJECT-TYPE
    SYNTAX	Integer32 (1..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference index for each outgoing IP Filter rule."
    ::= { ipfOutEntry 1 }

ipfOutRule OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Textual representation of the outgoing IP Filter rule."
    ::= { ipfOutEntry 2 }

ipfOutHits OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Hits of the outgoing IP Filter rule."
    ::= { ipfOutEntry 3 }

ipfAccInTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF IpfAccInEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table with IP Filter incoming accounting rules
     and statistics."
    ::= { ucdIpFilter 3 }

ipfAccInEntry OBJECT-TYPE
    SYNTAX	IpfAccInEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "IP FIlter incoming accounting rules table entry."
    INDEX	{ ipfAccInIndex }
    ::= { ipfAccInTable 1 }

IpfAccInEntry ::= SEQUENCE {
    ipfAccInIndex	Integer32,
    ipfAccInRule	OCTET STRING,
    ipfAccInHits	Counter32,
    ipfAccInBytes	Counter32
}

ipfAccInIndex OBJECT-TYPE
    SYNTAX	Integer32 (1..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference index for each incoming accounting
     IP Filter rule."
    ::= { ipfAccInEntry 1 }

ipfAccInRule OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Textual representation of the incoming accounting
     IP Filter rule."
    ::= { ipfAccInEntry 2 }

ipfAccInHits OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Hits of the incoming accounting IP Filter rule."
    ::= { ipfAccInEntry 3 }

ipfAccInBytes OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Bytes passed thru the incoming accounting
     IP Filter rule."
    ::= { ipfAccInEntry 4 }

ipfAccOutTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF IpfAccOutEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table with IP Filter outgoing accounting rules
     and statistic."
    ::= { ucdIpFilter 4 }

ipfAccOutEntry OBJECT-TYPE
    SYNTAX	IpfAccOutEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "IP Filter outgoing accounting rules table entry."
    INDEX	{ ipfAccOutIndex }
    ::= { ipfAccOutTable 1 }

IpfAccOutEntry ::= SEQUENCE {
    ipfAccOutIndex	Integer32,
    ipfAccOutRule	OCTET STRING,
    ipfAccOutHits	Counter32,
    ipfAccOutBytes	Counter32
}

ipfAccOutIndex OBJECT-TYPE
    SYNTAX	Integer32 (1..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference index for each outgoing accounting
     IP Filter rule."
    ::= { ipfAccOutEntry 1 }

ipfAccOutRule OBJECT-TYPE
    SYNTAX	OCTET STRING
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Textual representation of the outgoing accounting
     IP Filter rule."
    ::= { ipfAccOutEntry 2 }

ipfAccOutHits OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Hits of the outgoing accounting IP Filter rule."
    ::= { ipfAccOutEntry 3 }

ipfAccOutBytes OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Bytes passed thru the outgoing accounting
     IP Filter rule."
    ::= { ipfAccOutEntry 4 }

END


UCD-IPFWACC-MIB DEFINITIONS ::= BEGIN

IMPORTS
    OBJECT-TYPE, MODULE-IDENTITY, IpAddress, Integer32, Counter32
    FROM SNMPv2-SMI
    DisplayString
    FROM SNMPv2-TC
    ucdExperimental
    FROM UCD-SNMP-MIB;

ucdIpFwAccMIB MODULE-IDENTITY
    LAST-UPDATED "9912160000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
     "The ucd-snmp-coders mailing list is the best place
      to write for public questions about the ucd-snmp
      project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

          Primary Author: Wes Hardaker

          postal:    IT-DCAS
                     UCDavis
                     Davis CA  95616
          phone:     +1 530 754-7571
          email:     wjhardaker@ucdavis.edu"
    DESCRIPTION
    "This module defines MIB components for reading information
         from the accounting rules IP Firewall. This would typically
         let you read the rules and the counters. I did not include
         some flags and fields that I considered irrelevant for the
         accounting rules. Resetting the counters of the rules by SNMP
         would be simple, but I don't consider it so useful. I gave no
         consideration to implementing write access for allowing
         modification of the accounting rules.

         Cristian.Estan@net.utcluj.ro "
    REVISION	 "9912160000Z"
    DESCRIPTION
    "SMIv2 version converted from an older MIB definition."
    ::= { ucdExperimental 1 }

ipFwAccTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF IpFwAccEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table with the accounting rules of the IP firewall"
    ::= { ucdIpFwAccMIB 1 }

ipFwAccEntry OBJECT-TYPE
    SYNTAX	IpFwAccEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "An accounting rule of the IP firewall"
    INDEX	{ ipFwAccIndex }
    ::= { ipFwAccTable 1 }

IpFwAccEntry ::= SEQUENCE {
    ipFwAccIndex	Integer32,
    ipFwAccSrcAddr	IpAddress,
    ipFwAccSrcNetMask	IpAddress,
    ipFwAccDstAddr	IpAddress,
    ipFwAccDstNetMask	IpAddress,
    ipFwAccViaName	DisplayString,
    ipFwAccViaAddr	IpAddress,
    ipFwAccProto	INTEGER,
    ipFwAccBidir	INTEGER,
    ipFwAccDir		INTEGER,
    ipFwAccBytes	Counter32,
    ipFwAccPackets	Counter32,
    ipFwAccNrSrcPorts	Integer32,
    ipFwAccNrDstPorts	Integer32,
    ipFwAccSrcIsRange	INTEGER,
    ipFwAccDstIsRange	INTEGER,
    ipFwAccPort1	Integer32,
    ipFwAccPort2	Integer32,
    ipFwAccPort3	Integer32,
    ipFwAccPort4	Integer32,
    ipFwAccPort5	Integer32,
    ipFwAccPort6	Integer32,
    ipFwAccPort7	Integer32,
    ipFwAccPort8	Integer32,
    ipFwAccPort9	Integer32,
    ipFwAccPort10	Integer32
}

ipFwAccIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference index for each firewall rule."
    ::= { ipFwAccEntry 1 }

ipFwAccSrcAddr OBJECT-TYPE
    SYNTAX	IpAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The source address in the firewall rule."
    ::= { ipFwAccEntry 2 }

ipFwAccSrcNetMask OBJECT-TYPE
    SYNTAX	IpAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The netmask of the source address in the firewall rule."
    ::= { ipFwAccEntry 3 }

ipFwAccDstAddr OBJECT-TYPE
    SYNTAX	IpAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The destination address in the firewall rule."
    ::= { ipFwAccEntry 4 }

ipFwAccDstNetMask OBJECT-TYPE
    SYNTAX	IpAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The netmask of the destination address in the firewall rule."
    ::= { ipFwAccEntry 5 }

ipFwAccViaName OBJECT-TYPE
    SYNTAX	DisplayString (SIZE(1..64))
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The name of the interface to which the rule applies. If no
     interface is associated with the present rule, this should
     contain a dash (-)."
    ::= { ipFwAccEntry 6 }

ipFwAccViaAddr OBJECT-TYPE
    SYNTAX	IpAddress
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The address of the interface to which the rule applies.
     Using this parameter makes sense when multiple addresses are
     associated to the same physical interface. If not defined
     for the current rule this should be set to 0."
    ::= { ipFwAccEntry 7 }

ipFwAccProto OBJECT-TYPE
    SYNTAX	INTEGER {
            other(1),
            all(2),
            tcp(3),
            udp(4),
            icmp(5)
        }
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The protocol(s) to which the rule applies."
    ::= { ipFwAccEntry 8 }

ipFwAccBidir OBJECT-TYPE
    SYNTAX	INTEGER {
            unidirectional(1),
            bidirectional(2)
        }
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Whether the rule works in both directions (i.e. with the
     source and destination parts swapped) or not."
    ::= { ipFwAccEntry 9 }

ipFwAccDir OBJECT-TYPE
    SYNTAX	INTEGER {
            both(1),
            in(2),
            out(3)
        }
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Whether the rule applies to packets entering or exiting the
     kernel."
    ::= { ipFwAccEntry 10 }

ipFwAccBytes OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of bytes that matched this rule since the last
     reset of the counters."
    ::= { ipFwAccEntry 11 }

ipFwAccPackets OBJECT-TYPE
    SYNTAX	Counter32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of packets that matched this rule since the last
     reset of the counters."
    ::= { ipFwAccEntry 12 }

ipFwAccNrSrcPorts OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of ports that refer to the source address."
    ::= { ipFwAccEntry 13 }

ipFwAccNrDstPorts OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of ports that refer to the destination address."
    ::= { ipFwAccEntry 14 }

ipFwAccSrcIsRange OBJECT-TYPE
    SYNTAX	INTEGER {
            srchasrange(1),
            srchasnorange(2)
        }
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Interpret the first two ports of the source part as
     the upper and lower limit of an interval or not."
    ::= { ipFwAccEntry 15 }

ipFwAccDstIsRange OBJECT-TYPE
    SYNTAX	INTEGER {
            dsthasrange(1),
            dsthasnorange(2)
        }
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Interpret the first two ports of the destination part as
     the upper and lower limit of an interval or not."
    ::= { ipFwAccEntry 16 }

ipFwAccPort1 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 1."
    ::= { ipFwAccEntry 17 }

ipFwAccPort2 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 2."
    ::= { ipFwAccEntry 18 }

ipFwAccPort3 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 3."
    ::= { ipFwAccEntry 19 }

ipFwAccPort4 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 4."
    ::= { ipFwAccEntry 20 }

ipFwAccPort5 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 5."
    ::= { ipFwAccEntry 21 }

ipFwAccPort6 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 6."
    ::= { ipFwAccEntry 22 }

ipFwAccPort7 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 7."
    ::= { ipFwAccEntry 23 }

ipFwAccPort8 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 8."
    ::= { ipFwAccEntry 24 }

ipFwAccPort9 OBJECT-TYPE
     SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 9."
    ::= { ipFwAccEntry 25 }

ipFwAccPort10 OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Port number 10."
    ::= { ipFwAccEntry 26 }

END


UCD-SNMP-MIB DEFINITIONS ::= BEGIN

-- Design notes:
--
-- The design of this mib may seem unusual in parts, as it was
-- designed for ease of numerical management routines.
--
-- In that light, most sub-sections of this mib have four common
-- numerical oid consistencies:
--
-- 2021.ID.1   : an integer index value.  In scalers, this is always
--               of value 1.  In tables it is a row index.
-- 2021.ID.2   : a name of the script, process, etc. that this row represents.
-- 2021.ID.100 : An error flag indicating if an error is present on
--               that row (a threshold value was crossed, etc).
-- 2021.ID.101 : An error string describing why the error flag is non-0.
--
-- These conventions enable managers to easy examine portions of the
-- mib by setting the ID to the sub-section they are interested in
-- monitoring, and then scanning the .100 value to check for an
-- error(s), and get a more specific error message from .101 for the
-- named check found in .2.
--
-- Row numbers between 2 and 100 are sub-section specific.
--
-- Mib sections utilizing the above conventions:
--   Tables:  	procTable, execTable, diskTable, loadTable
--   Scalers: 	memory, snmperrs

IMPORTS
    OBJECT-TYPE, NOTIFICATION-TYPE, MODULE-IDENTITY,
    Integer32, Opaque, enterprises
        FROM SNMPv2-SMI

    TEXTUAL-CONVENTION, DisplayString, TruthValue
    FROM SNMPv2-TC;

ucdavis MODULE-IDENTITY
    LAST-UPDATED "9912090000Z"
    ORGANIZATION "University of California, Davis"
    CONTACT-INFO
     "The ucd-snmp-coders mailing list is the best place
     to write for public questions about the ucd-snmp
     project: ucd-snmp-coders@ucd-snmp.ucdavis.edu

         Primary Author: Wes Hardaker

         postal:    IT-DCAS
                    UCDavis
                    Davis CA  95616
         phone:     +1 530 754-7571
         email:     wjhardaker@ucdavis.edu"
    DESCRIPTION
    "This file defines the private UCD SNMP MIB extensions."
    REVISION	 "9912090000Z"
    DESCRIPTION
    "SMIv2 version converted from older MIB definitions."
    ::= { enterprises 2021 }

-- Current UCD core mib table entries:
--   prTable          OBJECT IDENTIFIER ::= { ucdavis   2 }
--   memory           OBJECT IDENTIFIER ::= { ucdavis   4 }
--   extTable         OBJECT IDENTIFIER ::= { ucdavis   8 }
--   diskTable        OBJECT IDENTIFIER ::= { ucdavis   9 }
--   loadTable        OBJECT IDENTIFIER ::= { ucdavis  10 }
--   systemStats      OBJECT IDENTIFIER ::= { ucdavis  11 }
--   ucdDemoMIB       OBJECT IDENTIFIER ::= { ucdavis  14 } - UCD-DEMO-MIB
--   fileTable        OBJECT IDENTIFIER ::= { ucdavis  15 }
--   version          OBJECT IDENTIFIER ::= { ucdavis 100 }
--   snmperrs         OBJECT IDENTIFIER ::= { ucdavis 101 }
--   mibRegistryTable OBJECT IDENTIFIER ::= { ucdavis 102 }

-- Older mib table entries that were changed to new locations above:
--   processes        OBJECT IDENTIFIER ::= { ucdavis   1 }
--   exec             OBJECT IDENTIFIER ::= { ucdavis   3 }
--   disk             OBJECT IDENTIFIER ::= { ucdavis   6 }
--   load             OBJECT IDENTIFIER ::= { ucdavis   7 }

-- Never implemented and removed from the mib:
--   lockd            OBJECT IDENTIFIER ::= { ucdavis   5 }

-- Branches for registering other UCD MIB modules:
ucdInternal           OBJECT IDENTIFIER ::= { ucdavis 12 }
ucdExperimental       OBJECT IDENTIFIER ::= { ucdavis 13 }

-- OID values assigned in the ucdExperimental branch:
--   ucdIpFwAccMIB    OBJECT IDENTIFIER ::= { ucdExperimental  1 } - UCD-IPFWACC-MIB
--   ucdIpFilter      OBJECT IDENTIFIER ::= { ucdExperimental  2 } - UCD-IPFILTER-MIB
--   wavelan          OBJECT IDENTIFIER ::= { ucdExperimental  3 } - WL-MIB
--   ucdDlmodMIB      OBJECT IDENTIFIER ::= { ucdExperimental 14 } - UCD-DLMOD-MIB
--   ucdDiskIOMIB     OBJECT IDENTIFIER ::= { ucdExperimental 15 } - UCD-DISKIO-MIB

-- These are the returned values of the agent type.
-- returned to:  .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0

ucdSnmpAgent      OBJECT IDENTIFIER ::= { ucdavis 250 }
hpux9             OBJECT IDENTIFIER ::= { ucdSnmpAgent 1 }
hpux10            OBJECT IDENTIFIER ::= { ucdSnmpAgent 6 }
sunos4            OBJECT IDENTIFIER ::= { ucdSnmpAgent 2 }
solaris           OBJECT IDENTIFIER ::= { ucdSnmpAgent 3 }
osf               OBJECT IDENTIFIER ::= { ucdSnmpAgent 4 }
ultrix            OBJECT IDENTIFIER ::= { ucdSnmpAgent 5 }
netbsd1           OBJECT IDENTIFIER ::= { ucdSnmpAgent 7 }
freebsd           OBJECT IDENTIFIER ::= { ucdSnmpAgent 8 }
irix              OBJECT IDENTIFIER ::= { ucdSnmpAgent 9 }
linux             OBJECT IDENTIFIER ::= { ucdSnmpAgent 10 }
bsdi              OBJECT IDENTIFIER ::= { ucdSnmpAgent 11 }
openbsd           OBJECT IDENTIFIER ::= { ucdSnmpAgent 12 }
unknown           OBJECT IDENTIFIER ::= { ucdSnmpAgent 255 }

--
-- Define the Float Textual Convention
--   This definition was written by David Perkins.
--

Float ::= TEXTUAL-CONVENTION
    STATUS      current
    DESCRIPTION
        "A single precision floating-point number.  The semantics
         and encoding are identical for type 'single' defined in
         IEEE Standard for Binary Floating-Point,
         ANSI/IEEE Std 754-1985.
         The value is restricted to the BER serialization of
         the following ASN.1 type:
             FLOATTYPE ::= [120] IMPLICIT FloatType
         (note: the value 120 is the sum of '30'h and '48'h)
         The BER serialization of the length for values of
         this type must use the definite length, short
         encoding form.

         For example, the BER serialization of value 123
         of type FLOATTYPE is '9f780442f60000'h.  (The tag
         is '9f78'h; the length is '04'h; and the value is
         '42f60000'h.) The BER serialization of value
         '9f780442f60000'h of data type Opaque is
         '44079f780442f60000'h. (The tag is '44'h; the length
         is '07'h; and the value is '9f780442f60000'h."
    SYNTAX Opaque (SIZE (7))

--
-- Process table checks
--

prTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF PrEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table containing information on running
     programs/daemons configured for monitoring in the
     snmpd.conf file of the agent.  Processes violating the
     number of running processes required by the agent's
     configuration file are flagged with numerical and
     textual errors."
    ::= { ucdavis 2 }

prEntry OBJECT-TYPE
    SYNTAX	PrEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
        "An entry containing a process and its statistics."
    INDEX	{ prIndex }
    ::= { prTable  1 }

PrEntry ::= SEQUENCE {
    prIndex		Integer32,
    prNames		DisplayString,
    prMin		Integer32,
    prMax		Integer32,
    prCount		Integer32,
    prErrorFlag		Integer32,
    prErrMessage	DisplayString,
    prErrFix		Integer32,
    prErrFixCmd		DisplayString
}

prIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..65535)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference Index for each observed process."
    ::= { prEntry 1 }

prNames OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The process name we're counting/checking on."
    ::= { prEntry 2 }

prMin OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The minimum number of processes that should be
     running.  An error flag is generated if the number of
     running processes is < the minimum."
    ::= { prEntry 3 }

prMax OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The maximum number of processes that should be
     running.  An error flag is generated if the number of
     running processes is > the maximum."
    ::= { prEntry 4 }

prCount OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of current processes running with the name
     in question."
    ::= { prEntry 5 }

prErrorFlag OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "A Error flag to indicate trouble with a process.  It
     goes to 1 if there is an error, 0 if no error."
    ::= { prEntry 100 }

prErrMessage OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "An error message describing the problem (if one exists)."
    ::= { prEntry 101 }

prErrFix OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Setting this to one will try to fix the problem if
     the agent has been configured with a script to call
     to attempt to fix problems automatically using remote
     snmp operations."
    ::= { prEntry 102 }

prErrFixCmd OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The command that gets run when the prErrFix column is
     set to 1."
    ::= { prEntry 103 }

extTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF ExtEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table of extensible commands returning output and
     result codes.  These commands are configured via the
     agent's snmpd.conf file."
    ::= { ucdavis 8 }

extEntry OBJECT-TYPE
    SYNTAX     ExtEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "An entry containing an extensible script/program and its output."
    INDEX      { extIndex }
    ::= { extTable  1 }

ExtEntry ::= SEQUENCE {
    extIndex		Integer32,
    extNames		DisplayString,
    extCommand		DisplayString,
    extResult		Integer32,
    extOutput		DisplayString,
    extErrFix		Integer32,
    extErrFixCmd	DisplayString
}

extIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..65535)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference Index for extensible scripts.  Simply an
     integer row number."
    ::= { extEntry 1 }

extNames OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "A Short, one name description of the extensible command."
    ::= { extEntry 2 }

extCommand OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The command line to be executed."
    ::= { extEntry 3 }

extResult OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The result code (exit status) from the executed command."
    ::= { extEntry 100 }

extOutput OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The first line of output of the executed command."
    ::= { extEntry 101 }

extErrFix OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Setting this to one will try to fix the problem if
     the agent has been configured with a script to call
     to attempt to fix problems automatically using remote
     snmp operations."
    ::= { extEntry 102 }

extErrFixCmd OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The command that gets run when the extErrFix column is
     set to 1."
    ::= { extEntry 103 }

--
-- Memory usage/watch reporting.
-- Not supported on all systems!
-- See agent/mibgroup/ucd_snmp.h to see if its loaded for your architecture.
--
memory OBJECT IDENTIFIER ::= { ucdavis 4 }

memIndex OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Bogus Index.  This should always return the integer 0."
    ::= { memory 1 }

memErrorName OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Bogus Name. This should always return the string 'swap'."
    ::= { memory 2 }

memTotalSwap OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Swap Size configured for the host."
    ::= { memory 3 }

memAvailSwap OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Available Swap Space on the host."
    ::= { memory 4 }

memTotalReal OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Real/Physical Memory Size on the host."
    ::= { memory 5 }

memAvailReal OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Available Real/Physical Memory Space on the host."
    ::= { memory 6 }

memTotalSwapTXT OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total virtual memory used by text."
    ::= { memory 7 }

memAvailSwapTXT OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Active virtual memory used by text."
    ::= { memory 8 }

memTotalRealTXT OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Real/Physical Memory Size used by text."
    ::= { memory 9 }

memAvailRealTXT OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Active Real/Physical Memory Space used by text."
    ::= { memory 10 }

memTotalFree OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Available Memory on the host"
    ::= { memory 11 }

memMinimumSwap OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Minimum amount of free swap required to be free
     or else memErrorSwap is set to 1 and an error string is
     returned memSwapErrorMsg."
    ::= { memory 12 }

memShared OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Shared Memory"
    ::= { memory 13 }

memBuffer OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Buffered Memory"
    ::= { memory 14 }

memCached OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total Cached Memory"
    ::= { memory 15 }

memSwapError OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Error flag.  1 indicates very little swap space left"
    ::= { memory 100 }

memSwapErrorMsg OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Error message describing the Error Flag condition"
    ::= { memory 101 }

dskTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF DskEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "Disk watching information.  Partions to be watched
     are configured by the snmpd.conf file of the agent."
    ::= { ucdavis 9 }

dskEntry OBJECT-TYPE
    SYNTAX     DskEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "An entry containing a disk and its statistics."
    INDEX      { dskIndex }
    ::= { dskTable  1 }

DskEntry ::= SEQUENCE {
    dskIndex		Integer32,
    dskPath		DisplayString,
    dskDevice		DisplayString,
    dskMinimum		Integer32,
    dskMinPercent	Integer32,
    dskTotal		Integer32,
    dskAvail		Integer32,
    dskUsed		Integer32,
    dskPercent		Integer32,
    dskPercentNode	Integer32,
    dskErrorFlag	Integer32,
    dskErrorMsg		DisplayString
}

dskIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..65535)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Integer reference number (row number) for the disk mib."
    ::= { dskEntry 1 }

dskPath OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Path where the disk is mounted."
    ::= { dskEntry 2 }

dskDevice OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Path of the device for the partition"
    ::= { dskEntry 3 }

dskMinimum OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Minimum space required on the disk (in kBytes) before the
         errors are triggered.  Either this or dskMinPercent is
         configured via the agent's snmpd.conf file."
    ::= { dskEntry 4 }

dskMinPercent OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Percentage of minimum space required on the disk before the
         errors are triggered.  Either this or dskMinimum is
         configured via the agent's snmpd.conf file."
    ::= { dskEntry 5 }

dskTotal OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Total size of the disk/partion (kBytes)"
    ::= { dskEntry 6 }

dskAvail OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Available space on the disk"
    ::= { dskEntry 7 }

dskUsed OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Used space on the disk"
    ::= { dskEntry 8 }

dskPercent OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Percentage of space used on disk"
    ::= { dskEntry 9 }

dskPercentNode OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Percentage of inodes used on disk"
    ::= { dskEntry 10 }

dskErrorFlag OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Error flag signaling that the disk or partition is under
     the minimum required space configured for it."
    ::= { dskEntry 100 }

dskErrorMsg OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "A text description providing a warning and the space left
     on the disk."
    ::= { dskEntry 101 }

laTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF LaEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "Load average information."
    ::= { ucdavis 10 }

laEntry OBJECT-TYPE
    SYNTAX	LaEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "An entry containing a load average and its values."
    INDEX	{ laIndex }
    ::= { laTable  1 }

LaEntry ::= SEQUENCE {
    laIndex		Integer32,
    laNames		DisplayString,
    laLoad		DisplayString,
    laConfig		DisplayString,
    laLoadInt		Integer32,
    laLoadFloat		Float,
    laErrorFlag		Integer32,
    laErrMessage	DisplayString
}

laIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..3)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "reference index/row number for each observed loadave."
    ::= { laEntry 1 }

laNames OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The list of loadave names we're watching."
    ::= { laEntry 2 }

laLoad OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The 1,5 and 10 minute load averages (one per row)."
    ::= { laEntry 3 }

laConfig OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The watch point for load-averages to signal an
     error.  If the load averages rises above this value,
     the laErrorFlag below is set."
    ::= { laEntry 4 }

laLoadInt OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The 1,5 and 10 minute load averages as an integer.
     This is computed by taking the floating point
     loadaverage value and multiplying by 100, then
     converting the value to an integer."
    ::= { laEntry 5 }

laLoadFloat OBJECT-TYPE
    SYNTAX	Float
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The 1,5 and 10 minute load averages as an opaquely
     wrapped floating point number."
    ::= { laEntry 6 }

laErrorFlag OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "A Error flag to indicate the load-average has crossed
     its threshold value defined in the snmpd.conf file.
     It is set to 1 if the threshold is crossed, 0 otherwise."
    ::= { laEntry 100 }

laErrMessage OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "An error message describing the load-average and its
     surpased watch-point value."
    ::= { laEntry 101 }

version	OBJECT IDENTIFIER ::= { ucdavis 100 }

versionIndex OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Index to mib (always 0)"
    ::= { version 1 }

versionTag OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "CVS tag keyword"
    ::= { version 2 }

versionDate OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Date string from RCS keyword"
    ::= { version 3 }

versionCDate OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Date string from ctime() "
    ::= { version 4 }

versionIdent OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Id string from RCS keyword"
    ::= { version 5 }

versionConfigureOptions OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Options passed to the configure script when this agent was built."
    ::= { version 6 }

versionClearCache OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Set to 1 to clear the exec cache, if enabled"
    ::= { version 10 }

versionUpdateConfig OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Set to 1 to read-read the config file(s)."
    ::= { version 11 }

versionRestartAgent OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Set to 1 to restart the agent."
    ::= { version 12 }

versionDoDebugging OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-write
    STATUS	current
    DESCRIPTION
    "Set to 1 to turn debugging statements on in the agent or 0
     to turn it off."
    ::= { version 20 }

snmperrs OBJECT IDENTIFIER ::= { ucdavis 101 }

snmperrIndex OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Bogus Index for snmperrs (always 0)."
    ::= { snmperrs 1 }

snmperrNames OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "snmp"
    ::= { snmperrs 2 }

snmperrErrorFlag OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "A Error flag to indicate trouble with the agent.  It
     goes to 1 if there is an error, 0 if no error."
    ::= { snmperrs 100 }

snmperrErrMessage OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "An error message describing the problem (if one exists)."
    ::= { snmperrs 101 }

mrTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF MrEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "A table displaying all the oid's registered by mib modules in
     the agent.  Since the agent is modular in nature, this lists
     each module's OID it is responsible for and the name of the module"
    ::= { ucdavis 102 }

mrEntry OBJECT-TYPE
    SYNTAX	MrEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "An entry containing a registered mib oid."
    INDEX	{ IMPLIED mrIndex }
    ::= { mrTable 1 }

MrEntry ::= SEQUENCE {
    mrIndex		OBJECT IDENTIFIER,
    mrModuleName	DisplayString
}

mrIndex OBJECT-TYPE
    SYNTAX	OBJECT IDENTIFIER
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The registry slot of a mibmodule."
    ::= { mrEntry  1 }

mrModuleName OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The module name that registered this OID."
    ::= { mrEntry  2 }

systemStats OBJECT IDENTIFIER ::= { ucdavis 11 }

ssIndex OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Reference Index for each observed systemStat (1)."
    ::= { systemStats 1 }

ssErrorName OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The list of systemStats names (vmstat) we're Counting."
    ::= { systemStats 2 }

ssSwapIn OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Amount of memory swapped in from disk (kB/s)."
    ::= { systemStats 3 }

ssSwapOut OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Amount of memory swapped to disk (kB/s)."
    ::= { systemStats 4 }

ssIOSent OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Blocks sent to a block device (blocks/s)."
    ::= { systemStats 5 }

ssIOReceive OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Blocks received from a block device (blocks/s)."
    ::= { systemStats 6 }

ssSysInterrupts OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of interrupts per second, including the clock."
    ::= { systemStats 7 }

ssSysContext OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "The number of context switches per second."
    ::= { systemStats 8 }

ssCpuUser OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "percentages of user CPU time."
    ::= { systemStats 9 }

ssCpuSystem OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "percentages of system CPU time."
    ::= { systemStats 10 }

ssCpuIdle OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "percentages of idle CPU time."
    ::= { systemStats 11 }

-- possibly used in the future:
--
-- ssErrorFlag OBJECT-TYPE
--     SYNTAX	   Integer32
--     MAX-ACCESS  read-only
--     STATUS      current
--     DESCRIPTION
--         "Error flag."
--     ::= { systemStats 100 }
--
-- ssErrMessage OBJECT-TYPE
--     SYNTAX      DisplayString
--     MAX-ACCESS  read-only
--     STATUS      current
--     DESCRIPTION
--         "Error message describing the errorflag condition."
--     ::= { systemStats 101 }

ucdTraps OBJECT IDENTIFIER ::= { ucdavis 251 }

ucdStart NOTIFICATION-TYPE
    STATUS	current
    DESCRIPTION
    ""
    ::= { ucdTraps 1 }

ucdShutdown	NOTIFICATION-TYPE
    STATUS current
    DESCRIPTION
    "This trap is sent when the agent terminates"
    ::= { ucdTraps 2 }

--
-- File Table:  monitor a list of files to check for a maximum size.
--

fileTable OBJECT-TYPE
    SYNTAX	SEQUENCE OF FileEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "Table of monitored files."
    ::= { ucdavis 15 }

fileEntry OBJECT-TYPE
    SYNTAX	FileEntry
    MAX-ACCESS	not-accessible
    STATUS	current
    DESCRIPTION
    "Entry of file"
    INDEX	{ fileIndex }
    ::= { fileTable 1 }

FileEntry ::= SEQUENCE {
    fileIndex		Integer32,
    fileName		DisplayString,
    fileSize		Integer32,
    fileMax		Integer32,
    fileErrorFlag	TruthValue,
    fileErrorMsg	DisplayString
}

fileIndex OBJECT-TYPE
    SYNTAX	Integer32 (0..2147483647)
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Index of file"
    ::= { fileEntry 1 }

fileName OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Filename"
    ::= { fileEntry 2 }

fileSize OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Size of file (kB)"
    ::= { fileEntry 3 }

fileMax	OBJECT-TYPE
    SYNTAX	Integer32
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Limit of filesize (kB)"
    ::= { fileEntry 4 }

fileErrorFlag OBJECT-TYPE
    SYNTAX	TruthValue
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Limit exceeded flag"
    ::= { fileEntry 100 }

fileErrorMsg OBJECT-TYPE
    SYNTAX	DisplayString
    MAX-ACCESS	read-only
    STATUS	current
    DESCRIPTION
    "Filesize error message"
    ::= { fileEntry 101 }

END


UCD-SNMP-MIB-OLD DEFINITIONS ::= BEGIN

--
--  This mib is a badly created mib which has been replaced by a more
--  properly created UCD-SNMP-MIB.  Use that mib instead.  This file
--  exists for historical purposes only and for use by people that
--  need to support both agent versions.
--

IMPORTS
    ucdavis
        FROM UCD-SNMP-MIB
        OBJECT-TYPE
        FROM SNMPv2-SMI
    DisplayString
        FROM SNMPv2-TC
    Integer32
            FROM SNMPv2-SMI;

-- private	  OBJECT IDENTIFIER ::= { internet 4 }
-- enterprises    OBJECT IDENTIFIER ::= { private 1 }
-- ucdavis          OBJECT IDENTIFIER ::= { enterprises 2021 }
-- processes      OBJECT IDENTIFIER ::= { ucdavis 1 }
-- exec           OBJECT IDENTIFIER ::= { ucdavis 3 }
-- memory         OBJECT IDENTIFIER ::= { ucdavis 4 }
-- lockd          OBJECT IDENTIFIER ::= { ucdavis 5 }
-- disk           OBJECT IDENTIFIER ::= { ucdavis 6 }
-- load           OBJECT IDENTIFIER ::= { ucdavis 7 }
-- version        OBJECT IDENTIFIER ::= { ucdavis 100 }
-- snmperrs       OBJECT IDENTIFIER ::= { ucdavis 101 }
-- mibRegistryTable    OBJECT IDENTIFIER ::= { ucdavis 102 }

-- These are the returned values of the agent type.
-- returned to:  .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0

-- The following section is commented out since it is defined in the
-- current UCD-SNMP-MIB

-- ucdSnmpAgent      OBJECT IDENTIFIER ::= { ucdavis 250 }
-- hpux9             OBJECT IDENTIFIER ::= { ucdSnmpAgent 1 }
-- hpux10            OBJECT IDENTIFIER ::= { ucdSnmpAgent 6 }
-- sunos4            OBJECT IDENTIFIER ::= { ucdSnmpAgent 2 }
-- solaris           OBJECT IDENTIFIER ::= { ucdSnmpAgent 3 }
-- osf               OBJECT IDENTIFIER ::= { ucdSnmpAgent 4 }
-- ultrix            OBJECT IDENTIFIER ::= { ucdSnmpAgent 5 }
-- netbsd1           OBJECT IDENTIFIER ::= { ucdSnmpAgent 7 }
-- freebsd           OBJECT IDENTIFIER ::= { ucdSnmpAgent 8 }
-- irix              OBJECT IDENTIFIER ::= { ucdSnmpAgent 9 }
-- linux             OBJECT IDENTIFIER ::= { ucdSnmpAgent 10 }
-- bsdi              OBJECT IDENTIFIER ::= { ucdSnmpAgent 11 }
-- unknown           OBJECT IDENTIFIER ::= { ucdSnmpAgent 255 }

Processes ::= SEQUENCE {
   processIndex  INTEGER,
   processNames  DisplayString,
   processMin    INTEGER,
   processMax    INTEGER,
   processCount  INTEGER,
   processErrorFlag  INTEGER,
   processErrMessage  DisplayString,
   processErrFix  INTEGER
}

processes OBJECT-TYPE
    SYNTAX SEQUENCE OF Processes
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
        "A set of information on running programs/daemons."
    INDEX { processIndex }
    ::= { ucdavis 1 }

processIndex OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "Reference Index for each observed process."
    ::= { processes 1 }

processNames OBJECT-TYPE
    SYNTAX DisplayString  (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The table of process names we're Counting."
    ::= { processes 2 }

processMin OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The minimum number of processes that should be
        running.  An error flag is generated if the number of
        running processes is < the minimum."
    ::= { processes 3 }

processMax OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The maximum number of processes that should be
        running.  An error flag is generated if the number of
        running processes is > the maximum."
    ::= { processes 4 }

processCount OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The number of current processes running with the name
        in question."
    ::= { processes 5 }

processErrorFlag OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "A Error flag to indicate trouble with a process.  It
        goes to 1 if there is an error, 0 if no error."
    ::= { processes 100 }

processErrMessage OBJECT-TYPE
    SYNTAX DisplayString  (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "An error message describing the problem (if one exists)."
    ::= { processes 101 }

processErrFix OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
        "Setting this to one will try to fix the problem if possible."
    ::= { processes 102 }

extensible OBJECT-TYPE
    SYNTAX SEQUENCE OF Extensible
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
        "Extensible commands returning output and result codes."
    INDEX { extensibleIndex }
    ::= { ucdavis 3 }

Extensible ::= SEQUENCE {
   extensibleIndex   INTEGER,
   extensibleNames   DisplayString,
   extensibleCommand DisplayString,
   extensibleResult  INTEGER,
   extensibleOutput  DisplayString,
   extensibleErrFix  INTEGER
}

extensibleIndex OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "Reference Index for extensible calls."
    ::= { extensible 1 }

extensibleNames OBJECT-TYPE
    SYNTAX DisplayString  (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "Short, one name descriptions of the extensible commands."
    ::= { extensible 2 }

extensibleCommand OBJECT-TYPE
    SYNTAX DisplayString  (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The command line to be executed."
    ::= { extensible 3 }

extensibleResult OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The result code from the executed command."
    ::= { extensible 100 }

extensibleOutput OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The output of the extensible command (top line only)."
    ::= { extensible 101 }

extensibleErrFix OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-write
    STATUS mandatory
    DESCRIPTION
        "Set to 1 to fix the problem, if possible."
    ::= { extensible 102 }

-- the following section is commented out because it is already
-- defined in the current UCD-SNMP-MIB

-- memory OBJECT-TYPE
-- 	SYNTAX Memory
-- 	ACCESS not-accessible
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Miscellanous stuff - memory related."
-- 	::= { ucdavis 4 }
--
-- Memory ::= SEQUENCE {
--    memIndex        INTEGER,
--    memErrorName    DisplayString,
--    memTotalSwap     INTEGER,
--    memAvailSwap     INTEGER,
--    memTotalReal     INTEGER,
--    memAvailReal     INTEGER,
--    memTotalSwapTXT     INTEGER,
--    memAvailSwapTXT     INTEGER,
--    memTotalRealTXT     INTEGER,
--    memAvailRealTXT     INTEGER,
--    memTotalFree       INTEGER,
--    memMinimumSwap       INTEGER,
--    memSwapError       DisplayString,
--    memShared          INTEGER,
--    memBuffer          INTEGER,
--    memCached          INTEGER
-- }
-- memIndex OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Generic Index."
--      ::= { memory 1 }
--
-- memErrorName OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Bogus Name (swap) for consistancy with the rest of the mibs."
--      ::= { memory 2 }
--
-- memTotalSwap OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Swap Size."
-- 	::= { memory 3 }
--
-- memAvailSwap OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Available Swap Space."
-- 	::= { memory 4 }
--
-- memTotalReal OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Real/Physical Memory Size."
-- 	::= { memory 5 }
--
-- memAvailReal OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Available Real/Physical Memory Space."
-- 	::= { memory 6 }
--
-- memTotalSwapTXT OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total VM used by text."
-- 	::= { memory 7 }
--
-- memAvailSwapTXT OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Active VM used by text."
-- 	::= { memory 8 }
--
-- memTotalRealTXT OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Real/Physical Memory Size used by txt."
-- 	::= { memory 9 }
--
-- memAvailRealTXT OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Active Real/Physical Memory Space used by txt."
-- 	::= { memory 10 }
--
-- memTotalFree OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Available Memory"
-- 	::= { memory 11 }
--
-- memMinimumSwap OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Minimum amount of free swap.  Otherwise memErrorSwap
-- 		is set to 1 "
-- 	::= { memory 12 }
--
-- memShared OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Shared Memory"
-- 	::= { memory 13 }
--
-- memBuffer OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Buffered Memory"
-- 	::= { memory 14 }
--
-- memCached OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Total Cached Memory"
-- 	::= { memory 15 }
--
-- memSwapError OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Error flag.  1 indicates very little swap space left"
-- 	::= { memory 100 }
--
-- memSwapErrorMsg OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Error message describing the errorflag condition"
--      ::= { memory 101 }
--
-- lockd OBJECT-TYPE
-- 	SYNTAX Lockd
-- 	ACCESS not-accessible
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Tests the functionality of the rpc.lockd/rpc.statd pair."
-- 	INDEX { lockdIndex }
-- 	::= { ucdavis 5 }

-- Lockd ::= SEQUENCE {
--    lockdIndex   INTEGER,
--    lockdError  INTEGER,
--    lockdErrorMsg  DisplayString
-- }
--
-- lockdIndex OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Reference Index for lockd calls."
-- 	::= { lockd 1 }
--
-- lockdError OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Error Flag.  > 0 indicates error"
-- 	::= { lockd 100 }
--
-- lockdErrorMsg OBJECT-TYPE
-- 	SYNTAX DisplayString (SIZE (0..255))
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Error message if something is wrong"
-- 	::= { lockd 101 }

disk 	OBJECT-TYPE
    SYNTAX SEQUENCE OF Disk
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
        "Disk watching information."
    INDEX { diskIndex }
    ::= { ucdavis 6 }

Disk ::= SEQUENCE {
   diskIndex   INTEGER,
   diskPath  DisplayString,
   diskDevice  DisplayString,
   diskMinimum  INTEGER,
   diskMinPercent  INTEGER,
   diskTotal  INTEGER,
   diskAvail  INTEGER,
   diskUsed  INTEGER,
   diskPercent  INTEGER,
   diskErrorFlag  INTEGER,
   diskErrorMsg  DisplayString
}

diskIndex OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "Reference number for the Disk Mib."
    ::= { disk 1 }

diskPath OBJECT-TYPE
     SYNTAX  DisplayString
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Path where disk is mounted."
     ::= { disk 2 }

diskDevice OBJECT-TYPE
     SYNTAX  DisplayString
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Device path"
     ::= { disk 3 }

diskMinimum OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Minimum space required on the disk."
     ::= { disk 4 }

diskMinPercent OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Minimum percentage of space required on the disk."
     ::= { disk 5 }

diskTotal OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Total Disk Size (kbytes)"
     ::= { disk 6 }

diskAvail OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Available disk Space"
     ::= { disk 7 }

diskUsed OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Used Space on Disk"
     ::= { disk 8 }

diskPercent OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Percentage of space used on disk"
     ::= { disk 9 }

diskErrorFlag OBJECT-TYPE
     SYNTAX  INTEGER
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "Error flag signaling disk is over minimum required space"
     ::= { disk 100 }

diskErrorMsg OBJECT-TYPE
     SYNTAX  DisplayString
     ACCESS  read-only
     STATUS  mandatory
     DESCRIPTION
          "A text description of what caused the error flag to be set."
     ::= { disk 101 }

loadaves OBJECT-TYPE
    SYNTAX SEQUENCE OF Loadaves
    ACCESS not-accessible
    STATUS mandatory
    DESCRIPTION
        "Load average information."
    INDEX { loadaveIndex }
    ::= { ucdavis 7 }

Loadaves ::= SEQUENCE {
   loadaveIndex  INTEGER,
   loadaveNames  DisplayString,
   loadaveLoad   DisplayString,
   loadaveConfig DisplayString,
   loadaveErrorFlag  INTEGER,
   loadaveErrMessage  DisplayString
}

loadaveIndex OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "Reference Index for each observed loadave."
    ::= { loadaves 1 }

loadaveNames OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The list of loadave names we're Counting."
    ::= { loadaves 2 }

loadaveLoad OBJECT-TYPE
    SYNTAX DisplayString
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The 1,5 and 10 minute load averages."
    ::= { loadaves 3 }

loadaveConfig OBJECT-TYPE
    SYNTAX DisplayString
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "The watch point for loadaverages to signal an error."
    ::= { loadaves 4 }

loadaveErrorFlag OBJECT-TYPE
    SYNTAX INTEGER
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "A Error flag to indicate trouble with a loadave.  It
        goes to 1 if there is an error, 0 if no error."
    ::= { loadaves 100 }

loadaveErrMessage OBJECT-TYPE
    SYNTAX DisplayString (SIZE (0..255))
    ACCESS read-only
    STATUS mandatory
    DESCRIPTION
        "An error message describing the problem (if one exists)."
    ::= { loadaves 101 }

-- the following section is commented out because it is already
-- defined in the current UCD-SNMP-MIB

-- version	OBJECT-TYPE
-- 	SYNTAX Version
-- 	ACCESS not-accessible
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"ece-snmpd version info."
-- 	INDEX { versionIndex }
-- 	::= { ucdavis 100 }
--
-- Version ::= SEQUENCE {
--    versionIndex   INTEGER,
--    versionTag  DisplayString,
--    versionDate  DisplayString,
--    versionCDate  DisplayString,
--    versionIdent  DisplayString,
--    versionClearCache  INTEGER,
--    versionUpdateConfig  INTEGER,
--    versionDoDebugging  INTEGER
-- }
--
-- versionIndex OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Index to mib (always 1)"
--      ::= { version 1 }
--
-- versionTag OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "CVS tag keyword"
--      ::= { version 2 }
--
-- versionDate OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Date string from RCS keyword"
--      ::= { version 3 }
--
-- versionCDate OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Date string from ctime() "
--      ::= { version 4 }
--
-- versionIdent OBJECT-TYPE
--      SYNTAX  DisplayString
--      ACCESS  read-only
--      STATUS  mandatory
--      DESCRIPTION
--           "Id string from RCS keyword"
--      ::= { version 5 }
--
-- versionClearCache OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-write
--      STATUS  mandatory
--      DESCRIPTION
--           "Set to 1 to clear the exec cache, if enabled"
--      ::= { version 10 }
--
-- versionUpdateConfig OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-write
--      STATUS  mandatory
--      DESCRIPTION
--           "Set to 1 to read-read the config file(s)."
--      ::= { version 11 }
--
-- versionRestartAgent OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-write
--      STATUS  mandatory
--      DESCRIPTION
--           "Set to 1 to restart the agent."
--      ::= { version 12 }
--
-- versionDoDebugging OBJECT-TYPE
--      SYNTAX  INTEGER
--      ACCESS  read-write
--      STATUS  mandatory
--      DESCRIPTION
--           "Set to 1 to turn debugging statements on in the agent."
--      ::= { version 20 }
--

-- the following section is commented out because it is already
-- defined in the current UCD-SNMP-MIB

-- snmperrs OBJECT-TYPE
-- 	SYNTAX Snmperrs
-- 	ACCESS not-accessible
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"A place for the agent to report problems."
-- 	INDEX { snmperrIndex }
-- 	::= { ucdavis 101 }
--
--
-- Snmperrs ::= SEQUENCE {
--    snmperrIndex  INTEGER,
--    snmperrNames  DisplayString,
--    snmperrErrorFlag  INTEGER,
--    snmperrErrMessage  DisplayString
-- }
--
-- snmperrIndex OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"Reference Index for each observed snmperr."
-- 	::= { snmperrs 1 }
--
-- snmperrNames OBJECT-TYPE
-- 	SYNTAX DisplayString (SIZE (0..255))
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"snmp"
-- 	::= { snmperrs 2 }
--
-- snmperrErrorFlag OBJECT-TYPE
-- 	SYNTAX INTEGER
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"A Error flag to indicate trouble with the agent.  It
-- 		goes to 1 if there is an error, 0 if no error."
-- 	::= { snmperrs 100 }
--
-- snmperrErrMessage OBJECT-TYPE
-- 	SYNTAX DisplayString (SIZE (0..255))
-- 	ACCESS read-only
-- 	STATUS mandatory
-- 	DESCRIPTION
-- 		"An error message describing the problem (if one exists)."
-- 	::= { snmperrs 101 }
--
END


UDP-MIB DEFINITIONS ::= BEGIN

IMPORTS
    OBJECT-GROUP, MODULE-COMPLIANCE
        FROM SNMPv2-CONF
    mib-2, IpAddress, Counter32, OBJECT-TYPE, MODULE-IDENTITY
        FROM SNMPv2-SMI;

udpMIB MODULE-IDENTITY
    LAST-UPDATED "9411010000Z"
    ORGANIZATION "IETF SNMPv2 Working Group"
    CONTACT-INFO
                 "Keith McCloghrie

          Postal: Cisco Systems, Inc.
                  170 West Tasman Drive
                  San Jose, CA  95134-1706
                  US

          Phone:  +1 408 526 5260
          Email:  kzm@cisco.com"
    DESCRIPTION
        "The MIB module for managing UDP implementations."
    REVISION     "9103310000Z"
    DESCRIPTION
        "The initial revision of this MIB module was part of MIB-
         II."
    ::= { mib-2  50 }

udp OBJECT IDENTIFIER ::= { mib-2  7 }

udpInDatagrams OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of UDP datagrams delivered to UDP users."
    ::= { udp  1 }

udpNoPorts OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of received UDP datagrams for which there
         was no application at the destination port."
    ::= { udp  2 }

udpInErrors OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The number of received UDP datagrams that could not be
         delivered for reasons other than the lack of an application
         at the destination port."
    ::= { udp  3 }

udpOutDatagrams OBJECT-TYPE
    SYNTAX     Counter32
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The total number of UDP datagrams sent from this entity."
    ::= { udp  4 }

udpTable OBJECT-TYPE
    SYNTAX     SEQUENCE OF UdpEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "A table containing UDP listener information."
    ::= { udp  5 }

udpEntry OBJECT-TYPE
    SYNTAX     UdpEntry
    MAX-ACCESS not-accessible
    STATUS     current
    DESCRIPTION
        "Information about a particular current UDP listener."
    INDEX      { udpLocalAddress,  udpLocalPort }
    ::= { udpTable  1 }

UdpEntry ::=
    SEQUENCE {
        udpLocalAddress
            IpAddress,

        udpLocalPort
            INTEGER
    }

udpLocalAddress OBJECT-TYPE
    SYNTAX     IpAddress
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The local IP address for this UDP listener.  In the case of
         a UDP listener which is willing to accept datagrams for any
         IP interface associated with the node, the value 0.0.0.0 is
         used."
    ::= { udpEntry  1 }

udpLocalPort OBJECT-TYPE
    SYNTAX     INTEGER
    MAX-ACCESS read-only
    STATUS     current
    DESCRIPTION
        "The local port number for this UDP listener."
    ::= { udpEntry  2 }

udpMIBConformance ::= { udpMIB  2 }

udpMIBCompliances ::= { udpMIBConformance  1 }

udpMIBGroups ::= { udpMIBConformance  2 }

udpMIBCompliance MODULE-COMPLIANCE
    STATUS     current
    DESCRIPTION
        "The compliance statement for SNMPv2 entities which
         implement UDP."

    MODULE           -- this module
    MANDATORY-GROUPS { udpGroup }
    ::= { udpMIBCompliances  1 }

udpGroup OBJECT-GROUP
    OBJECTS    {
                 udpInDatagrams,
                 udpNoPorts,
                 udpInErrors,
                 udpOutDatagrams,
                 udpLocalAddress,
                 udpLocalPort
               }
    STATUS     current
    DESCRIPTION
        "The udp group of objects providing for management of UDP
         entities."
    ::= { udpMIBGroups  1 }

END


+----------------------------------------------------------------------+
| The installation process is incomplete. The following resources were |
| not installed:                                                       |
|                                                                      |
|   Self-contained Extension Support                                   |
|   PEAR: PHP Extension and Add-on Repository                          |
|                                                                      |
| To install these components, become the superuser and execute:       |
|                                                                      |
|   # make install-su                                                  |
+----------------------------------------------------------------------+


Empty

:)


PHPDoc 1.0beta

 Sorry, frames required.


Data Types: Conditional Pulldowns

ex: "MPIMotorEventConfig"

Step 1
 Step 2


Methods: Conditional Pulldowns

ex: "mpiAxisConfigSet"

Step 1
 Step 2


Software Home Page (MEI)

* - modules


Top Frame for Software Search

Hardware | Utilities | Software | Sample Applications
Search by Object | Search by Method | Search by Data Type


Table of Contents for Methods Breakdown

Methods Breakdown

--Table of Contents--

---Topic--- | pg
Object Methods | 2
Configuration Methods | 3
Memory Methods | 7
Status Methods | 13
Event Notification Methods | 17
List Methods | 19
Identity Methods | 27


Table of Contents for MPI Library Basics

MPI LIBRARY BASICS

--Table of Contents--

---Topic--- | pg
Introduction | 2
Motion Concepts | 3
General Definitions | 5
Naming Conventions | 10
Object Descriptions | 14


Table of Contents for SERCOS

SERCOS

--Table of Contents--

---Topic--- | pg
Introduction | 2
Overview | 3
Data Types | 7
Communications | 13
Procedures | 17
Telegrams | 19
Topologies | 27


Table of Contents for Software Topics

SOFTWARE TOPICS

--Table of Contents--

--Topic-- | pg
Object Relationships | 2
Host and Controller Based Motion | 8
Multitasking | 13
Configuration Diagram | 14
Servo Algorithms: PID/PIV | 15
Project / Makefile Settings: Symbol Definitions | 20
About Homing | 22
Using the Origin Variable | 23
How Stop Events Work | 24
Compiling Program Sequencer Commands | 26
Running Multiple Applications with the XMP | 27
Perform a Point-to-Point Coordinated Move | 28
About the PID PIDOutputOffset Parameter | 29
How Motion Completion Events are Generated | 30
S-Curve Jerk Algorithm and Attributes | 33
S-Curve Motion Profiles: Command Acceleration vs. Peak Acceleration | 37
Default XMP-Series Controller Configuration | 38
Axis Tolerances and Related Events | 42


Table of Contents for Utilities

 | SAFETY WARNINGS
Chapter 1 | Requirements
 | Introduction
 | Required Materials
 | Safety Precautions
 | Hardware Requirements and Installation

Chapter 2 | Motion Console
 | Object-oriented Motion Control
 | Motion Console Objects
 | Motion Console User Interface
 |  | Main Motion Console Frame
 |  | Adding a New Controller
 |  | Object Summary Windows
 |  | Object Explorer
 |  | Object List Configuration Dialog Boxes
 | Configuring New Systems with Motion Console
 |  | Getting Started with Motion Console
 |  | Saving Parameter Settings
 |  | Associating Objects with Motion Console
 |  | Configuring a Motion Supervisor
 |  | Mapping One Object to Another
 |  | Removing (Deleting) a Mapped Object
 |  | Safety Reminders
 | Motion Console Objects
 |  | Controller Objects
 |  | Motion Supervisor Object
 |  | Axis Objects
 |  | Filter Objects
 |  | Motor Objects
 |  | SERCOS Ring Objects
 |  | SERCOS Node Objects
 |  | Idn Objects

Chapter 3 | Motion Scope
 | Description
 | Installing and Launching Motion Scope
 | Motion Scope User Interface
 | Motion Scope Quick-Start Guide
 | Motion Scope Toolbar Functions
 |  | File Menu Items
 |  | View Menu Items
 |  | Pane Menu Items
 |  |  | Display
 |  |  | Export
 |  |  | Import
 |  |  | Mode
 |  |  | Print
 |  |  | Traces
 |  |  | Trigger
 |  | Trace Menu Items
 |  | Window Menu Items
 | Other Data and Display Features
 |  | MaxBuffer (ms) and SampleSize (samples)
 |  | XRange and XOffset Fields
 |  | YScale and YOffset Fields
 |  | XRangeBar and YRangeBar
 |  | Zoom and Step Buttons
 |  | Trace and AutoScale Menu Items
 | Direct Cursor Measurement of Traces

Chapter 4 | VM3
 | Introduction
 | Installing and Running VM3
 | VM3 Layout
 | “Board Data” Panel (F1)
 | VM3 Data Panels and Header Files
 | “Commands” Panel (F2)
 | “Auto” Panel (F3)
 | “Hex” Panel (F4)
 | “Decimal” Panel (F5)
 | “Float” Panel (F6)
 | “Dump/Save” Panel (F8)
 | “Reset” Panel (F9)
 | “Toggle” Panel (F10)
 | Command Line Options

Chapter 5 | XMP Configuration Utility
 | Introduction
 | Command-Line Syntax
 | Examples
 | Firmware/Library Upgrades
 | Modifying Configuration
 | Open Issues


Use the following search to find any topic relating to the XMP Software Tools and Utilities Guide.

To receive a result, type in part of a word, a single word, or a collection of words. To broaden or narrow the search, use the "find all words," "find any word," or "exact match" functions.

Motion Engineering © 2001