int AIMConfig(
    const char *portName, int address, int port, int maxChans,
    int maxSignals, int maxSequences, char *ethernetDevice)
{
    unsigned char enet_address[6];
    int status;
    int retries = 0;
    mcaAIMPvt *pPvt;

    pPvt = callocMustSucceed(1, sizeof(mcaAIMPvt), "AIMConfig");
    status = nmc_initialize(ethernetDevice);
    if (status != 0) {
        errlogPrintf("AIMConfig: nmc_initialize failed for device %s status=%d\n",
                     ethernetDevice, status);
        return(ERROR);
    }

    /* Copy parameters to object private */
    pPvt->exists = 1;
    pPvt->maxChans = maxChans;
    pPvt->nchans = maxChans;
    pPvt->maxSignals = maxSignals;
    pPvt->maxSequences = maxSequences;
    /* Copy the module ADC port number. Subtract 1 to convert from */
    /* user units to device units  */
    pPvt->adc = port - 1;
    /* Set reasonable defaults for other parameters */
    pPvt->plive   = 0;
    pPvt->preal   = 0;
    pPvt->ptotal  = 0;
    pPvt->ptschan = 0;
    pPvt->ptechan = 0;
    pPvt->acqmod  = 1;
    pPvt->acquiring = 0;
    
    /* Maximum time to use old status info before a new query is sent. Only used 
     * if signal!=0, typically with multiplexors. 0.1 seconds  */
    pPvt->maxStatusTime = 0.1;
    /* Compute the module Ethernet address */
    nmc_build_enet_addr(address, enet_address);

    /* Find the particular module on the net - may have to retry in case
       the module database is still being built after initialisation.
       This is not possible to resolve other than by waiting, since there are
       an unknown number of modules on the local subnet, and they can reply
       to the initial inquiry broadcast in an arbitrary order. */
    do {
	status = nmc_findmod_by_addr(&pPvt->module, enet_address);
	epicsThreadSleep(0.1);
    } while ((status != OK) && (retries++ < 5));

    if (status != OK) {
        errlogPrintf("AIMConfig ERROR: cannot find module on the network!\n");
        return (ERROR);
    }

    /* Buy the module (make this IOC own it) */
    status = nmc_buymodule(pPvt->module, 0);
    if (status != OK) {
        errlogPrintf("AIMConfig ERROR: cannot buy module, someone else owns it!\n");
        return (ERROR);
    }

    /* Allocate memory in the AIM, get base address */
    status = nmc_allocate_memory(pPvt->module,
                    pPvt->maxChans * pPvt->maxSignals * pPvt->maxSequences * 4,
                    &pPvt->base_address);
    if (status != OK) {
        errlogPrintf("AIMConfig ERROR: cannot allocate required memory in AIM\n");
        return (ERROR);
    }
    pPvt->seq_address = pPvt->base_address;

    pPvt->ethernetDevice = epicsStrDup(ethernetDevice);
    pPvt->portName = epicsStrDup(portName);

    /*
     *  Link with higher level routines
     */
    pPvt->common.interfaceType = asynCommonType;
    pPvt->common.pinterface  = (void *)&mcaAIMCommon;
    pPvt->common.drvPvt = pPvt;
    pPvt->int32.interfaceType = asynInt32Type;
    pPvt->int32.pinterface  = (void *)&mcaAIMInt32;
    pPvt->int32.drvPvt = pPvt;
    pPvt->float64.interfaceType = asynFloat64Type;
    pPvt->float64.pinterface  = (void *)&mcaAIMFloat64;
    pPvt->float64.drvPvt = pPvt;
    pPvt->int32Array.interfaceType = asynInt32ArrayType;
    pPvt->int32Array.pinterface  = (void *)&mcaAIMInt32Array;
    pPvt->int32Array.drvPvt = pPvt;
    pPvt->drvUser.interfaceType = asynDrvUserType;
    pPvt->drvUser.pinterface  = (void *)&mcaAIMDrvUser;
    pPvt->drvUser.drvPvt = pPvt;
    status = pasynManager->registerPort(pPvt->portName,
                                        ASYN_MULTIDEVICE | ASYN_CANBLOCK,
                                        1,  /* autoconnect */
                                        0,  /* medium priority */
                                        0); /* default stacksize */
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig ERROR: Can't register myself.\n");
        return -1;
    }
    status = pasynManager->registerInterface(pPvt->portName, &pPvt->common);
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig: Can't register common.\n");
        return -1;
    }
    status = pasynInt32Base->initialize(pPvt->portName, &pPvt->int32);
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig: Can't register int32.\n");
        return -1;
    }

    status = pasynFloat64Base->initialize(pPvt->portName, &pPvt->float64);
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig: Can't register float64.\n");
        return -1;
    }

    status = pasynInt32ArrayBase->initialize(pPvt->portName, &pPvt->int32Array);
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig: Can't register int32Array.\n");
        return -1;
    }

    status = pasynManager->registerInterface(pPvt->portName,&pPvt->drvUser);
    if (status != asynSuccess) {
        errlogPrintf("AIMConfig ERROR: Can't register drvUser\n");
        return -1;
    }
    return(0);
}
Beispiel #2
0
/** Constructor for the DSA2000 class.
  * Calls constructor for the asynPortDriver base class.
  * \param[in] portName The name of the asyn port driver to be created.
  * \param[in] moduleAddress The low-order 16 bits of the Ethernet address */
