From 29bdec75c333f6844b3979ae7ff0467578ccbd4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Wed, 8 Apr 2020 15:53:26 +0200 Subject: [PATCH] Use dedicated asynport for each fft object (to not disturb ecmc). --- .../Db/ecmcPluginFFT.template | 29 +- .../ecmcPlugin_FFTApp/src/ecmcFFT.cpp | 453 ++++++++++++------ .../ecmcPlugin_FFTApp/src/ecmcFFT.h | 38 +- .../ecmcPlugin_FFTApp/src/ecmcFFTWrap.cpp | 12 +- 4 files changed, 362 insertions(+), 170 deletions(-) diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/ecmcPluginFFT.template b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/ecmcPluginFFT.template index d8c4b2a..8d7fcba 100644 --- a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/ecmcPluginFFT.template +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/ecmcPluginFFT.template @@ -3,9 +3,9 @@ record(longin,"$(P)Plugin-FFT${INDEX}-stat"){ field(DESC, "Status") field(PINI, "1") field(DTYP, "asynInt32") - field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynInt32/plugin.fft${INDEX}.status?") + field(INP, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.status") field(SCAN, "I/O Intr") - field(TSE, "$(TSE=-2)") + field(TSE, "0") } # Data source @@ -13,11 +13,11 @@ record(waveform,"$(P)Plugin-FFT${INDEX}-Source"){ field(DESC, "Data source name") field(PINI, "1") field(DTYP, "asynInt8ArrayIn") - field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynInt8ArrayIn/plugin.fft${INDEX}.source?") + field(INP, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.source") field(FTVL, "CHAR") field(NELM, "1024") field(SCAN, "I/O Intr") - field(TSE, "$(TSE=-2)") + field(TSE, "0") } # Rawdata @@ -26,11 +26,11 @@ record(waveform,"$(P)Plugin-FFT${INDEX}-Raw-Data-Act"){ field(DESC, "Raw data") field(PINI, "1") field(DTYP, "asynFloat64ArrayIn") - field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynFloat64ArrayIn/plugin.fft${INDEX}.rawdata?") + field(INP, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.rawdata") field(FTVL, "DOUBLE") field(NELM, "$(NELM)") field(SCAN, "I/O Intr") - field(TSE, "$(TSE=-2)") + field(TSE, "0") } # FFT amplitude result @@ -39,11 +39,11 @@ record(waveform,"$(P)Plugin-FFT${INDEX}-Spectrum-Amp-Act"){ field(DESC, "FFT spectrum amplitude result") field(PINI, "1") field(DTYP, "asynFloat64ArrayIn") - field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynFloat64ArrayIn/plugin.fft${INDEX}.fftamplitude?") + field(INP, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.fftamplitude") field(FTVL, "DOUBLE") field(NELM, "$(NELM)") field(SCAN, "I/O Intr") - field(TSE, "$(TSE=-2)") + field(TSE, "0") } # FFT xaxis @@ -52,17 +52,17 @@ record(waveform,"$(P)Plugin-FFT${INDEX}-Spectrum-X-Axis-Act"){ field(DESC, "Raw data") field(PINI, "1") field(DTYP, "asynFloat64ArrayIn") - field(INP, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynFloat64ArrayIn/plugin.fft${INDEX}.fftxaxis?") + field(INP, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.fftxaxis") field(FTVL, "DOUBLE") field(NELM, "$(NELM)") field(SCAN, "I/O Intr") - field(TSE, "$(TSE=-2)") + field(TSE, "0") } record(bo,"$(P)Plugin-FFT${INDEX}-Enable"){ field(DESC, "FFT Enable") field(DTYP,"asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynInt32/plugin.fft${INDEX}.enable=") + field(OUT, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.enable") field(ZNAM,"FALSE") field(ONAM,"TRUE") field(DOL, "0") @@ -72,7 +72,7 @@ record(bo,"$(P)Plugin-FFT${INDEX}-Enable"){ record(bo,"$(P)Plugin-FFT${INDEX}-Trigg"){ field(DESC, "FFT Trigg measurement") field(DTYP,"asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynInt32/plugin.fft${INDEX}.trigg=") + field(OUT, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.trigg") field(ZNAM,"FALSE") field(ONAM,"TRUE") field(DOL, "0") @@ -82,9 +82,8 @@ record(bo,"$(P)Plugin-FFT${INDEX}-Trigg"){ record(longout,"$(P)Plugin-FFT${INDEX}-Mode-RB"){ info(asyn:READBACK,"1") field(PINI, "1") - field(TSE, -2) + field(TSE, "0") field(DTYP, "asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR=0),$(TIMEOUT=1000))T_SMP_MS=$(T_SMP_MS=1000)/TYPE=asynInt32/plugin.fft${INDEX}.mode=") + field(OUT, "@asyn(PLUGIN.FFT${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.fft${INDEX}.mode") field(SCAN, "Passive") - field(TSE, "$(TSE=0)") } diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.cpp b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.cpp index 192abc2..cf826f9 100644 --- a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.cpp +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.cpp @@ -68,21 +68,37 @@ void f_worker(void *obj) { * - runtime_error */ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is created) - char* configStr) { + char* configStr, + char* portName) + : asynPortDriver(portName, + 1, /* maxAddr */ + asynInt32Mask | asynFloat64Mask | asynFloat32ArrayMask | + asynFloat64ArrayMask | asynEnumMask | asynDrvUserMask | + asynOctetMask | asynInt8ArrayMask | asynInt16ArrayMask | + asynInt32ArrayMask | asynUInt32DigitalMask, /* Interface mask */ + asynInt32Mask | asynFloat64Mask | asynFloat32ArrayMask | + asynFloat64ArrayMask | asynEnumMask | asynDrvUserMask | + asynOctetMask | asynInt8ArrayMask | asynInt16ArrayMask | + asynInt32ArrayMask | asynUInt32DigitalMask, /* Interrupt mask */ + ASYN_CANBLOCK , /*NOT ASYN_MULTI_DEVICE*/ + 1, /* Autoconnect */ + 0, /* Default priority */ + 0) /* Default stack size */ + { cfgDataSourceStr_ = NULL; rawDataBuffer_ = NULL; dataItem_ = NULL; dataItemInfo_ = NULL; fftDouble_ = NULL; - asynPort_ = NULL; - asynEnable_ = NULL; // Enable - asynRawData_ = NULL; // Input data - asynFFTAmp_ = NULL; // Result - asynFFTMode_ = NULL; // Mode - asynFFTStat_ = NULL; // Status - asynSource_ = NULL; // Source - asynTrigg_ = NULL; // Trigg new measurement - asynFFTXAxis_ = NULL; // Result x axis + // asynPort_ = NULL; + // asynEnable_ = NULL; // Enable + // asynRawData_ = NULL; // Input data + // asynFFTAmp_ = NULL; // Result + // asynFFTMode_ = NULL; // Mode + // asynFFTStat_ = NULL; // Status + // asynSource_ = NULL; // Source + // asynTrigg_ = NULL; // Trigg new measurement + // asynFFTXAxis_ = NULL; // Result x axis status_ = NO_STAT; elementsInBuffer_ = 0; fftWaitingForCalc_= 0; @@ -94,6 +110,16 @@ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is cr cycleCounter_ = 0; ignoreCycles_ = 0; + // New asyn + asynEnableId_ = -1; // Enable/disable acq./calcs + asynRawDataId_ = -1; // Raw data (input) array (double) + asynFFTAmpId_ = -1; // FFT amplitude array (double) + asynFFTModeId_ = -1; // FFT mode (cont/trigg) + asynFFTStatId_ = -1; // FFT status (no_stat/idle/acq/calc) + asynSourceId_ = -1; // SOURCE + asynTriggId_ = -1; // Trigg new measurement + asynFFTXAxisId_ = -1; // FFT X-axis frequencies + ecmcSampleRateHz_ = getEcmcSampleRate(); cfgFFTSampleRateHz_ = ecmcSampleRateHz_; @@ -105,10 +131,10 @@ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is cr cfgEnable_ = 0; // start disabled (enable over asyn) cfgMode_ = TRIGG; - asynPort_ = (ecmcAsynPortDriver*) getEcmcAsynPortDriver(); - if(!asynPort_) { - throw std::runtime_error("Asyn port NULL"); - } + // asynPort_ = (ecmcAsynPortDriver*) getEcmcAsynPortDriver(); + // if(!asynPort_) { + // throw std::runtime_error("Asyn port NULL"); + // } parseConfigStr(configStr); // Assigns all configs // Check valid nfft @@ -326,30 +352,6 @@ void ecmcFFT::dataUpdatedCallback(uint8_t* data, updateStatus(CALC); fftWaitingForCalc_ = 1; doCalcEvent_.signal(); // let worker start - - // // **** Breakout to sperate low prio work thread below - // removeDCOffset(); // Remove dc on rawdata - // calcFFT(); // FFT cacluation - // scaleFFT(); // Scale FFT - // calcFFTAmp(); // Calculate amplitude from complex - // // **** Breakout to thread above - - // triggOnce_ = 0; // Wait for nex trigger if in trigg mode - - // // Update asyn with both input and result - // asynRawData_->refreshParamRT(1); // Forced update (do not consider record rate) - // asynFFTAmp_->refreshParamRT(1); // Forced update (do not consider record rate) - // //asynFFTXAxis_->refreshParamRT(1); // Forced update (do not consider record rate) - - // if(cfgDbgMode_){ - // printComplexArray(fftBufferResult_, - // cfgNfft_, - // objectId_); - // printEcDataArray((uint8_t*)rawDataBuffer_, - // cfgNfft_*sizeof(double), - // ECMC_EC_F64, - // objectId_); - //} } return; } @@ -660,155 +662,232 @@ size_t ecmcFFT::getEcDataTypeByteSize(ecmcEcDataType dt){ return 0; } -// register a dummy asyn parameter "plugin.adv.counter" void ecmcFFT::initAsyn() { - - if(!asynPort_) { - throw std::runtime_error("Asyn port NULL"); - } - + // Add enable "plugin.fft%d.enable" std::string paramName =ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_ENABLE; - asynEnable_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t *)&(cfgEnable_), // pointer to data - sizeof(cfgEnable_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - - if(!asynEnable_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + + if( createParam(0, paramName.c_str(), asynParamInt32, &asynEnableId_) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter enable"); } - asynEnable_->setAllowWriteToEcmc(true); - asynEnable_->refreshParam(1); // read once into asyn param lib + setIntegerParam(asynEnableId_, cfgEnable_); // Add rawdata "plugin.fft%d.rawdata" paramName =ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_RAWDATA; - - asynRawData_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamFloat64Array, // asyn type - (uint8_t *)rawDataBuffer_, // pointer to data - cfgNfft_*sizeof(double), // size of data - ECMC_EC_F64, // ecmc data type - 0); // die if fail - if(!asynRawData_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamFloat64Array, &asynRawDataId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter rawdata"); } - asynRawData_->setAllowWriteToEcmc(false); - asynRawData_->refreshParam(1); // read once into asyn param lib - + doCallbacksFloat64Array(rawDataBuffer_, cfgNfft_, asynRawDataId_,0); + // Add fft amplitude "plugin.fft%d.fftamplitude" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_AMP; - - asynFFTAmp_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamFloat64Array, // asyn type - (uint8_t *)fftBufferResultAmp_, // pointer to data - (cfgNfft_ / 2 + 1)*sizeof(double), // size of data - ECMC_EC_F64, // ecmc data type - 0); // die if fail - if(!asynFFTAmp_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamFloat64Array, &asynFFTAmpId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter fftamplitude"); } - - asynFFTAmp_->setAllowWriteToEcmc(false); - asynFFTAmp_->refreshParam(1); // read once into asyn param lib + doCallbacksFloat64Array(fftBufferResultAmp_, cfgNfft_/2+1, asynFFTXAxisId_,0); // Add fft mode "plugin.fft%d.mode" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_MODE; - - asynFFTMode_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t *)(&cfgMode_), // pointer to data - sizeof(cfgMode_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - if(!asynFFTMode_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamInt32, &asynFFTModeId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter mode"); } - - asynFFTMode_->setAllowWriteToEcmc(true); - asynFFTMode_->refreshParam(1); // read once into asyn param lib + setIntegerParam(asynFFTModeId_, (epicsInt32)cfgMode_); // Add fft mode "plugin.fft%d.status" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_STAT; - - asynFFTStat_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t *)(&status_), // pointer to data - sizeof(status_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - if(!asynFFTStat_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamInt32, &asynFFTStatId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter status"); } + setIntegerParam(asynFFTStatId_, (epicsInt32)status_); - asynFFTStat_->setAllowWriteToEcmc(false); - asynFFTStat_->refreshParam(1); // read once into asyn param lib - - // Add fft mode "plugin.fft%d.status" + // Add fft mode "plugin.fft%d.source" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_SOURCE; - - asynSource_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamInt8Array, // asyn type - (uint8_t *)cfgDataSourceStr_, // pointer to data - strlen(cfgDataSourceStr_), // size of data - ECMC_EC_U8, // ecmc data type - 0); // die if fail - if(!asynSource_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamInt8Array, &asynSourceId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter source"); } - - asynSource_->setAllowWriteToEcmc(false); - asynSource_->refreshParam(1); // read once into asyn param lib + doCallbacksInt8Array(cfgDataSourceStr_, strlen(cfgDataSourceStr_), asynSourceId_,0); // Add fft mode "plugin.fft%d.trigg" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_TRIGG; - - asynTrigg_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t *)(&triggOnce_), // pointer to data - sizeof(triggOnce_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - if(!asynTrigg_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamInt32, &asynTriggId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter trigg"); } - - asynTrigg_->setAllowWriteToEcmc(true); - asynTrigg_->refreshParam(1); // read once into asyn param lib + setIntegerParam(asynTriggId_, (epicsInt32)triggOnce_); // Add fft mode "plugin.fft%d.xaxisfreqs" paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + "." + ECMC_PLUGIN_ASYN_FFT_X_FREQS; - - asynFFTXAxis_ = asynPort_->addNewAvailParam(paramName.c_str(), // name - asynParamFloat64Array, // asyn type - (uint8_t *)fftBufferXAxis_, // pointer to data - (cfgNfft_ / 2 + 1) * sizeof(double), // size of data - ECMC_EC_F64, // ecmc data type - 0); // die if fail - if(!asynFFTXAxis_) { - throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); + if( createParam(0, paramName.c_str(), asynParamFloat64Array, &asynFFTXAxisId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter xaxisfreqs"); } + doCallbacksFloat64Array(fftBufferXAxis_,cfgNfft_/2+1, asynFFTXAxisId_,0); - asynFFTXAxis_->setAllowWriteToEcmc(false); - asynFFTXAxis_->refreshParam(1); // read once into asyn param lib + // Update integers + callParamCallbacks(); } +// void ecmcFFT::initAsyn() { + +// if(!asynPort_) { +// throw std::runtime_error("Asyn port NULL"); +// } + +// // Add enable "plugin.fft%d.enable" +// std::string paramName =ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_ENABLE; +// asynEnable_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamInt32, // asyn type +// (uint8_t *)&(cfgEnable_), // pointer to data +// sizeof(cfgEnable_), // size of data +// ECMC_EC_S32, // ecmc data type +// 0); // die if fail + +// if(!asynEnable_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } +// asynEnable_->setAllowWriteToEcmc(true); +// asynEnable_->refreshParam(1); // read once into asyn param lib + +// // Add rawdata "plugin.fft%d.rawdata" +// paramName =ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_RAWDATA; + +// asynRawData_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamFloat64Array, // asyn type +// (uint8_t *)rawDataBuffer_, // pointer to data +// cfgNfft_*sizeof(double), // size of data +// ECMC_EC_F64, // ecmc data type +// 0); // die if fail + +// if(!asynRawData_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } +// asynRawData_->setAllowWriteToEcmc(false); +// asynRawData_->refreshParam(1); // read once into asyn param lib + +// // Add fft amplitude "plugin.fft%d.fftamplitude" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_AMP; + +// asynFFTAmp_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamFloat64Array, // asyn type +// (uint8_t *)fftBufferResultAmp_, // pointer to data +// (cfgNfft_ / 2 + 1)*sizeof(double), // size of data +// ECMC_EC_F64, // ecmc data type +// 0); // die if fail + +// if(!asynFFTAmp_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } + +// asynFFTAmp_->setAllowWriteToEcmc(false); +// asynFFTAmp_->refreshParam(1); // read once into asyn param lib + +// // Add fft mode "plugin.fft%d.mode" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_MODE; + +// asynFFTMode_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamInt32, // asyn type +// (uint8_t *)(&cfgMode_), // pointer to data +// sizeof(cfgMode_), // size of data +// ECMC_EC_S32, // ecmc data type +// 0); // die if fail + +// if(!asynFFTMode_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } + +// asynFFTMode_->setAllowWriteToEcmc(true); +// asynFFTMode_->refreshParam(1); // read once into asyn param lib + +// // Add fft mode "plugin.fft%d.status" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_STAT; + +// asynFFTStat_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamInt32, // asyn type +// (uint8_t *)(&status_), // pointer to data +// sizeof(status_), // size of data +// ECMC_EC_S32, // ecmc data type +// 0); // die if fail + +// if(!asynFFTStat_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } + +// asynFFTStat_->setAllowWriteToEcmc(false); +// asynFFTStat_->refreshParam(1); // read once into asyn param lib + +// // Add fft mode "plugin.fft%d.status" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_SOURCE; + +// asynSource_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamInt8Array, // asyn type +// (uint8_t *)cfgDataSourceStr_, // pointer to data +// strlen(cfgDataSourceStr_), // size of data +// ECMC_EC_U8, // ecmc data type +// 0); // die if fail + +// if(!asynSource_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// }doCallbacksFloat64Array(rawDataBuffer_,cfgNfft_, asynRawDataId_,0); + +// asynSource_->setAllowWriteToEcmc(false); +// asynSource_->refreshParam(1); // read once into asyn param lib + +// // Add fft mode "plugin.fft%d.trigg" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_TRIGG; + +// asynTrigg_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamInt32, // asyn type +// (uint8_t *)(&triggOnce_), // pointer to data +// sizeof(triggOnce_), // size of data +// ECMC_EC_S32, // ecmc data type +// 0); // die if fail + +// if(!asynTrigg_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } + +// asynTrigg_->setAllowWriteToEcmc(true); +// asynTrigg_->refreshParam(1); // read once into asyn param lib + +// // Add fft mode "plugin.fft%d.xaxisfreqs" +// paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + +// "." + ECMC_PLUGIN_ASYN_FFT_X_FREQS; + +// asynFFTXAxis_ = asynPort_->addNewAvailParam(paramName.c_str(), // name +// asynParamFloat64Array, // asyn type +// (uint8_t *)fftBufferXAxis_, // pointer to data +// (cfgNfft_ / 2 + 1) * sizeof(double), // size of data +// ECMC_EC_F64, // ecmc data type +// 0); // die if fail + +// if(!asynFFTXAxis_) { +// throw std::runtime_error("Failed to create asyn parameter \"" + paramName +"\".\n"); +// } + +// asynFFTXAxis_->setAllowWriteToEcmc(false); +// asynFFTXAxis_->refreshParam(1); // read once into asyn param lib +// } + // Avoid issues with std:to_string() std::string ecmcFFT::to_string(int value) { std::ostringstream os; @@ -827,6 +906,7 @@ void ecmcFFT::triggFFT() { void ecmcFFT::setModeFFT(FFT_MODE mode) { cfgMode_ = mode; + setIntegerParam(asynFFTModeId_,(epicsInt32)mode); } FFT_STATUS ecmcFFT::getStatusFFT() { @@ -835,7 +915,8 @@ FFT_STATUS ecmcFFT::getStatusFFT() { void ecmcFFT::updateStatus(FFT_STATUS status) { status_ = status; - asynFFTStat_->refreshParamRT(1); + setIntegerParam(asynFFTStatId_,(epicsInt32) status); + callParamCallbacks(); } // Do nut use this as same time as callback! @@ -864,9 +945,10 @@ void ecmcFFT::doCalcWorker() { // NOTE these calls should not be here.. since they belong to other thread // Update asyn with both input and result triggOnce_ = 0; // Wait for next trigger if in trigg mode - asynRawData_->refreshParamRT(1); // Forced update (do not consider record rate) - asynFFTAmp_->refreshParamRT(1); // Forced update (do not consider record rate) - //asynFFTXAxis_->refreshParamRT(1); // Forced update (do not consider record rate) + + doCallbacksFloat64Array(rawDataBuffer_,cfgNfft_, asynRawDataId_,0); + doCallbacksFloat64Array(fftBufferResultAmp_,cfgNfft_/2+1, asynFFTAmpId_,0); + printf("END CALC in worker for object %d###############################\n",objectId_); if(cfgDbgMode_){ @@ -882,4 +964,87 @@ void ecmcFFT::doCalcWorker() { clearBuffers(); fftWaitingForCalc_ = 0; } -} \ No newline at end of file +} + +asynStatus ecmcFFT::writeInt32(asynUser *pasynUser, epicsInt32 value) { + int function = pasynUser->reason; + if( function == asynEnableId_ ) { + cfgEnable_ = value; + return asynSuccess; + } else if( function == asynFFTModeId_){ + cfgMode_ = (FFT_MODE)value; + return asynSuccess; + } else if( function == asynTriggId_){ + triggOnce_ = value > 0; + return asynSuccess; + } + return asynError; +} + +asynStatus ecmcFFT::readInt32(asynUser *pasynUser, epicsInt32 *value) { + int function = pasynUser->reason; + if( function == asynEnableId_ ) { + *value = cfgEnable_; + return asynSuccess; + } else if( function == asynFFTModeId_ ){ + *value = cfgMode_; + return asynSuccess; + } else if( function == asynTriggId_ ){ + *value = triggOnce_; + return asynSuccess; + }else if( function == asynFFTStatId_ ){ + *value = (epicsInt32)status_; + return asynSuccess; + } + + return asynError; +} + +asynStatus ecmcFFT::readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, + size_t nElements, size_t *nIn) { + int function = pasynUser->reason; + if( function == asynRawDataId_ ) { + unsigned int ncopy = cfgNfft_; + if(nElements < ncopy) { + ncopy = nElements; + } + memcpy (value, rawDataBuffer_, ncopy); + *nIn = ncopy; + return asynSuccess; + } else if( function == asynFFTXAxisId_ ) { + unsigned int ncopy = cfgNfft_/ 2 + 1; + if(nElements < ncopy) { + ncopy = nElements; + } + memcpy (value, fftBufferXAxis_, ncopy); + *nIn = ncopy; + return asynSuccess; + } if( function == asynFFTAmpId_ ) { + unsigned int ncopy = cfgNfft_/ 2 + 1; + if(nElements < ncopy) { + ncopy = nElements; + } + memcpy (value, fftBufferResultAmp_, ncopy); + *nIn = ncopy; + return asynSuccess; + } + + *nIn = 0; + return asynError; +} +asynStatus ecmcFFT::readInt8Array(asynUser *pasynUser, epicsInt8 *value, + size_t nElements, size_t *nIn) { + int function = pasynUser->reason; + if( function == asynSourceId_ ) { + unsigned int ncopy = strlen(cfgDataSourceStr_); + if(nElements < ncopy) { + ncopy = nElements; + } + memcpy (value, cfgDataSourceStr_, ncopy); + *nIn = ncopy; + return asynSuccess; + } + + *nIn = 0; + return asynError; +} diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.h b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.h index 89f50be..6969014 100644 --- a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.h +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFT.h @@ -20,7 +20,7 @@ #include #include "kissfft/kissfft.hh" -class ecmcFFT { +class ecmcFFT : public asynPortDriver { public: /** ecmc FFT class @@ -31,7 +31,8 @@ class ecmcFFT { * - out_of_range */ ecmcFFT(int fftIndex, // index of this object - char* configStr); + char* configStr, + char* portName); ~ecmcFFT(); // Add data to buffer (called from "external" callback) @@ -49,6 +50,13 @@ class ecmcFFT { /** Do not use this as same time as callback! * if used it should be called from ecmc realtime callback*/ void sampleData(); + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); + virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, + size_t nElements, size_t *nIn); + virtual asynStatus readInt8Array(asynUser *pasynUser, epicsInt8 *value, + size_t nElements, size_t *nIn); + private: void parseConfigStr(char *configStr); @@ -94,14 +102,24 @@ class ecmcFFT { double cfgFFTSampleRateHz_; // Config: Sample rate (defaukts to ecmc rate) // Asyn - ecmcAsynDataItem* asynEnable_; // Enable/disable acq./calcs - ecmcAsynDataItem* asynRawData_; // Raw data (input) array (double) - ecmcAsynDataItem* asynFFTAmp_; // FFT amplitude array (double) - ecmcAsynDataItem* asynFFTMode_; // FFT mode (cont/trigg) - ecmcAsynDataItem* asynFFTStat_; // FFT status (no_stat/idle/acq/calc) - ecmcAsynDataItem* asynSource_; // SOURCE - ecmcAsynDataItem* asynTrigg_; // Trigg new measurement - ecmcAsynDataItem* asynFFTXAxis_; // FFT X-axis frequencies +// ecmcAsynDataItem* asynEnable_; // Enable/disable acq./calcs +// ecmcAsynDataItem* asynRawData_; // Raw data (input) array (double) +// ecmcAsynDataItem* asynFFTAmp_; // FFT amplitude array (double) +// ecmcAsynDataItem* asynFFTMode_; // FFT mode (cont/trigg) +// ecmcAsynDataItem* asynFFTStat_; // FFT status (no_stat/idle/acq/calc) +// ecmcAsynDataItem* asynSource_; // SOURCE +// ecmcAsynDataItem* asynTrigg_; // Trigg new measurement +// ecmcAsynDataItem* asynFFTXAxis_; // FFT X-axis frequencies + + // New Asyn + int asynEnableId_; // Enable/disable acq./calcs + int asynRawDataId_; // Raw data (input) array (double) + int asynFFTAmpId_; // FFT amplitude array (double) + int asynFFTModeId_; // FFT mode (cont/trigg) + int asynFFTStatId_; // FFT status (no_stat/idle/acq/calc) + int asynSourceId_; // SOURCE + int asynTriggId_; // Trigg new measurement + int asynFFTXAxisId_; // FFT X-axis frequencies // Thread related epicsEvent doCalcEvent_; diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFTWrap.cpp b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFTWrap.cpp index c40ba5e..f6a0b40 100644 --- a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFTWrap.cpp +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcFFTWrap.cpp @@ -16,19 +16,29 @@ #include #include +#include #include "ecmcFFTWrap.h" #include "ecmcFFT.h" #include "ecmcFFTDefs.h" +#define ECMC_PLUGIN_MAX_PORTNAME_CHARS 64 +#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.FFT" + static std::vector ffts; static int fftObjCounter = 0; +static char portNameBuffer[ECMC_PLUGIN_MAX_PORTNAME_CHARS]; int createFFT(char* configStr) { // create new ecmcFFT object ecmcFFT* fft = NULL; + + // create asynport name for new object () + memset(portNameBuffer, 0, ECMC_PLUGIN_MAX_PORTNAME_CHARS); + snprintf (portNameBuffer, ECMC_PLUGIN_MAX_PORTNAME_CHARS, + ECMC_PLUGIN_PORTNAME_PREFIX "%d", fftObjCounter); try { - fft = new ecmcFFT(fftObjCounter, configStr); + fft = new ecmcFFT(fftObjCounter, configStr,portNameBuffer); } catch(std::exception& e) { if(fft) {