asynStatus isisdaeDriver::readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements, size_t *nIn) { asynStatus stat = readArray(pasynUser, "readFloat64Array", value, nElements, nIn); callParamCallbacks(); // this flushes P_ErrMsgs doCallbacksFloat64Array(value, *nIn, pasynUser->reason, 0); return stat; }
/** 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); } }
void NDPluginAttribute::doTimeSeriesCallbacks() { int currentTSPoint; int i; getIntegerParam(NDPluginAttributeTSCurrentPoint, ¤tTSPoint); for (i=0; i<maxAttributes_; i++) { doCallbacksFloat64Array(pTSArray_[i], currentTSPoint, NDPluginAttributeTSArrayValue, i); } }
asynStatus NDPluginStats::doComputeProfilesT(NDArray *pArray) { epicsType *pData = (epicsType *)pArray->pData; epicsType *pCentroid, *pCursor; size_t ix, iy; int itemp; if (pArray->ndims > 2) return(asynError); /* Compute the X and Y profiles at the centroid and cursor positions */ getIntegerParam (NDPluginStatsCursorX, &itemp); this->cursorX = itemp; getIntegerParam (NDPluginStatsCursorY, &itemp); this->cursorY = itemp; this->unlock(); iy = (size_t) (this->centroidY + 0.5); iy = MAX(iy, 0); iy = MIN(iy, this->profileSizeY-1); pCentroid = pData + iy*this->profileSizeX; iy = this->cursorY; iy = MAX(iy, 0); iy = MIN(iy, this->profileSizeY-1); pCursor = pData + iy*this->profileSizeX; for (ix=0; ix<this->profileSizeX; ix++) { this->profileX[profCentroid][ix] = *pCentroid++; this->profileX[profCursor][ix] = *pCursor++; } ix = (size_t) (this->centroidX + 0.5); ix = MAX(ix, 0); ix = MIN(ix, this->profileSizeX-1); pCentroid = pData + ix; ix = this->cursorX; ix = MAX(ix, 0); ix = MIN(ix, this->profileSizeX-1); pCursor = pData + ix; for (iy=0; iy<this->profileSizeY; iy++) { this->profileY[profCentroid][iy] = *pCentroid; this->profileY[profCursor][iy] = *pCursor; pCentroid += this->profileSizeX; pCursor += this->profileSizeX; } this->lock(); doCallbacksFloat64Array(this->profileX[profAverage], this->profileSizeX, NDPluginStatsProfileAverageX, 0); doCallbacksFloat64Array(this->profileY[profAverage], this->profileSizeY, NDPluginStatsProfileAverageY, 0); doCallbacksFloat64Array(this->profileX[profThreshold], this->profileSizeX, NDPluginStatsProfileThresholdX, 0); doCallbacksFloat64Array(this->profileY[profThreshold], this->profileSizeY, NDPluginStatsProfileThresholdY, 0); doCallbacksFloat64Array(this->profileX[profCentroid], this->profileSizeX, NDPluginStatsProfileCentroidX, 0); doCallbacksFloat64Array(this->profileY[profCentroid], this->profileSizeY, NDPluginStatsProfileCentroidY, 0); doCallbacksFloat64Array(this->profileX[profCursor], this->profileSizeX, NDPluginStatsProfileCursorX, 0); doCallbacksFloat64Array(this->profileY[profCursor], this->profileSizeY, NDPluginStatsProfileCursorY, 0); return(asynSuccess); }
asynStatus NDPluginAttribute::writeInt32(asynUser *pasynUser, epicsInt32 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; static const char *functionName = "NDPluginAttribute::writeInt32"; /* Set the parameter in the parameter library. */ status = (asynStatus) setIntegerParam(function, value); if (function == NDPluginAttributeReset) { setDoubleParam(NDPluginAttributeVal, 0.0); setDoubleParam(NDPluginAttributeValSum, 0.0); //Clear the time series array memset(pTimeSeries_, 0, maxTimeSeries_*sizeof(epicsFloat64)); doCallbacksFloat64Array(this->pTimeSeries_, maxTimeSeries_, NDPluginAttributeArray, 0); currentPoint_ = 0; valueSum_ = 0.0; } else if (function == NDPluginAttributeUpdate) { //Update the data array by hand. doCallbacksFloat64Array(this->pTimeSeries_, maxTimeSeries_, NDPluginAttributeArray, 0); } else { /* If this parameter belongs to a base class call its method */ if (function < FIRST_NDPLUGIN_ATTR_PARAM) status = NDPluginDriver::writeInt32(pasynUser, value); } /* Do callbacks so higher layers see any changes */ status = (asynStatus) callParamCallbacks(); if (status) epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s: status=%d, function=%d, value=%d", functionName, status, function, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s: function=%d, value=%d\n", functionName, function, value); return status; }
/** Callback task that runs as a separate thread. */ void testErrors::callbackTask(void) { asynStatus currentStatus; int itemp; epicsInt32 iVal; epicsFloat64 dVal; int i; char octetValue[20]; /* Loop forever */ while (1) { lock(); getIntegerParam(P_StatusReturn, &itemp); currentStatus = (asynStatus)itemp; getIntegerParam(P_Int32Value, &iVal); iVal++; if (iVal > 15) iVal=0; setIntegerParam(P_Int32Value, iVal); setParamStatus(P_Int32Value, currentStatus); getDoubleParam(P_Float64Value, &dVal); dVal += 0.1; setDoubleParam(P_Float64Value, dVal); setParamStatus(P_Float64Value, currentStatus); sprintf(octetValue, "%.1f", dVal); setParamStatus(P_UInt32DigitalValue, currentStatus); setStringParam(P_OctetValue, octetValue); setParamStatus(P_OctetValue, currentStatus); setParamStatus(P_Float64ArrayValue, 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); doCallbacksInt8Array(int8ArrayValue_, MAX_ARRAY_POINTS, P_Int8ArrayValue, 0); setParamStatus(P_Int16ArrayValue, currentStatus); doCallbacksInt16Array(int16ArrayValue_, MAX_ARRAY_POINTS, P_Int16ArrayValue, 0); setParamStatus(P_Int32ArrayValue, currentStatus); doCallbacksInt32Array(int32ArrayValue_, MAX_ARRAY_POINTS, P_Int32ArrayValue, 0); setParamStatus(P_Float32ArrayValue, currentStatus); doCallbacksFloat32Array(float32ArrayValue_, MAX_ARRAY_POINTS, P_Float32ArrayValue, 0); setParamStatus(P_Float64ArrayValue, currentStatus); doCallbacksFloat64Array(float64ArrayValue_, MAX_ARRAY_POINTS, P_Float64ArrayValue, 0); unlock(); epicsThreadSleep(CALLBACK_PERIOD); } }
void NDPluginROIStat::doTimeSeriesCallbacks() { double *pData; /* Loop over the ROIs in this driver */ for (int roi=0; roi<maxROIs_; ++roi) { pData = timeSeries_ + (roi * MAX_TIME_SERIES_TYPES * numTSPoints_); doCallbacksFloat64Array(pData + TSMinValue*numTSPoints_, currentTSPoint_, NDPluginROIStatTSMinValue, roi); doCallbacksFloat64Array(pData + TSMaxValue*numTSPoints_, currentTSPoint_, NDPluginROIStatTSMaxValue, roi); doCallbacksFloat64Array(pData + TSMeanValue*numTSPoints_, currentTSPoint_, NDPluginROIStatTSMeanValue, roi); doCallbacksFloat64Array(pData + TSTotal*numTSPoints_, currentTSPoint_, NDPluginROIStatTSTotal, roi); doCallbacksFloat64Array(pData + TSNet*numTSPoints_, currentTSPoint_, NDPluginROIStatTSNet, roi); doCallbacksFloat64Array(pData + TSTimestamp*numTSPoints_, currentTSPoint_, NDPluginROIStatTSTimestamp, roi); } }
/** 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_); } }
/** Callback function that is called by the NDArray driver with new NDArray data. * Does image statistics. * \param[in] pArray The NDArray from the callback. */ void NDPluginStats::processCallbacks(NDArray *pArray) { /* This function does array statistics. * It is called with the mutex already locked. It unlocks it during long calculations when private * structures don't need to be protected. */ NDDimension_t bgdDims[ND_ARRAY_MAX_DIMS], *pDim; size_t bgdPixels; int bgdWidth; int dim; NDStats_t stats, *pStats=&stats, statsTemp, *pStatsTemp=&statsTemp; double bgdCounts, avgBgd; NDArray *pBgdArray=NULL; int computeStatistics, computeCentroid, computeProfiles, computeHistogram; size_t sizeX=0, sizeY=0; int i; int itemp; int numTSPoints, currentTSPoint, TSAcquiring; NDArrayInfo arrayInfo; const char* functionName = "processCallbacks"; /* Call the base class method */ NDPluginDriver::processCallbacks(pArray); pArray->getInfo(&arrayInfo); getIntegerParam(NDPluginStatsComputeStatistics, &computeStatistics); getIntegerParam(NDPluginStatsComputeCentroid, &computeCentroid); getIntegerParam(NDPluginStatsComputeProfiles, &computeProfiles); getIntegerParam(NDPluginStatsComputeHistogram, &computeHistogram); if (pArray->ndims > 0) sizeX = pArray->dims[0].size; if (pArray->ndims == 1) sizeY = 1; if (pArray->ndims > 1) sizeY = pArray->dims[1].size; if (sizeX != this->profileSizeX) { this->profileSizeX = sizeX; setIntegerParam(NDPluginStatsProfileSizeX, (int)this->profileSizeX); for (i=0; i<MAX_PROFILE_TYPES; i++) { if (this->profileX[i]) free(this->profileX[i]); this->profileX[i] = (double *)malloc(this->profileSizeX * sizeof(double)); } } if (sizeY != this->profileSizeY) { this->profileSizeY = sizeY; setIntegerParam(NDPluginStatsProfileSizeY, (int)this->profileSizeY); for (i=0; i<MAX_PROFILE_TYPES; i++) { if (this->profileY[i]) free(this->profileY[i]); this->profileY[i] = (double *)malloc(this->profileSizeY * sizeof(double)); } } if (computeStatistics) { getIntegerParam(NDPluginStatsBgdWidth, &bgdWidth); doComputeStatistics(pArray, pStats); /* If there is a non-zero background width then compute the background counts */ if (bgdWidth > 0) { bgdPixels = 0; bgdCounts = 0.; /* Initialize the dimensions of the background array */ for (dim=0; dim<pArray->ndims; dim++) { pArray->initDimension(&bgdDims[dim], pArray->dims[dim].size); } for (dim=0; dim<pArray->ndims; dim++) { pDim = &bgdDims[dim]; pDim->offset = 0; pDim->size = MIN((size_t)bgdWidth, pDim->size); this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims); pDim->size = pArray->dims[dim].size; if (!pBgdArray) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s, error allocating array buffer in convert\n", driverName, functionName); continue; } doComputeStatistics(pBgdArray, pStatsTemp); pBgdArray->release(); bgdPixels += pStatsTemp->nElements; bgdCounts += pStatsTemp->total; pDim->offset = MAX(0, pDim->size - 1 - bgdWidth); pDim->size = MIN((size_t)bgdWidth, pArray->dims[dim].size - pDim->offset); this->pNDArrayPool->convert(pArray, &pBgdArray, pArray->dataType, bgdDims); pDim->offset = 0; pDim->size = pArray->dims[dim].size; if (!pBgdArray) { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, "%s::%s, error allocating array buffer in convert\n", driverName, functionName); continue; } doComputeStatistics(pBgdArray, pStatsTemp); pBgdArray->release(); bgdPixels += pStatsTemp->nElements; bgdCounts += pStatsTemp->total; } if (bgdPixels < 1) bgdPixels = 1; avgBgd = bgdCounts / bgdPixels; pStats->net = pStats->total - avgBgd*pStats->nElements; } setDoubleParam(NDPluginStatsMinValue, pStats->min); setDoubleParam(NDPluginStatsMinX, (double)pStats->minX); setDoubleParam(NDPluginStatsMinY, (double)pStats->minY); setDoubleParam(NDPluginStatsMaxValue, pStats->max); setDoubleParam(NDPluginStatsMaxX, (double)pStats->maxX); setDoubleParam(NDPluginStatsMaxY, (double)pStats->maxY); setDoubleParam(NDPluginStatsMeanValue, pStats->mean); setDoubleParam(NDPluginStatsSigmaValue, pStats->sigma); setDoubleParam(NDPluginStatsTotal, pStats->total); setDoubleParam(NDPluginStatsNet, pStats->net); asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, (char *)pArray->pData, arrayInfo.totalBytes, "%s:%s min=%f, max=%f, mean=%f, total=%f, net=%f", driverName, functionName, pStats->min, pStats->max, pStats->mean, pStats->total, pStats->net); } if (computeCentroid) { doComputeCentroid(pArray); setDoubleParam(NDPluginStatsCentroidX, this->centroidX); setDoubleParam(NDPluginStatsCentroidY, this->centroidY); setDoubleParam(NDPluginStatsSigmaX, this->sigmaX); setDoubleParam(NDPluginStatsSigmaY, this->sigmaY); setDoubleParam(NDPluginStatsSigmaXY, this->sigmaXY); } if (computeProfiles) { doComputeProfiles(pArray); } if (computeHistogram) { getIntegerParam(NDPluginStatsHistSize, &itemp); this->histSizeNew = itemp; getDoubleParam (NDPluginStatsHistMin, &this->histMin); getDoubleParam (NDPluginStatsHistMax, &this->histMax); doComputeHistogram(pArray); setDoubleParam(NDPluginStatsHistEntropy, this->histEntropy); doCallbacksFloat64Array(this->histogram, this->histogramSize, NDPluginStatsHistArray, 0); } getIntegerParam(NDPluginStatsTSCurrentPoint, ¤tTSPoint); getIntegerParam(NDPluginStatsTSNumPoints, &numTSPoints); getIntegerParam(NDPluginStatsTSAcquiring, &TSAcquiring); if (TSAcquiring) { timeSeries[TSMinValue][currentTSPoint] = pStats->min; timeSeries[TSMinX][currentTSPoint] = (double)pStats->minX; timeSeries[TSMinY][currentTSPoint] = (double)pStats->minY; timeSeries[TSMaxValue][currentTSPoint] = pStats->max; timeSeries[TSMaxX][currentTSPoint] = (double)pStats->maxX; timeSeries[TSMaxY][currentTSPoint] = (double)pStats->maxY; timeSeries[TSMeanValue][currentTSPoint] = pStats->mean; timeSeries[TSSigmaValue][currentTSPoint] = pStats->sigma; timeSeries[TSTotal][currentTSPoint] = pStats->total; timeSeries[TSNet][currentTSPoint] = pStats->net; timeSeries[TSCentroidX][currentTSPoint] = this->centroidX; timeSeries[TSCentroidY][currentTSPoint] = this->centroidY; timeSeries[TSSigmaX][currentTSPoint] = this->sigmaX; timeSeries[TSSigmaY][currentTSPoint] = this->sigmaY; timeSeries[TSSigmaXY][currentTSPoint] = this->sigmaXY; currentTSPoint++; setIntegerParam(NDPluginStatsTSCurrentPoint, currentTSPoint); if (currentTSPoint >= numTSPoints) { setIntegerParam(NDPluginStatsTSAcquiring, 0); doTimeSeriesCallbacks(); } } /* Save a copy of this array for calculations when cursor is moved or threshold is changed */ if (this->pArrays[0]) this->pArrays[0]->release(); this->pArrays[0] = this->pNDArrayPool->copy(pArray, NULL, 1); callParamCallbacks(); }
void NDPluginStats::doTimeSeriesCallbacks() { int currentPoint; getIntegerParam(NDPluginStatsTSCurrentPoint, ¤tPoint); doCallbacksFloat64Array(this->timeSeries[TSMinValue], currentPoint, NDPluginStatsTSMinValue, 0); doCallbacksFloat64Array(this->timeSeries[TSMinX], currentPoint, NDPluginStatsTSMinX, 0); doCallbacksFloat64Array(this->timeSeries[TSMinY], currentPoint, NDPluginStatsTSMinY, 0); doCallbacksFloat64Array(this->timeSeries[TSMaxValue], currentPoint, NDPluginStatsTSMaxValue, 0); doCallbacksFloat64Array(this->timeSeries[TSMaxX], currentPoint, NDPluginStatsTSMaxX, 0); doCallbacksFloat64Array(this->timeSeries[TSMaxY], currentPoint, NDPluginStatsTSMaxY, 0); doCallbacksFloat64Array(this->timeSeries[TSMeanValue], currentPoint, NDPluginStatsTSMeanValue, 0); doCallbacksFloat64Array(this->timeSeries[TSSigmaValue], currentPoint, NDPluginStatsTSSigmaValue, 0); doCallbacksFloat64Array(this->timeSeries[TSTotal], currentPoint, NDPluginStatsTSTotal, 0); doCallbacksFloat64Array(this->timeSeries[TSNet], currentPoint, NDPluginStatsTSNet, 0); doCallbacksFloat64Array(this->timeSeries[TSCentroidX], currentPoint, NDPluginStatsTSCentroidX, 0); doCallbacksFloat64Array(this->timeSeries[TSCentroidY], currentPoint, NDPluginStatsTSCentroidY, 0); doCallbacksFloat64Array(this->timeSeries[TSSigmaX], currentPoint, NDPluginStatsTSSigmaX, 0); doCallbacksFloat64Array(this->timeSeries[TSSigmaY], currentPoint, NDPluginStatsTSSigmaY, 0); doCallbacksFloat64Array(this->timeSeries[TSSigmaXY], currentPoint, NDPluginStatsTSSigmaXY, 0); }
asynStatus NDPluginAttribute::writeInt32(asynUser *pasynUser, epicsInt32 value) { int function = pasynUser->reason; asynStatus status = asynSuccess; int numTSPoints, currentTSPoint; int i; static const char *functionName = "NDPluginAttribute::writeInt32"; /* Set the parameter in the parameter library. */ status = (asynStatus) setIntegerParam(function, value); if (function == NDPluginAttributeReset) { getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints); for (i=0; i<maxAttributes_; i++) { setDoubleParam(i, NDPluginAttributeVal, 0.0); setDoubleParam(i, NDPluginAttributeValSum, 0.0); // Clear the time series array memset(pTSArray_[i], 0, numTSPoints*sizeof(epicsFloat64)); doCallbacksFloat64Array(this->pTSArray_[i], numTSPoints, NDPluginAttributeTSArrayValue, i); callParamCallbacks(i); } setIntegerParam(NDPluginAttributeTSCurrentPoint, 0); } else if (function == NDPluginAttributeTSNumPoints) { for (i=0; i<maxAttributes_; i++) { free(pTSArray_[i]); pTSArray_[i] = static_cast<epicsFloat64 *>(calloc(value, sizeof(epicsFloat64))); } } else if (function == NDPluginAttributeTSControl) { switch (value) { case TSEraseStart: setIntegerParam(NDPluginAttributeTSCurrentPoint, 0); setIntegerParam(NDPluginAttributeTSAcquiring, 1); getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints); for (i=0; i<maxAttributes_; i++) { memset(pTSArray_[i], 0, numTSPoints*sizeof(epicsFloat64)); } doTimeSeriesCallbacks(); break; case TSStart: getIntegerParam(NDPluginAttributeTSNumPoints, &numTSPoints); getIntegerParam(NDPluginAttributeTSCurrentPoint, ¤tTSPoint); if (currentTSPoint < numTSPoints) { setIntegerParam(NDPluginAttributeTSAcquiring, 1); } break; case TSStop: setIntegerParam(NDPluginAttributeTSAcquiring, 0); doTimeSeriesCallbacks(); break; case TSRead: doTimeSeriesCallbacks(); break; } } else { /* If this parameter belongs to a base class call its method */ if (function < FIRST_NDPLUGIN_ATTR_PARAM) status = NDPluginDriver::writeInt32(pasynUser, value); } /* Do callbacks so higher layers see any changes */ status = (asynStatus) callParamCallbacks(); if (status) epicsSnprintf(pasynUser->errorMessage, pasynUser->errorMessageSize, "%s: status=%d, function=%d, value=%d", functionName, status, function, value); else asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, "%s: function=%d, value=%d\n", functionName, function, value); return status; }
/** * \param[in] pArray The NDArray from the callback. */ void NDPluginAttribute::processCallbacks(NDArray *pArray) { /* * This function is called with the mutex already locked. It unlocks it during long calculations when private * structures don't need to be protected. */ int status = 0; int dataType; char attrName[MAX_ATTR_NAME_] = {0}; NDAttribute *pAttribute = NULL; NDAttributeList *pAttrList = NULL; epicsFloat64 attrValue = 0.0; epicsFloat64 updatePeriod = 0.0; static const char *functionName = "NDPluginAttribute::processCallbacks"; asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "Starting %s. currentPoint_: %d\n", functionName, currentPoint_); /* Get the time and decide if we update the array.*/ getDoubleParam(NDPluginAttributeUpdatePeriod, &updatePeriod); epicsTimeGetCurrent(&nowTime_); nowTimeSecs_ = nowTime_.secPastEpoch + (nowTime_.nsec / 1.e9); if ((nowTimeSecs_ - lastTimeSecs_) < (updatePeriod / 1000.0)) { arrayUpdate_ = 0; } else { arrayUpdate_ = 1; lastTimeSecs_ = nowTimeSecs_; } /* Get all parameters while we have the mutex */ getIntegerParam(NDPluginAttributeDataType, &dataType); /* Call the base class method */ NDPluginDriver::processCallbacks(pArray); /* Get the attributes for this driver */ pAttrList = pArray->pAttributeList; getStringParam(NDPluginAttributeAttrName, MAX_ATTR_NAME_, attrName); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "Finding the attribute %s\n", attrName); pAttribute = pAttrList->find(attrName); if (pAttribute) { status = pAttribute->getValue(NDAttrFloat64, &attrValue); asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "Attribute %s is %f\n", attrName, attrValue); if (status == asynSuccess) { setDoubleParam(NDPluginAttributeVal, attrValue); valueSum_ = valueSum_ + attrValue; setDoubleParam(NDPluginAttributeValSum, valueSum_); if (currentPoint_ < maxTimeSeries_) { pTimeSeries_[currentPoint_] = attrValue; ++currentPoint_; } } callParamCallbacks(); if (arrayUpdate_) { doCallbacksFloat64Array(this->pTimeSeries_, currentPoint_, NDPluginAttributeArray, 0); } } else { asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, "%s: Error reading NDAttribute %s. \n", functionName, attrName); } }