void omsMAXvEncFunc::initialize() { const char* functionName = "initialize"; Debug(5, "omsMAXvEncFunc::initialize: start initialize\n" ); int encIndex = numAxes; if (encIndex > MAXENCFUNC) encIndex = MAXENCFUNC; /* auxiliary encoders */ for (int i=0; i < encIndex; ++i){ if (createParam(i, motorEncoderFunctionString, asynParamInt32, &encFuncIndex[i]) != asynSuccess) errlogPrintf("%s:%s:%s: unable to create param motorEncoderFunctionString, index %d\n", driverName, functionName, portName, i); if (createParam(i, motorEncoderRawPosString, asynParamFloat64, &encRawPosIndex[i]) != asynSuccess) errlogPrintf("%s:%s:%s: unable to create param motorEncoderRawPosString, index %d\n", driverName, functionName, portName, i); } createParam(0, motorAuxEncoderPositionString, asynParamFloat64, &encPosIndex[0]); createParam(1, motorAuxEncoderPositionString, asynParamFloat64, &encPosIndex[1]); Debug(3, "omsMAXvEncFunc::initialize: auxiliary encoder 0 position index %d\n", encPosIndex[0] ); Debug(3, "omsMAXvEncFunc::initialize: auxiliary encoder 1 position index %d\n", encPosIndex[1] ); for (int i=0; i < encIndex; ++i) Debug(3, "omsMAXvEncFunc::initialize: encFuncIndex %d => %d\n", i, encFuncIndex[i] ); lock(); for (int i=0; i < encIndex; ++i){ setIntegerParam(i, encFuncIndex[i], 0); setDoubleParam(i, encRawPosIndex[i], 0.0); } setDoubleParam(0, encPosIndex[0], 0.0); setDoubleParam(1, encPosIndex[1], 0.0); for (int i=0; i < encIndex; ++i) { callParamCallbacks(i, i); } unlock(); }
void motorSimAxis::process(double delta ) { double lastpos; int done = 0; lastpos = nextpoint_.axis[0].p; nextpoint_.T += delta; routeFind( route_, reroute_, &endpoint_, &nextpoint_ ); /* if (reroute_ == ROUTE_NEW_ROUTE) routePrint( route_, reroute_, &endpoint_, &nextpoint_, stdout ); */ reroute_ = ROUTE_CALC_ROUTE; /* No, do a limits check */ if (homing_ && ((lastpos - home_) * (nextpoint_.axis[0].p - home_)) <= 0) { /* Homing and have crossed the home sensor - return to home */ homing_ = 0; reroute_ = ROUTE_NEW_ROUTE; endpoint_.axis[0].p = home_; endpoint_.axis[0].v = 0.0; } if ( nextpoint_.axis[0].p > hiHardLimit_ && nextpoint_.axis[0].v > 0 ) { if (homing_) setVelocity(-endpoint_.axis[0].v, 0.0 ); else { reroute_ = ROUTE_NEW_ROUTE; endpoint_.axis[0].p = hiHardLimit_; endpoint_.axis[0].v = 0.0; } } else if (nextpoint_.axis[0].p < lowHardLimit_ && nextpoint_.axis[0].v < 0) { if (homing_) setVelocity(-endpoint_.axis[0].v, 0.0 ); else { reroute_ = ROUTE_NEW_ROUTE; endpoint_.axis[0].p = lowHardLimit_; endpoint_.axis[0].v = 0.0; } } if (nextpoint_.axis[0].v == 0) { if (!deferred_move_) { done = 1; } } else { done = 0; } setDoubleParam (pC_->motorPosition_, (nextpoint_.axis[0].p+enc_offset_)); setDoubleParam (pC_->motorEncoderPosition_, (nextpoint_.axis[0].p+enc_offset_)); setIntegerParam(pC_->motorStatusDirection_, (nextpoint_.axis[0].v > 0)); setIntegerParam(pC_->motorStatusDone_, done); setIntegerParam(pC_->motorStatusHighLimit_, (nextpoint_.axis[0].p >= hiHardLimit_)); setIntegerParam(pC_->motorStatusHome_, (nextpoint_.axis[0].p == home_)); setIntegerParam(pC_->motorStatusMoving_, !done); setIntegerParam(pC_->motorStatusLowLimit_, (nextpoint_.axis[0].p <= lowHardLimit_)); callParamCallbacks(); }
/** * Reset the data for an ROI. * \param[in] roi number * \return asynStatus */ asynStatus NDPluginROIStat::clear(epicsUInt32 roi) { asynStatus status = asynSuccess; bool stat = true; const char* functionName = "NDPluginROIStat::clear"; asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Clearing params. roi=%d\n", functionName, roi); stat = (setDoubleParam(roi, NDPluginROIStatMinValue, 0.0) == asynSuccess) && stat; stat = (setDoubleParam(roi, NDPluginROIStatMaxValue, 0.0) == asynSuccess) && stat; stat = (setDoubleParam(roi, NDPluginROIStatMeanValue, 0.0) == asynSuccess) && stat; stat = (setDoubleParam(roi, NDPluginROIStatTotal, 0.0) == asynSuccess) && stat; stat = (setDoubleParam(roi, NDPluginROIStatNet, 0.0) == asynSuccess) && stat; stat = (callParamCallbacks(roi) == asynSuccess) && stat; if (!stat) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Error clearing params. roi=%d\n", functionName, roi); status = asynError; } return status; }
asynStatus ReadASCII::writeInt32(asynUser *pasynUser, epicsInt32 value) { //Checks for updates to the index and on/off of PID lookup int function = pasynUser->reason; asynStatus status = asynSuccess; const char *paramName; const char* functionName = "writeInt32"; int LUTOn; /* Set the parameter in the parameter library. */ status = (asynStatus)setIntegerParam(function, value); if (function == P_Index) { //check lookup on getIntegerParam(P_LookUpOn, &LUTOn); if (LUTOn) { //update all column floats setDoubleParam(P_SPOut, pSP_[value]); setDoubleParam(P_P, pP_[value]); setDoubleParam(P_I, pI_[value]); setDoubleParam(P_D, pD_[value]); setDoubleParam(P_MaxHeat, pMaxHeat_[value]); } }else if (function == P_LookUpOn) { //reload file if bad if (true == fileBad) { status = readFileBasedOnParameters(); } //file may now be good - retry if (false == fileBad) { //uses the current temperature to find PID values if (value) { double curTemp; getDoubleParam(P_CurTemp, &curTemp); updatePID(getSPInd(curTemp)); } } } /* Do callbacks so higher layers see any changes */ status = (asynStatus)callParamCallbacks(); if (status) epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, name=%s, value=%d", driverName, functionName, status, function, paramName, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, name=%s, value=%d\n", driverName, functionName, function, paramName, value); return status; }
asynStatus MMC100Axis::queryPosition() { if (pc_->homing_axis_) return asynError; size_t num_read=0; char input[MMC100_STRING_SIZE]; //static const char* functionName = "MMC100Controller::queryPosition"; asynStatus ret = pc_->writeRead(input, &num_read, "%dPOS?", id_); if (ret != asynSuccess || num_read < 17) // 17 == len("#0.000000,0.000000") return asynError; // Format: #theory,encoder // So, find the comma, replace it with a null terminator, and // use atof on each of them. char *theory_pos=&input[1]; char *encoder_pos=strnchr(input, MMC100_STRING_SIZE, ','); if (!encoder_pos) { return asynError; } encoder_pos[0] = '\0'; encoder_pos++; encoderPos_=atof(encoder_pos); theoryPos_=atof(theory_pos); setDoubleParam(pc_->motorEncoderPosition_, encoderPos_ * pc_->unitScale_); setDoubleParam(pc_->motorPosition_, encoderPos_ * pc_->unitScale_); //setDoubleParam(pc_->motorPosition_, theoryPos_ * pc_->unitScale_); #if DEBUG fprintf(stderr, "encoder: %g theory: %g\n", encoderPos_, theoryPos_); #endif return asynSuccess; }
void ReadASCII::updatePID(int index) { //Updates the PID and max heater values to those in the file on the given line setDoubleParam(P_P, pP_[index]); setDoubleParam(P_I, pI_[index]); setDoubleParam(P_D, pD_[index]); setDoubleParam(P_MaxHeat, pMaxHeat_[index]); }
asynStatus ddriveAxis::queryPosition() { asynStatus ret = pc_->writeRead(encoder_pos_, "mess,%d", axisNo_); if (ret == asynSuccess) { setDoubleParam(pc_->motorEncoderPosition_, encoder_pos_ / DDRIVE_COUNTS_TO_UM); setDoubleParam(pc_->motorPosition_, encoder_pos_ / DDRIVE_COUNTS_TO_UM); } return ret; }
/** Polls the axis. * This function reads the controller position, encoder position, the limit status, the moving status, * and the drive power-on status. It does not current detect following error, etc. but this could be * added. * It calls setIntegerParam() and setDoubleParam() for each item that it polls, * and then calls callParamCallbacks() at the end. * \param[out] moving A flag that is set indicating that the axis is moving (1) or done (0). */ asynStatus C300Axis::poll(bool *moving) { int done; int num; asynStatus comStatus; // Read the current encoder position sprintf(pC_->outString_, "%s:DATA?", axisName_); comStatus = pC_->writeReadController(); if (comStatus) goto skip; // encoder position is the 9th floating point value in a comma separated list //printf("\naxisName_ = %s\n", axisName_); //printf("data string = %s\n", pC_->inString_); num = sscanf(&pC_->inString_[C300_DATA_OFFSET], "%lG", &posMonCorrectedVal_); //printf("data string = %s\n", pC_->inString_); num = sscanf(&pC_->inString_[C300_CORR_OFFSET], "%lG", &analogInScaledVal_); //printf("data string = %s\n", pC_->inString_); //printf("posMonCorrectedVal_ = %lG\n", posMonCorrectedVal_); //printf("analogInScaledVal_ = %lG\n", analogInScaledVal_); //printf("diScaleFactor_ = %f\n", diScaleFactor_); //printf("diScaleFactorInv_ = %f\n", diScaleFactorInv_); //printf("bitsPerUnit_ = %f\n", bitsPerUnit_); /*encoderPosition_ = (posMonCorrectedVal_ - analogInScaledVal_) * -1.0 * diScaleFactorInv_;*/ encoderPosition_ = (posMonCorrectedVal_ - analogInScaledVal_) * diScaleFactorInv_; //printf("encoderPosition_ = %f\n", encoderPosition_); setDoubleParam(pC_->motorEncoderPosition_,encoderPosition_); // Read the current theoretical position sprintf(pC_->outString_, "%s:POS?", axisName_); comStatus = pC_->writeReadController(); if (comStatus) goto skip; theoryPosition_ = atof(pC_->inString_); setDoubleParam(pC_->motorPosition_, theoryPosition_); //printf("theoryPosition_ = %f\n", theoryPosition_); // Read error status // Simulate dmov functionality here done = (abs(theoryPosition_ - encoderPosition_) > C300Tolerance) ? 0 : 1; setIntegerParam(pC_->motorStatusDone_, done); *moving = done ? false:true; // The limits will be fixed. // Motor doesn't have limits or home switch (maybe move this to a constructor) setIntegerParam(pC_->motorStatusHighLimit_, 0); setIntegerParam(pC_->motorStatusLowLimit_, 0); setIntegerParam(pC_->motorStatusAtHome_, 0); skip: setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0); callParamCallbacks(); return comStatus ? asynError : asynSuccess; }
asynStatus roper::getStatus() { /* NOTE: There seems to be a problem in WinView. * If this function is called immediately after acquisition is started * then the detector seems to be instantly done when getAcquireStatus() is called? * Work around this by only calling getStatus() from writeInt32 and writeFloat64 if a parameter * is actually changed, not when the ADFileNumber or other writes happen */ short result; const char *functionName = "getStatus"; VARIANT varResult; IDispatch *pROIDispatch; double top, bottom, left, right; long minX, minY, sizeX, sizeY, binX, binY; try { varResult = pExpSetup->GetParam(EXP_REVERSE, &result); setIntegerParam(ADReverseX, varResult.lVal); varResult = pExpSetup->GetParam(EXP_FLIP, &result); setIntegerParam(ADReverseY, varResult.lVal); varResult = pExpSetup->GetParam(EXP_SEQUENTS, &result); setIntegerParam(ADNumImages, varResult.lVal); varResult = pExpSetup->GetParam(EXP_SHUTTER_CONTROL, &result); setIntegerParam(RoperShutterMode, varResult.lVal); varResult = pExpSetup->GetParam(EXP_TIMING_MODE, &result); setIntegerParam(ADTriggerMode, varResult.lVal); varResult = pExpSetup->GetParam(EXP_AUTOD, &result); setIntegerParam(RoperAutoDataType, varResult.lVal); varResult = pExpSetup->GetParam(EXP_GAIN, &result); setDoubleParam(ADGain, (double)varResult.lVal); //varResult = pExpSetup->GetParam(EXP_FOCUS_NFRAME, &result); varResult = pExpSetup->GetParam(EXP_EXPOSURE, &result); setDoubleParam(ADAcquireTime, varResult.dblVal); varResult = pExpSetup->GetParam(EXP_ACTUAL_TEMP, &result); setDoubleParam(ADTemperature, varResult.dblVal); pROIDispatch = pExpSetup->GetROI(1); pROIRect->AttachDispatch(pROIDispatch); pROIRect->Get(&top, &left, &bottom, &right, &binX, &binY); minX = int(left); minY = int(top); sizeX = int(right)-int(left)+1; sizeY = int(bottom)-int(top)+1; setIntegerParam(ADMinX, minX); setIntegerParam(ADMinY, minY); setIntegerParam(ADSizeX, sizeX); setIntegerParam(ADSizeY, sizeY); } catch(CException *pEx) { pEx->GetErrorMessage(this->errorMessage, sizeof(this->errorMessage)); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s:%s: exception = %s\n", driverName, functionName, this->errorMessage); pEx->Delete(); return(asynError); } callParamCallbacks(); return(asynSuccess); }
/** Simulation task that runs as a separate thread. When the P_Run parameter is set to 1 * to rub the simulation it computes a 1 kHz sine wave with 1V amplitude and user-controllable * noise, and displays it on * a simulated scope. It computes waveforms for the X (time) and Y (volt) axes, and computes * statistics about the waveform. */ void testAsynPortDriver::simTask(void) { /* This thread computes the waveform and does callbacks with it */ double timePerDiv, voltsPerDiv, voltOffset, triggerDelay, noiseAmplitude; double updateTime, minValue, maxValue, meanValue; double time, timeStep; double noise, yScale; int run, i, maxPoints; double pi=4.0*atan(1.0); lock(); /* Loop forever */ while (1) { getDoubleParam(P_UpdateTime, &updateTime); getIntegerParam(P_Run, &run); // Release the lock while we wait for a command to start or wait for updateTime unlock(); if (run) epicsEventWaitWithTimeout(eventId_, updateTime); else (void) epicsEventWait(eventId_); // Take the lock again lock(); /* run could have changed while we were waiting */ getIntegerParam(P_Run, &run); if (!run) continue; getIntegerParam(P_MaxPoints, &maxPoints); getDoubleParam (P_TimePerDiv, &timePerDiv); getDoubleParam (P_VoltsPerDiv, &voltsPerDiv); getDoubleParam (P_VoltOffset, &voltOffset); getDoubleParam (P_TriggerDelay, &triggerDelay); getDoubleParam (P_NoiseAmplitude, &noiseAmplitude); time = triggerDelay; timeStep = timePerDiv * NUM_DIVISIONS / maxPoints; minValue = 1e6; maxValue = -1e6; meanValue = 0.; yScale = 1.0 / voltsPerDiv; for (i=0; i<maxPoints; i++) { noise = noiseAmplitude * (rand()/(double)RAND_MAX - 0.5); pData_[i] = AMPLITUDE * (sin(time*FREQUENCY*2*pi)) + noise; /* Compute statistics before doing the yOffset and yScale */ if (pData_[i] < minValue) minValue = pData_[i]; if (pData_[i] > maxValue) maxValue = pData_[i]; meanValue += pData_[i]; pData_[i] = NUM_DIVISIONS/2 + yScale * (voltOffset + pData_[i]); time += timeStep; } updateTimeStamp(); meanValue = meanValue/maxPoints; setDoubleParam(P_MinValue, minValue); setDoubleParam(P_MaxValue, maxValue); setDoubleParam(P_MeanValue, meanValue); callParamCallbacks(); doCallbacksFloat64Array(pData_, maxPoints, P_Waveform, 0); } }
/** Constructor for NDPluginAttribute; most parameters are simply passed to NDPluginDriver::NDPluginDriver. * * \param[in] portName The name of the asyn port driver to be created. * \param[in] queueSize The number of NDArrays that the input queue for this plugin can hold when * NDPluginDriverBlockingCallbacks=0. Larger queues can decrease the number of dropped arrays, * at the expense of more NDArray buffers being allocated from the underlying driver's NDArrayPool. * \param[in] blockingCallbacks Initial setting for the NDPluginDriverBlockingCallbacks flag. * 0=callbacks are queued and executed by the callback thread; 1 callbacks execute in the thread * of the driver doing the callbacks. * \param[in] NDArrayPort Name of asyn port driver for initial source of NDArray callbacks. * \param[in] NDArrayAddr asyn port driver address for initial source of NDArray callbacks. * \param[in] maxAttributes The maximum number of attributes that this plugin will support * \param[in] maxBuffers The maximum number of NDArray buffers that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited number of buffers. * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited amount of memory. * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. */ NDPluginAttribute::NDPluginAttribute(const char *portName, int queueSize, int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr, int maxAttributes, int maxBuffers, size_t maxMemory, int priority, int stackSize) /* Invoke the base class constructor */ : NDPluginDriver(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, maxAttributes, maxBuffers, maxMemory, asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask, asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask, ASYN_MULTIDEVICE, 1, priority, stackSize, 1) { int i; static const char *functionName = "NDPluginAttribute::NDPluginAttribute"; maxAttributes_ = maxAttributes; if (maxAttributes_ < 1) maxAttributes_ = 1; /* parameters */ createParam(NDPluginAttributeAttrNameString, asynParamOctet, &NDPluginAttributeAttrName); createParam(NDPluginAttributeResetString, asynParamInt32, &NDPluginAttributeReset); createParam(NDPluginAttributeValString, asynParamFloat64, &NDPluginAttributeVal); createParam(NDPluginAttributeValSumString, asynParamFloat64, &NDPluginAttributeValSum); createParam(NDPluginAttributeTSControlString, asynParamInt32, &NDPluginAttributeTSControl); createParam(NDPluginAttributeTSNumPointsString, asynParamInt32, &NDPluginAttributeTSNumPoints); createParam(NDPluginAttributeTSCurrentPointString, asynParamInt32, &NDPluginAttributeTSCurrentPoint); createParam(NDPluginAttributeTSAcquiringString, asynParamInt32, &NDPluginAttributeTSAcquiring); createParam(NDPluginAttributeTSArrayValueString, asynParamFloat64Array, &NDPluginAttributeTSArrayValue); /* Set the plugin type string */ setStringParam(NDPluginDriverPluginType, "NDPluginAttribute"); setIntegerParam(NDPluginAttributeTSNumPoints, DEFAULT_NUM_TSPOINTS); pTSArray_ = static_cast<epicsFloat64 **>(calloc(maxAttributes_, sizeof(epicsFloat64 *))); if (pTSArray_ == NULL) { perror(functionName); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Error from calloc for pTSArray_.\n", functionName); } for (i=0; i<maxAttributes_; i++) { pTSArray_[i] = static_cast<epicsFloat64*>(calloc(DEFAULT_NUM_TSPOINTS, sizeof(epicsFloat64))); setDoubleParam(i, NDPluginAttributeVal, 0.0); setDoubleParam(i, NDPluginAttributeValSum, 0.0); setStringParam(i, NDPluginAttributeAttrName, ""); if (pTSArray_[i] == NULL) { perror(functionName); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Error from calloc for pTSArray_.\n", functionName); } callParamCallbacks(i); } // Disable ArrayCallbacks. // This plugin currently does not do array callbacks, so make the setting reflect the behavior setIntegerParam(NDArrayCallbacks, 0); /* Try to connect to the array port */ connectToArrayPort(); }
asynStatus NDPluginCircularBuff::calculateTrigger(NDArray *pArray, int *trig) { NDAttribute *trigger; char triggerString[256]; double triggerValue; double calcResult; int status; int preTrigger, postTrigger, currentImage, triggered; static const char *functionName="calculateTrigger"; *trig = 0; getIntegerParam(NDCircBuffPreTrigger, &preTrigger); getIntegerParam(NDCircBuffPostTrigger, &postTrigger); getIntegerParam(NDCircBuffCurrentImage, ¤tImage); getIntegerParam(NDCircBuffTriggered, &triggered); triggerCalcArgs_[0] = epicsNAN; triggerCalcArgs_[1] = epicsNAN; triggerCalcArgs_[2] = preTrigger; triggerCalcArgs_[3] = postTrigger; triggerCalcArgs_[4] = currentImage; triggerCalcArgs_[5] = triggered; getStringParam(NDCircBuffTriggerA, sizeof(triggerString), triggerString); trigger = pArray->pAttributeList->find(triggerString); if (trigger != NULL) { status = trigger->getValue(NDAttrFloat64, &triggerValue); if (status == asynSuccess) { triggerCalcArgs_[0] = triggerValue; } } getStringParam(NDCircBuffTriggerB, sizeof(triggerString), triggerString); trigger = pArray->pAttributeList->find(triggerString); if (trigger != NULL) { status = trigger->getValue(NDAttrFloat64, &triggerValue); if (status == asynSuccess) { triggerCalcArgs_[1] = triggerValue; } } setDoubleParam(NDCircBuffTriggerAVal, triggerCalcArgs_[0]); setDoubleParam(NDCircBuffTriggerBVal, triggerCalcArgs_[1]); status = calcPerform(triggerCalcArgs_, &calcResult, triggerCalcPostfix_); if (status) { asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s error evaluating expression=%s\n", driverName, functionName, calcErrorStr(status)); return asynError; } if (!isnan(calcResult) && !isinf(calcResult) && (calcResult != 0)) *trig = 1; setDoubleParam(NDCircBuffTriggerCalcVal, calcResult); return asynSuccess; }
asynStatus shamrock::getStatus() { int error; asynStatus status; int grating; float wavelength; float width; int i; static const char *functionName = "getStatus"; int port; //Get Flipper Status for (i=0; i<MAX_FLIPPER_MIRRORS; i++) { if (flipperMirrorIsPresent_[i] == 0) continue; error = ShamrockGetFlipperMirror(shamrockId_, i+1, &port); status = checkError(error, functionName, "ShamrockGetFlipperMirror"); if (status) return asynError; setIntegerParam(i, SRFlipperMirrorPort_, port); } error = ShamrockGetGrating(shamrockId_, &grating); status = checkError(error, functionName, "ShamrockGetGrating"); if (status) return asynError; setIntegerParam(SRGrating_, grating); error = ShamrockGetWavelength(shamrockId_, &wavelength); status = checkError(error, functionName, "ShamrockGetWavelength"); if (status) return asynError; setDoubleParam(SRWavelength_, wavelength); for (i=0; i<MAX_SLITS; i++) { setDoubleParam(i, SRSlitSize_, 0.); if (slitIsPresent_[i] == 0) continue; error = ShamrockGetAutoSlitWidth(shamrockId_, i+1, &width); status = checkError(error, functionName, "ShamrockGetAutoSlitWidth"); if (status) return asynError; setDoubleParam(i, SRSlitSize_, width); } error = ShamrockGetCalibration(shamrockId_, calibration_, numPixels_); status = checkError(error, functionName, "ShamrockGetCalibration"); setDoubleParam(0, SRMinWavelength_, calibration_[0]); setDoubleParam(0, SRMaxWavelength_, calibration_[numPixels_-1]); // We need to find a C/C++ library to do 3'rd order polynomial fit // For now we do a first order fit! //double slope = (calibration_[numPixels_-1] - calibration_[0]) / (numPixels_-1); for (i=0; i<MAX_ADDR; i++) { callParamCallbacks(i); } doCallbacksFloat32Array(calibration_, numPixels_, SRCalibration_, 0); return asynSuccess; }
/** Constructor for NDPluginAttribute; most parameters are simply passed to NDPluginDriver::NDPluginDriver. * * \param[in] portName The name of the asyn port driver to be created. * \param[in] queueSize The number of NDArrays that the input queue for this plugin can hold when * NDPluginDriverBlockingCallbacks=0. Larger queues can decrease the number of dropped arrays, * at the expense of more NDArray buffers being allocated from the underlying driver's NDArrayPool. * \param[in] blockingCallbacks Initial setting for the NDPluginDriverBlockingCallbacks flag. * 0=callbacks are queued and executed by the callback thread; 1 callbacks execute in the thread * of the driver doing the callbacks. * \param[in] NDArrayPort Name of asyn port driver for initial source of NDArray callbacks. * \param[in] NDArrayAddr asyn port driver address for initial source of NDArray callbacks. * \param[in] maxBuffers The maximum number of NDArray buffers that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited number of buffers. * \param[in] maxMemory The maximum amount of memory that the NDArrayPool for this driver is * allowed to allocate. Set this to -1 to allow an unlimited amount of memory. * \param[in] priority The thread priority for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. * \param[in] stackSize The stack size for the asyn port driver thread if ASYN_CANBLOCK is set in asynFlags. * \param[in] maxTimeSeries The max size of the time series array * \param[in] attrName The name of the NDArray attribute */ NDPluginAttribute::NDPluginAttribute(const char *portName, int queueSize, int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr, int maxBuffers, size_t maxMemory, int priority, int stackSize, int maxTimeSeries, const char *attrName) /* Invoke the base class constructor */ : NDPluginDriver(portName, queueSize, blockingCallbacks, NDArrayPort, NDArrayAddr, 1, NUM_NDPLUGIN_ATTR_PARAMS, maxBuffers, maxMemory, asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask, asynInt32ArrayMask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask, ASYN_MULTIDEVICE, 1, priority, stackSize) { static const char *functionName = "NDPluginAttribute::NDPluginAttribute"; /* parameters */ createParam(NDPluginAttributeNameString, asynParamOctet, &NDPluginAttributeName); createParam(NDPluginAttributeAttrNameString, asynParamOctet, &NDPluginAttributeAttrName); createParam(NDPluginAttributeResetString, asynParamInt32, &NDPluginAttributeReset); createParam(NDPluginAttributeUpdateString, asynParamInt32, &NDPluginAttributeUpdate); createParam(NDPluginAttributeValString, asynParamFloat64, &NDPluginAttributeVal); createParam(NDPluginAttributeValSumString, asynParamFloat64, &NDPluginAttributeValSum); createParam(NDPluginAttributeArrayString, asynParamFloat64Array, &NDPluginAttributeArray); createParam(NDPluginAttributeDataTypeString, asynParamInt32, &NDPluginAttributeDataType); createParam(NDPluginAttributeUpdatePeriodString, asynParamFloat64, &NDPluginAttributeUpdatePeriod); /* Set the plugin type string */ setStringParam(NDPluginDriverPluginType, "NDPluginAttribute"); maxTimeSeries_ = maxTimeSeries; pTimeSeries_ = static_cast<epicsFloat64*>(calloc(maxTimeSeries_, sizeof(epicsFloat64))); if (pTimeSeries_ == NULL) { perror(functionName); asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Error from calloc for pTimeSeries_.\n", functionName); } currentPoint_ = 0; arrayUpdate_ = 1; valueSum_ = 0.0; /* Set the attribute name */ /* This can be set at runtime too.*/ setStringParam(NDPluginAttributeAttrName, attrName); setDoubleParam(NDPluginAttributeVal, 0.0); setDoubleParam(NDPluginAttributeValSum, 0.0); /* Try to connect to the array port */ connectToArrayPort(); callParamCallbacks(); }
/** This thread reads status strings from the status socket, makes the string available to EPICS, and * sends an eveny when it detects acquisition complete, etc. */ void BISDetector::statusTask() { int status = asynSuccess; char response[MAX_MESSAGE_SIZE]; char *p; double timeout=-1.0; size_t nread; int eomReason; int acquire; int framesize; int open; double temperature; while(1) { status = pasynOctetSyncIO->read(this->pasynUserStatus, response, sizeof(response), timeout, &nread, &eomReason); if (status == asynSuccess) { this->lock(); setStringParam(BISStatus, response); getIntegerParam(ADAcquire, &acquire); if (strstr(response, "[INSTRUMENTQUEUE /PROCESSING=0]")) { if (acquire) { epicsEventSignal(this->readoutEventId); } } else if (strstr(response, "[CCDTEMPERATURE")) { p = strstr(response, "DEGREESC="); sscanf(p, "DEGREESC=%lf", &temperature); setDoubleParam(ADTemperature, temperature); } else if (strstr(response, "[DETECTORSTATUS")) { p = strstr(response, "FRAMESIZE="); sscanf(p, "FRAMESIZE=%d", &framesize); p = strstr(response, "CCDTEMP="); sscanf(p, "CCDTEMP=%lf", &temperature); setIntegerParam(ADSizeX, framesize); setIntegerParam(ADSizeY, framesize); setDoubleParam(ADTemperature, temperature); } else if (strstr(response, "[SHUTTERSTATUS")) { p = strstr(response, "STATUS="); sscanf(p, "STATUS=%d", &open); setIntegerParam(ADShutterStatus, open); } callParamCallbacks(); /* Sleep a short while to allow EPICS record to process * before sending the next string */ epicsThreadSleep(0.01); this->unlock(); } } }
/** Called when asyn clients call pasynFloat64->write(). * \param[in] pasynUser pasynUser structure that encodes the reason and address. * \param[in] value Value to write. */ asynStatus testErrors::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; int itemp; const char *paramName; const char* functionName = "writeFloat64"; /* Get the current error status */ getIntegerParam(P_StatusReturn, &itemp); status = (asynStatus)itemp; /* Fetch the parameter string name for use in debugging */ getParamName(function, ¶mName); /* Set the parameter in the parameter library. */ setDoubleParam(function, value); /* Set the parameter status in the parameter library. */ setParamStatus(function, status); /* Do callbacks so higher layers see any changes */ callParamCallbacks(); if (status) epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, name=%s, value=%f", driverName, functionName, status, function, paramName, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, name=%s, value=%f\n", driverName, functionName, function, paramName, value); return status; }
asynStatus drvFastSweep::writeInt32(asynUser *pasynUser, epicsInt32 value) { int command = pasynUser->reason; asynStatus status=asynSuccess; /* Set the parameter in the parameter library. */ status = setIntegerParam(command, value); if (command == mcaStartAcquire_) { if (!acquiring_) { acquiring_ = 1; setIntegerParam(mcaAcquiring_, acquiring_); epicsTimeGetCurrent(&startTime_); } } else if (command == mcaStopAcquire_) { stopAcquire(); } else if (command == mcaErase_) { memset(pData_, 0, maxPoints_ * maxSignals_ * sizeof(int)); numAcquired_ = 0; /* Reset the elapsed time */ elapsedTime_ = 0; setDoubleParam(mcaElapsedRealTime_, elapsedTime_); epicsTimeGetCurrent(&startTime_); } else if (command == mcaNumChannels_) { if ((value < 1) || (value > maxPoints_)) status = asynError; else numPoints_ = value; } callParamCallbacks(); return(status); }
void drvFastSweep::nextPoint(epicsInt32 *newData) { int i; int offset; epicsTimeStamp now; if (!acquiring_) return; offset = numAcquired_; for (i = 0; i < maxSignals_; i++) { pData_[offset] = newData[i]; offset += maxPoints_; } numAcquired_++; if (numAcquired_ >= numPoints_) { stopAcquire(); } epicsTimeGetCurrent(&now); elapsedTime_ = epicsTimeDiffInSeconds(&now, &startTime_); if ((realTime_ > 0) && (elapsedTime_ >= realTime_)) { stopAcquire(); } setIntegerParam(fastSweepCurrentChannel_, numAcquired_); setDoubleParam(mcaElapsedRealTime_, elapsedTime_); callParamCallbacks(); }
asynStatus NDPluginDLL::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; int k; int enum_param; /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the * status at the end, but that's OK */ status = setDoubleParam(function, value); for (k=0; k<num_controllers; k++) { if ((*mapAsyn2DLL).find(function)!= (*mapAsyn2DLL).end()) { enum_param = (*mapAsyn2DLL)[function]; controllers[k]->putDoubleParam(enum_param,(double)value); } } /* Do callbacks so higher layers see any changes */ callParamCallbacks(); return status; }
motorSimController::motorSimController(const char *portName, int numAxes, int priority, int stackSize) : asynMotorController(portName, numAxes, NUM_SIM_CONTROLLER_PARAMS, asynInt32Mask | asynFloat64Mask, asynInt32Mask | asynFloat64Mask, ASYN_CANBLOCK | ASYN_MULTIDEVICE, 1, // autoconnect priority, stackSize) { int axis; motorSimControllerNode *pNode; if (!motorSimControllerListInitialized) { motorSimControllerListInitialized = 1; ellInit(&motorSimControllerList); } // We should make sure this portName is not already in the list */ pNode = (motorSimControllerNode*) calloc(1, sizeof(motorSimControllerNode)); pNode->portName = epicsStrDup(portName); pNode->pController = this; ellAdd(&motorSimControllerList, (ELLNODE *)pNode); if (numAxes < 1 ) numAxes = 1; numAxes_ = numAxes; this->movesDeferred_ = 0; for (axis=0; axis<numAxes; axis++) { new motorSimAxis(this, axis, DEFAULT_LOW_LIMIT, DEFAULT_HI_LIMIT, DEFAULT_HOME, DEFAULT_START); setDoubleParam(axis, this->motorPosition_, DEFAULT_START); } this->motorThread_ = epicsThreadCreate("motorSimThread", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackMedium), (EPICSTHREADFUNC) motorSimTaskC, (void *) this); }
/** Called when asyn clients call pasynFloat64->write(). * This function performs actions for some parameters. * For all parameters it sets the value in the parameter library and calls any registered callbacks.. * \param[in] pasynUser pasynUser structure that encodes the reason and address. * \param[in] value Value to write. */ asynStatus NDPluginStats::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; int computeCentroid, computeProfiles; static const char *functionName = "writeFloat64"; /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the * status at the end, but that's OK */ status = setDoubleParam(function, value); if (function == NDPluginStatsCentroidThreshold) { getIntegerParam(NDPluginStatsComputeCentroid, &computeCentroid); if (computeCentroid && this->pArrays[0]) { doComputeCentroid(this->pArrays[0]); getIntegerParam(NDPluginStatsComputeProfiles, &computeProfiles); if (computeProfiles) doComputeProfiles(this->pArrays[0]); } } else { /* If this parameter belongs to a base class call its method */ if (function < FIRST_NDPLUGIN_STATS_PARAM) status = NDPluginDriver::writeFloat64(pasynUser, value); } /* Do callbacks so higher layers see any changes */ callParamCallbacks(); if (status) asynPrint(pasynUser, ASYN_TRACE_ERROR, "%s:%s: error, status=%d function=%d, value=%f\n", driverName, functionName, status, function, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, value=%f\n", driverName, functionName, function, value); return status; }
/** Called when asyn clients call pasynFloat64->write(). * For all parameters it sets the value in the parameter library and calls any registered callbacks.. * \param[in] pasynUser pasynUser structure that encodes the reason and address. * \param[in] value Value to write. */ asynStatus DSA2000::writeFloat64(asynUser *pasynUser, epicsFloat64 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; const char *paramName; const char* functionName = "writeInt32"; /* Set the parameter in the parameter library. */ setDoubleParam(function, value); /* Fetch the parameter string name for possible use in debugging */ getParamName(function, ¶mName); if (function == P_DACSetting) { status = setHVStatus(); } else { /* All other parameters just get set in parameter list, no need to * act on them here */ } /* Do callbacks so higher layers see any changes */ callParamCallbacks(); if (status) epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, name=%s, value=%f", driverName, functionName, status, function, paramName, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, name=%s, value=%f\n", driverName, functionName, function, paramName, value); return status; }
asynStatus sampleChanger::writeOctet(asynUser *pasynUser, const char *value, size_t maxChars, size_t *nActual) { int function = pasynUser->reason; const char* functionName = "writeOctet"; asynStatus status = asynSuccess; const char *paramName = NULL; getParamName(function, ¶mName); //printf("value: %s\n", value); if (function == P_recalc) { converter c(m_dims); c.createLookup(); setDoubleParam(P_outval, ++m_outval); *nActual = strlen(value); //printf("Here %s %f\n", m_fileName.c_str(), m_outval); } else { epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s:%s: status=%d, function=%d, name=%s, value=%s, error=%s", driverName, functionName, status, function, paramName, value, "unknown parameter"); status = asynError; *nActual = 0; } callParamCallbacks(); asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s:%s: function=%d, name=%s, value=%s\n", driverName, functionName, function, paramName, value); return status; }
/** Sets an float64 parameter. * \param[in] pasynUser asynUser structure that contains the function code in pasynUser->reason. * \param[in] value The value for this parameter * * Takes action if the function code requires it. */ asynStatus shamrock::writeFloat64( asynUser *pasynUser, epicsFloat64 value) { asynStatus status = asynSuccess; int error; int function = pasynUser->reason; int addr; static const char *functionName = "writeFloat64"; pasynManager->getAddr(pasynUser, &addr); if (addr < 0) addr=0; /* Set the value in the parameter library. This may change later but that's OK */ status = setDoubleParam(addr, function, value); if (function == SRWavelength_) { error = ShamrockSetWavelength(shamrockId_, (float) value); status = checkError(error, functionName, "ShamrockSetWavelength"); } else if (function == SRSlitSize_) { if (slitIsPresent_[addr]) { error = ShamrockSetAutoSlitWidth(shamrockId_, addr+1, (float) value); status = checkError(error, functionName, "ShamrockSetSlit"); } } getStatus(); asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s::%s function=%d, value=%f, status=%d\n", driverName, functionName, function, value, status); callParamCallbacks(addr); return status; }
asynStatus asynNDArrayDriver::readFloat64(asynUser *pasynUser, epicsFloat64 *value) { int function = pasynUser->reason; asynStatus status = asynSuccess; // Just read the status of the NDArrayPool if (function == NDPoolMaxMemory) { setDoubleParam(function, this->pNDArrayPool->maxMemory() / MEGABYTE_DBL); } else if (function == NDPoolUsedMemory) { setDoubleParam(function, this->pNDArrayPool->memorySize() / MEGABYTE_DBL); } // Call base class status = asynPortDriver::readFloat64(pasynUser, value); return status; }
// zero counters st start of run, done early before actual readbacks void isisdaeDriver::zeroRunCounters() { setDoubleParam(P_GoodUAH, 0.0); setDoubleParam(P_GoodUAHPeriod, 0.0); setDoubleParam(P_TotalUAmps, 0.0); setIntegerParam(P_TotalCounts, 0); setIntegerParam(P_GoodFramesTotal, 0); setIntegerParam(P_GoodFramesPeriod, 0); setIntegerParam(P_RawFramesTotal, 0); setIntegerParam(P_RawFramesPeriod, 0); setIntegerParam(P_RunDurationTotal, 0); setIntegerParam(P_RunDurationPeriod, 0); setIntegerParam(P_MonitorCounts, 0); setDoubleParam(P_TotalDaeCounts, 0.0); setDoubleParam(P_CountRate, 0.0); callParamCallbacks(); }
void testAsynPortDriver::setTimePerDiv() { int microSecPerDiv; // Integer times are in microseconds getIntegerParam(P_TimePerDivSelect, µSecPerDiv); setDoubleParam(P_TimePerDiv, microSecPerDiv / 1000000.); }
////////////////////////////////////////////////////////////////////////////////////////////////// // // // void CLeyboldSimPortDriver::setDefaultValues(size_t TableIndex) // // // // Descreiption: // // This method sets a set of normal 'typical' values that would be expected from a // // pump running in steady state. // // // ////////////////////////////////////////////////////////////////////////////////////////////////// void CLeyboldSimPortDriver::setDefaultValues(size_t TableIndex) { // The running state has just been enabled. setIntegerParam(TableIndex, RUNNING, On); // Not set here : FAULT // Reset, FaultStr, WarningTemperatureStr, WarningHighLoadStr and WarningPurgeStr are not used. setIntegerParam(TableIndex, DISCONNECTED, 0); setIntegerParam(TableIndex, WARNINGTEMPERATURE, 0); setIntegerParam(TableIndex, WARNINGHIGHLOAD, 0); setIntegerParam(TableIndex, WARNINGPURGE, 0); setIntegerParam(TableIndex, STATORFREQUENCY, NormalStatorFrequency); setIntegerParam(TableIndex, CONVERTERTEMPERATURE, 50); setDoubleParam (TableIndex, MOTORCURRENT, 1.1); setIntegerParam(TableIndex, PUMPTEMPERATURE, 65); setDoubleParam (TableIndex, CIRCUITVOLTAGE, 60.2); }
void testAsynPortDriver::setVoltsPerDiv() { int mVPerDiv; // Integer volts are in mV getIntegerParam(P_VoltsPerDivSelect, &mVPerDiv); setDoubleParam(P_VoltsPerDiv, mVPerDiv / 1000.); }
/** Polls the axis. * This function reads motor position, limit status, home status, and moving status * It calls setIntegerParam() and setDoubleParam() for each item that it polls, * and then calls callParamCallbacks() at the end. * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */ asynStatus SMC100Axis::poll(bool *moving) { int done; //int driveOn; int limit; double position; asynStatus comStatus; // Read the current motor position sprintf(pC_->outString_, "%1dTP", axisNo_ + 1); comStatus = pC_->writeReadController(); if (comStatus) goto skip; // The response string is of the form "1TP-0.123" position = (atof(&pC_->inString_[3]) / stepSize_); //printf("\n * * * * SMC100 stepSize_ : %f \n", stepSize_); setDoubleParam(pC_->motorPosition_, position); // Read the moving status of this motor sprintf(pC_->outString_, "%1dTS", axisNo_ + 1); comStatus = pC_->writeReadController(); if (comStatus) goto skip; // The response string is of the form "1TS000028" // May need to add logic for moving while homing done = ((pC_->inString_[7] == '2') && (pC_->inString_[8] == '8')) ? 0:1; setIntegerParam(pC_->motorStatusDone_, done); *moving = done ? false:true; // Read the limit status // The response string is of the form "1TS001328" // // The stage I tested this with is a GTS30V vertical jack. When the controller is initialized // for this device using Newport's software, +25 and -5 limits get set. The controller does not // let you set limits outside these values, so I never was able to run into a "hard" limit. // The controller also does not allow position settings outside these limits, and does not give // an indication. So, my recommendation is to leave the controller's travel limits set to the // Newport defaults, and use the motor record's soft limits, set to the controller's limits or within. // // Should a hard limit be actually encounted, this code *should* report it to the motor record limit = (pC_->inString_[6] == '2') ? 1:0; setIntegerParam(pC_->motorStatusHighLimit_, limit); limit = (pC_->inString_[6] == '1') ? 1:0; setIntegerParam(pC_->motorStatusLowLimit_, limit); limit = ((pC_->inString_[7] == '3') && (pC_->inString_[8] == '2')) ? 1:0; setIntegerParam(pC_->motorStatusAtHome_, limit); // Read the drive power on status //sprintf(pC_->outString_, "#%02dE", axisNo_ + 1); //comStatus = pC_->writeReadController(); //if (comStatus) goto skip; //driveOn = (pC_->inString_[5] == '1') ? 1:0; //setIntegerParam(pC_->motorStatusPowerOn_, driveOn); //setIntegerParam(pC_->motorStatusProblem_, 0); skip: setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0); callParamCallbacks(); return comStatus ? asynError : asynSuccess; }