Add breaktable support

This commit is contained in:
Anders Sandstrom
2021-01-26 14:19:48 +01:00
parent e6f5286836
commit 5418c98488
6 changed files with 89 additions and 14 deletions

View File

@@ -8,7 +8,7 @@ E3_MODULE_VERSION:=master
# DEPENDENT MODULE VERSION
# For Example,
ECMC_DEP_VERSION:=6.3.0
ECMC_DEP_VERSION:=develop
ASYN_DEP_VERSION:=4.37.0
#DEVLIB2_DEP_VERSION:=2.9.0

View File

@@ -2,7 +2,7 @@
EPICS_BASE:=${HOME}/epics/base-7.0.4
E3_REQUIRE_NAME:=require
E3_REQUIRE_VERSION:=3.3.0
E3_REQUIRE_VERSION:=3.4.0
# The definitions shown below can also be placed in an untracked RELEASE.local
-include $(TOP)/../../RELEASE.local

View File

@@ -36,6 +36,17 @@
#include "ecmcAsynPortDriverUtils.h"
#include "epicsThread.h"
// Breaktable
#include "ellLib.h"
#include "dbStaticLib.h"
#include "dbAccess.h"
#include "epicsVersion.h"
#include "cvtTable.h"
#ifdef BASE_VERSION
#define EPICS_3_13
extern DBBASE *pdbbase;
#endif
// New data callback from ecmc
static int printMissingObjError = 1;
@@ -92,6 +103,7 @@ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is cr
0) /* Default stack size */
{
cfgDataSourceStr_ = NULL;
cfgBreakTableStr_ = NULL;
rawDataBuffer_ = NULL;
dataItem_ = NULL;
dataItemInfo_ = NULL;
@@ -107,6 +119,10 @@ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is cr
cycleCounter_ = 0;
ignoreCycles_ = 0;
dataSourceLinked_ = 0;
breakTableIndex_ = -1;
breakTable_ = 0;
lastBreakPoint_ = 0;
breakInit_ = 1;
// Asyn
asynEnableId_ = -1; // Enable/disable acq./calcs
@@ -151,6 +167,11 @@ ecmcFFT::ecmcFFT(int fftIndex, // index of this object (if several is cr
cfgFFTSampleRateHz_ = ecmcSampleRateHz_;
}
// Check if breaktable
if(cfgBreakTableStr_) {
verifyBreakTable();
}
// Se if any data update cycles should be ignored
// example ecmc 1000Hz, fft 100Hz then ignore 9 cycles (could be strange if not multiples)
ignoreCycles_ = ecmcSampleRateHz_ / cfgFFTSampleRateHz_ -1;
@@ -199,6 +220,9 @@ ecmcFFT::~ecmcFFT() {
if(cfgDataSourceStr_) {
free(cfgDataSourceStr_);
}
if(cfgBreakTableStr_) {
free(cfgBreakTableStr_);
}
if(fftDouble_) {
delete fftDouble_;
}
@@ -234,6 +258,12 @@ void ecmcFFT::parseConfigStr(char *configStr) {
cfgDataSourceStr_=strdup(pThisOption);
}
// ECMC_PLUGIN_BREAKTABLE_OPTION_CMD (EPICS breaktable name)
else if (!strncmp(pThisOption, ECMC_PLUGIN_BREAKTABLE_OPTION_CMD, strlen(ECMC_PLUGIN_BREAKTABLE_OPTION_CMD))) {
pThisOption += strlen(ECMC_PLUGIN_BREAKTABLE_OPTION_CMD);
cfgBreakTableStr_=strdup(pThisOption);
}
// ECMC_PLUGIN_NFFT_OPTION_CMD (1/0)
else if (!strncmp(pThisOption, ECMC_PLUGIN_NFFT_OPTION_CMD, strlen(ECMC_PLUGIN_NFFT_OPTION_CMD))) {
pThisOption += strlen(ECMC_PLUGIN_NFFT_OPTION_CMD);
@@ -424,9 +454,24 @@ void ecmcFFT::dataUpdatedCallback(uint8_t* data,
}
void ecmcFFT::addDataToBuffer(double data) {
if(rawDataBuffer_ && (elementsInBuffer_ < cfgNfft_) ) {
rawDataBuffer_[elementsInBuffer_] = data* cfgScale_;
prepProcDataBuffer_[elementsInBuffer_] = data *cfgScale_;
if(breakTableIndex_>=0 && cfgBreakTableStr_ && interruptAccept) {
double breakData = data;
if (cvtRawToEngBpt(&breakData, breakTableIndex_, breakInit_, &breakTable_, &lastBreakPoint_)!=0) {
//TODO: What does status here mean..
//throw std::runtime_error("Breaktable conversion failed.\n");
}
breakInit_ = 0; // Breack pointer should now be assigned
//printf("Index %d: Before %lf, after %lf\n",objectId_,data,breakData);
data = breakData * cfgScale_;
} else {
data = data * cfgScale_;
}
rawDataBuffer_[elementsInBuffer_] = data;
prepProcDataBuffer_[elementsInBuffer_] = data;
}
elementsInBuffer_ ++;
}
@@ -1055,3 +1100,25 @@ int ecmcFFT::leastSquare(int n, const double y[], double* k, double* m){
*m = (sumy * sumx2 - sumx * sumxy) / denom;
return 0;
}
bool ecmcFFT::verifyBreakTable() {
breakTableIndex_ = -1;
dbMenu *menuConvert;
ELLLIST missing;
int i;
menuConvert = dbFindMenu(pdbbase,"menuConvert");
ellInit(&missing);
for(i=0; i<menuConvert->nChoice; i++)
{
// printf("menuConvertItem[%d] %s (looking for %s))\n",i,menuConvert->papChoiceValue[i], cfgBreakTableStr_);
if (strcmp(menuConvert->papChoiceValue[i],cfgBreakTableStr_)==0)
{
breakTableIndex_ = i;
printf("breakTable %s found as menuItem %d\n",cfgBreakTableStr_, breakTableIndex_);
break;
}
}
return breakTableIndex_>=0;
}

View File

@@ -19,6 +19,7 @@
#include "inttypes.h"
#include <string>
#include "kissfft/kissfft.hh"
#include "dbBase.h"
class ecmcFFT : public asynPortDriver {
public:
@@ -68,6 +69,7 @@ class ecmcFFT : public asynPortDriver {
void initAsyn();
void updateStatus(FFT_STATUS status); // Also updates asynparam
static int dataTypeSupported(ecmcEcDataType dt);
bool verifyBreakTable();
ecmcDataItem *dataItem_;
ecmcDataItemInfo *dataItemInfo_;
@@ -90,11 +92,16 @@ class ecmcFFT : public asynPortDriver {
int triggOnce_;
int cycleCounter_;
int ignoreCycles_;
int breakTableIndex_;
void *breakTable_;
short lastBreakPoint_;
short breakInit_;
double scale_; // Config: Data set size
FFT_STATUS status_; // Status/state (NO_STAT, IDLE, ACQ, CALC)
// Config options
char* cfgDataSourceStr_; // Config: data source string
char* cfgBreakTableStr_; // Config: EPICS breaktable name
int cfgDbgMode_; // Config: allow dbg printouts
int cfgApplyScale_; // Config: apply scale 1/nfft
int cfgDcRemove_; // Config: remove dc (average)

View File

@@ -24,7 +24,7 @@
#define ECMC_PLUGIN_RATE_OPTION_CMD "RATE="
#define ECMC_PLUGIN_RM_LIN_OPTION_CMD "RM_LIN="
#define ECMC_PLUGIN_SCALE_OPTION_CMD "SCALE="
#define ECMC_PLUGIN_BREAKTABLE_OPTION_CMD "BREAKTABLE="
// CONT, TRIGG
#define ECMC_PLUGIN_MODE_OPTION_CMD "MODE="

View File

@@ -115,15 +115,16 @@ struct ecmcPluginData pluginDataDef = {
// Description
.desc = "FFT plugin for use with ecmc.",
// Option description
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
" "ECMC_PLUGIN_SOURCE_OPTION_CMD"<source> : Sets source variable for FFT (example: ec0.s1.AI_1).\n"
" "ECMC_PLUGIN_NFFT_OPTION_CMD"<nfft> : Data points to collect, default = 4096.\n"
" "ECMC_PLUGIN_SCALE_OPTION_CMD"scalefactor : Apply scale to source data, default = 1.0.\n"
" "ECMC_PLUGIN_RM_DC_OPTION_CMD"<1/0> : Remove DC offset of input data (SOURCE), default = disabled.\n"
" "ECMC_PLUGIN_RM_LIN_OPTION_CMD"<1/0> : Remove linear component in data (SOURCE) by least square, default = disabled.\n"
" "ECMC_PLUGIN_ENABLE_OPTION_CMD"<1/0> : Enable data acq. and calcs (can be controlled over asyn), default = disabled.\n"
" "ECMC_PLUGIN_MODE_OPTION_CMD"<CONT/TRIGG> : Continious or triggered mode, defaults to TRIGG\n"
" "ECMC_PLUGIN_RATE_OPTION_CMD"<rate in hz> : fft data sample rate in hz (must be lower than ecmc rate and (ecmc_rate/fft_rate)=integer), default = ecmc rate."
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
" "ECMC_PLUGIN_SOURCE_OPTION_CMD"<source> : Sets source variable for FFT (example: ec0.s1.AI_1).\n"
" "ECMC_PLUGIN_NFFT_OPTION_CMD"<nfft> : Data points to collect, default = 4096.\n"
" "ECMC_PLUGIN_SCALE_OPTION_CMD"scalefactor : Apply scale to source data, default = 1.0.\n"
" "ECMC_PLUGIN_RM_DC_OPTION_CMD"<1/0> : Remove DC offset of input data (SOURCE), default = disabled.\n"
" "ECMC_PLUGIN_RM_LIN_OPTION_CMD"<1/0> : Remove linear component in data (SOURCE) by least square, default = disabled.\n"
" "ECMC_PLUGIN_ENABLE_OPTION_CMD"<1/0> : Enable data acq. and calcs (can be controlled over asyn), default = disabled.\n"
" "ECMC_PLUGIN_MODE_OPTION_CMD"<CONT/TRIGG> : Continious or triggered mode, defaults to TRIGG\n"
" "ECMC_PLUGIN_RATE_OPTION_CMD"<rate in hz> : fft data sample rate in hz (must be lower than ecmc rate and (ecmc_rate/fft_rate)=integer), default = ecmc rate."
" "ECMC_PLUGIN_BREAKTABLE_OPTION_CMD"<brktab> : Use epics breaktable to convert raw values (applied before any other signal cond. alg.), default not used."
,
// Plugin version
.version = ECMC_EXAMPLE_PLUGIN_VERSION,