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