//------------------------------------------------------------------------------ //! @brief Called when asyn clients call pasynUInt32Digital->read(). //! //! If pasynUser->reason is equal //! - P_Status0 the status bytes are read out and stored in //! the corresponding parameters. //! - any other: the value from the parameter library will be returned. //! //! @param [in] pasynUser pasynUser structure that encodes the reason and address //! @param [out] value Address of the value to read //! @param [in] mask Mask value to use when reading the value. //! //! @return in case of no error occured asynSuccess is returned. Otherwise //! asynError or asynTimeout is returned. A error message is stored //! in pasynUser->errorMessage. //------------------------------------------------------------------------------ asynStatus drvAsynWienerVme::readUInt32Digital( asynUser *pasynUser, epicsUInt32 *value, epicsUInt32 mask ) { int function = pasynUser->reason; asynStatus status = asynSuccess; const char *functionName = "readUInt32Digital"; if ( function == P_Status0 ) { can_frame_t pframe; pframe.can_id = _crateId | CAN_RTR_FLAG; pframe.can_dlc = 8; status = pasynGenericPointerSyncIO->writeRead( _pasynGenericPointer, &pframe, &pframe, pasynUser->timeout ); if ( asynTimeout == status ){ epicsSnprintf( pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s:%s: status=%d, function=%d, No reply from device within %f s", driverName, _deviceName, functionName, status, function, pasynUser->timeout ); return asynTimeout; } if ( status ){ epicsSnprintf( pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s:%s: status=%d, function=%d %s", driverName, _deviceName, functionName, status, function, _pasynGenericPointer->errorMessage ); return asynError; } if ( pframe.can_id != _crateId || pframe.can_dlc != 8 ) { epicsSnprintf( pasynUser->errorMessage, pasynUser->errorMessageSize, "\033[31;1m%s:%s:%s: function=%d, Mismatch in reply.\n Got '%08x %d...' where '%x08 8...' was expected.\033[0m", driverName, _deviceName, functionName, function, pframe.can_id, pframe.can_dlc, _crateId ); return asynError; } status = setUIntDigitalParam( P_Status0, pframe.data[0], mask ); status = setUIntDigitalParam( P_Status1, pframe.data[1], mask ); status = setUIntDigitalParam( P_Status2, pframe.data[2], mask ); status = setUIntDigitalParam( P_Status3, pframe.data[3], mask ); status = setUIntDigitalParam( P_Status4, pframe.data[4], mask ); status = setUIntDigitalParam( P_Status5, pframe.data[5], mask ); status = setUIntDigitalParam( P_Status6, pframe.data[6], mask ); status = setUIntDigitalParam( P_Status7, pframe.data[7], mask ); status = (asynStatus) callParamCallbacks(); } // read back parameter status = (asynStatus) getUIntDigitalParam( function, value, mask ); if ( status ) epicsSnprintf( pasynUser->errorMessage, pasynUser->errorMessageSize, "\033[31;1m%s:%s:%s: status=%d, function=%d, value=%u mask=%u\033[0m", driverName, _deviceName, functionName, status, function, *value, mask ); else asynPrint( pasynUser, ASYN_TRACEIO_DEVICE, "%s:%s:%s: function=%d, value=%u, mask=%u\n", driverName, _deviceName, functionName, function, *value, mask ); return status; }
asynStatus DSA2000::setHVStatus() { struct ncp_hcmd_sethvstatus setCommand; epicsUInt32 control; asynStatus status = asynSuccess; int sendStatus; int range; double DACVolts, fullScale=0;; int response; int actual; static const char *functionName = "setHVStatus"; getUIntDigitalParam(P_HVControl, &control, 0xFFFFFFFF); getIntegerParam(P_HVRangeSetting, &range); getDoubleParam(P_DACSetting, &DACVolts); switch (range) { case rangePlus5000: control &= ~HVPS_Negative; control |= HVPS_5000V; fullScale = 5000.; break; case rangePlus1300: control &= ~HVPS_Negative; control &= ~HVPS_5000V; fullScale = 1300.; break; case rangeMinus5000: control |= HVPS_Negative; control |= HVPS_5000V; fullScale = 5000.; break; default: asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: error, unknown range=%d\n", driverName, functionName, range); break; } setUIntDigitalParam(P_HVControl, control, 0xFFFFFFFF); setCommand.control = control; setCommand.DAC = (epicsInt16)((DACVolts/fullScale * 4095) + 0.5); sendStatus = nmc_sendcmd(this->module, NCP_K_HCMD_SETHVSTATUS, &setCommand, sizeof(setCommand), &response, sizeof(response), &actual, 0); if (sendStatus != 9) status = asynError; return status; }
asynStatus USB1608G::writeUInt32Digital(asynUser *pasynUser, epicsUInt32 value, epicsUInt32 mask) { int function = pasynUser->reason; int status=0; int i; epicsUInt32 outValue=0, outMask, direction=0; static const char *functionName = "writeUInt32Digital"; setUIntDigitalParam(function, value, mask); if (function == digitalDirection_) { outValue = (value == 0) ? DIGITALIN : DIGITALOUT; for (i=0; i<NUM_IO_BITS; i++) { if ((mask & (1<<i)) != 0) { status = cbDConfigBit(boardNum_, AUXPORT, i, outValue); } } } else if (function == digitalOutput_) { getUIntDigitalParam(digitalDirection_, &direction, 0xFFFFFFFF); for (i=0, outMask=1; i<NUM_IO_BITS; i++, outMask = (outMask<<1)) { // Only write the value if the mask has this bit set and the direction for that bit is output (1) outValue = ((value &outMask) == 0) ? 0 : 1; if ((mask & outMask & direction) != 0) { status = cbDBitOut(boardNum_, AUXPORT, i, outValue); } } } callParamCallbacks(); if (status == 0) { asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s, port %s, wrote outValue=0x%x, value=0x%x, mask=0x%x, direction=0x%x\n", driverName, functionName, this->portName, outValue, value, mask, direction); } else { asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s:%s, port %s, ERROR writing outValue=0x%x, value=0x%x, mask=0x%x, direction=0x%x, status=%d\n", driverName, functionName, this->portName, outValue, value, mask, direction, status); } return (status==0) ? asynSuccess : asynError; }
/** 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); }
/** Callback task that runs as a separate thread. */ void testErrors::callbackTask(void) { asynStatus currentStatus; int itemp; epicsInt32 iVal; epicsUInt32 uiVal; epicsFloat64 dVal; int i; char octetValue[20]; /* Loop forever */ while (1) { lock(); updateTimeStamp(); getIntegerParam(P_StatusReturn, &itemp); currentStatus = (asynStatus)itemp; getIntegerParam(P_Int32Value, &iVal); iVal++; if (iVal > 64) iVal=0; setIntegerParam(P_Int32Value, iVal); setParamStatus( P_Int32Value, currentStatus); getIntegerParam(P_BinaryInt32Value, &iVal); iVal++; if (iVal > 1) iVal=0; setIntegerParam(P_BinaryInt32Value, iVal); setParamStatus( P_BinaryInt32Value, currentStatus); getIntegerParam(P_MultibitInt32Value, &iVal); iVal++; if (iVal > MAX_INT32_ENUMS-1) iVal=0; setIntegerParam(P_MultibitInt32Value, iVal); setParamStatus( P_MultibitInt32Value, currentStatus); getUIntDigitalParam(P_UInt32DigitalValue, &uiVal, UINT32_DIGITAL_MASK); uiVal++; if (uiVal > 64) uiVal=0; setUIntDigitalParam(P_UInt32DigitalValue, uiVal, UINT32_DIGITAL_MASK); setParamStatus( P_UInt32DigitalValue, currentStatus); getUIntDigitalParam(P_BinaryUInt32DigitalValue, &uiVal, UINT32_DIGITAL_MASK); uiVal++; if (uiVal > 1) uiVal=0; setUIntDigitalParam(P_BinaryUInt32DigitalValue, uiVal, UINT32_DIGITAL_MASK); setParamStatus( P_BinaryUInt32DigitalValue, currentStatus); getUIntDigitalParam(P_MultibitUInt32DigitalValue, &uiVal, UINT32_DIGITAL_MASK); uiVal++; if (uiVal > MAX_UINT32_ENUMS-1) uiVal=0; setUIntDigitalParam(P_MultibitUInt32DigitalValue, uiVal, UINT32_DIGITAL_MASK); setParamStatus( P_MultibitUInt32DigitalValue, currentStatus); getDoubleParam(P_Float64Value, &dVal); dVal += 0.1; setDoubleParam(P_Float64Value, dVal); setParamStatus(P_Float64Value, currentStatus); sprintf(octetValue, "%.1f", dVal); setStringParam(P_OctetValue, octetValue); setParamStatus(P_OctetValue, currentStatus); for (i=0; i<MAX_ARRAY_POINTS; i++) { int8ArrayValue_[i] = iVal; int16ArrayValue_[i] = iVal; int32ArrayValue_[i] = iVal; float32ArrayValue_[i] = (epicsFloat32)dVal; float64ArrayValue_[i] = dVal; } callParamCallbacks(); setParamStatus(P_Int8ArrayValue, currentStatus); setParamStatus(P_Int16ArrayValue, currentStatus); setParamStatus(P_Int32ArrayValue, currentStatus); setParamStatus(P_Float32ArrayValue, currentStatus); setParamStatus(P_Float64ArrayValue, currentStatus); doCallbacksInt8Array(int8ArrayValue_, MAX_ARRAY_POINTS, P_Int8ArrayValue, 0); doCallbacksInt16Array(int16ArrayValue_, MAX_ARRAY_POINTS, P_Int16ArrayValue, 0); doCallbacksInt32Array(int32ArrayValue_, MAX_ARRAY_POINTS, P_Int32ArrayValue, 0); doCallbacksFloat32Array(float32ArrayValue_, MAX_ARRAY_POINTS, P_Float32ArrayValue, 0); doCallbacksFloat64Array(float64ArrayValue_, MAX_ARRAY_POINTS, P_Float64ArrayValue, 0); unlock(); epicsEventWait(eventId_); } }