DSA2000::DSA2000(const char *portName, int moduleAddress)
    : asynPortDriver(portName,
                     1, /* maxAddr */
                     (int)NUM_PARAMS,
                     asynInt32Mask | asynFloat64Mask | asynUInt32DigitalMask | asynDrvUserMask, /* Interface mask */
                     asynInt32Mask | asynFloat64Mask | asynUInt32DigitalMask,  /* Interrupt mask */
                     ASYN_CANBLOCK, /* asynFlags.  This driver blocks and it is not multi-device */
                     1, /* Autoconnect */
                     0, /* Default priority */
                     0) /* Default stack size*/
{
    unsigned char enet_address[6];
    int status;
    epicsUInt32 HVStatus, HVControl;
    double voltage;
    int range;
    int retries=0;
    const char *functionName = "DSA2000";

    createParam(P_HVControlString,          asynParamUInt32Digital, &P_HVControl);
    createParam(P_HVStatusString,           asynParamUInt32Digital, &P_HVStatus);
    createParam(P_HVRangeSettingString,     asynParamInt32,         &P_HVRangeSetting);
    createParam(P_HVRangeReadbackString,    asynParamInt32,         &P_HVRangeReadback);
    createParam(P_DACSettingString,         asynParamFloat64,       &P_DACSetting);
    createParam(P_DACReadbackString,        asynParamFloat64,       &P_DACReadback);
    createParam(P_ADCReadbackString,        asynParamFloat64,       &P_ADCReadback);
    createParam(P_HVResetString,            asynParamInt32,         &P_HVReset);
    createParam(P_ReadStatusString,         asynParamInt32,         &P_ReadStatus);

    /* Compute the module Ethernet address */
    nmc_build_enet_addr(moduleAddress, enet_address);

    /* Find the particular module on the net - may have to retry in case
     * the module database is still being built after initialisation.
     * This is not possible to resolve other than by waiting, since there are
     * an unknown number of modules on the local subnet, and they can reply
     * to the initial inquiry broadcast in an arbitrary order. */
    do {
        epicsThreadSleep(0.1);
        status = nmc_findmod_by_addr(&this->module, enet_address);
    } while ((status != OK) && (retries++ < 5));

    if (status != OK) {
        asynPrint(pasynUserSelf, ASYN_TRACE_ERROR,
                  "%s:%s: ERROR, cannot find module %d on the network!\n",
                  driverName, functionName, moduleAddress);
        return;
    }

    /* Read the status of the module */
    getHVStatus();

    /* Set the value of the output parameters from the initial readbacks */
    getUIntDigitalParam(P_HVStatus, &HVStatus, 0xFFFFFFFF);
    // Force callbacks on all bits first time
    setUIntDigitalParam(P_HVStatus, HVStatus, 0xFFFFFFFF, 0xFFFFFFFF);
    // Copy bits 0-2 and 9 of status to control
    HVControl = HVStatus & 0x207;
    setUIntDigitalParam(P_HVControl, HVControl, 0xFFFFFFFF, 0xFFFFFFFF);
    getDoubleParam(P_DACReadback, &voltage);
    setDoubleParam(P_DACSetting, voltage);
    getIntegerParam(P_HVRangeReadback, &range);
    setIntegerParam(P_HVRangeSetting, range);
}