diff --git a/.gitignore b/.gitignore index f8221a2..02bf308 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,6 @@ core.* *_old/ *PVs.list *-loc/*.Makefile -ecmc_plugin_scope/*.Makefile +ecmc_plugin_motion/*.Makefile +*__* +O* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e873d66 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,51 @@ +{ + "files.associations": { + "string": "cpp", + "array": "cpp", + "string_view": "cpp", + "sstream": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "cinttypes": "cpp" + } +} \ No newline at end of file diff --git a/GNUmakefile b/GNUmakefile index 91a9a9d..e062ae0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -30,16 +30,15 @@ ecmc_VERSION = 9.1.0 #USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB} #USR_LDFLAGS += -L ${EC_MASTER_LIB} # -#BASE_DIR = . -#SRC_DIR = $(BASE_DIR)/src +BASE_DIR = . +SRC_DIR = $(BASE_DIR)/src #DB_DIR = $(BASE_DIR)/Db # -#SOURCES += $(SRC_DIR)/ecmcPluginSafety.c -#SOURCES += $(SRC_DIR)/ecmcSafetyPlgWrap.cpp -#SOURCES += $(SRC_DIR)/ecmcSS1SafetyGroup.cpp -# -##SOURCES += $(foreach d,${SRC_DIR}, $(wildcard $d/*.c) $(wildcard $d/*.cpp)) -#HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h)) + +SOURCES += $(SRC_DIR)/ecmcDAQDataArray.cpp +SOURCES += $(SRC_DIR)/ecmcDAQDataChannel.cpp +SOURCES += $(SRC_DIR)/ecmcDAQWrap.cpp + #DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd)) #SCRIPTS += $(BASE_DIR)/startup.cmd #SCRIPTS += $(BASE_DIR)/scripts/addSS1Group.cmd diff --git a/src/ecmcDAQChannelItem.h b/src/ecmcDAQChannelItem.h index bdbac3d..568c9ed 100644 --- a/src/ecmcDAQChannelItem.h +++ b/src/ecmcDAQChannelItem.h @@ -15,7 +15,10 @@ #include #include #include +#include "string.h" #include "ecmcDataItem.h" +#include "ecmcPluginClient.h" +#include "ecmcDAQDefs.h" enum class ecmcDAQDataFormat { raw = 0, time_micro_s = 1, @@ -36,10 +39,11 @@ enum class ecmcDAQDataFormat { raw = 0, class ecmcDAQChannelItem { public: - ecmcDAQChannelItem(char* name, ecmcDAQDataFormat format) { + ecmcDAQChannelItem(const char* name, ecmcDAQDataFormat format) { dataItem_ = NULL; dataItemInfo_ = NULL; name_ = name; + cstrName_ = strdup(name); format_ = format; // micro s in int32 sampleTimeCompensation_ = 0; dataIndexToReturn_ = 0; @@ -57,10 +61,15 @@ class ecmcDAQChannelItem { float64Ptr_ = NULL; dataType_ = ECMC_EC_NONE; } + + ~ecmcDAQChannelItem() { + free(cstrName_); + } + void connectToSource() { // Get data item - dataItem_ = (ecmcDataItem*) getEcmcDataItem(name_.c_str()); + dataItem_ = (ecmcDataItem*) getEcmcDataItem(cstrName_); if(!dataItem_) { printf("ERROR: DataItem %s NULL.\n", name_.c_str()); throw std::runtime_error( "ERROR: DataItem NULL." ); @@ -77,10 +86,10 @@ class ecmcDAQChannelItem { dataType_= dataItemInfo_->dataType; // Execute here to be sure that startup.cmd of ecmc(cfg) has been executed. switch(format_) { - case ecmcDAQDataFormat.time_micro_s_minus_period: + case ecmcDAQDataFormat::time_micro_s_minus_period: sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000; break; - case ecmcDAQDataFormat.time_ns_minus_period: + case ecmcDAQDataFormat::time_ns_minus_period: sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000000; break; default: @@ -108,7 +117,7 @@ class ecmcDAQChannelItem { * looping with false will return new data for each call untill theres no more data * before call, check if data is available with notEmpty() */ - double getData(bool first) { + double getData(int first) { double data = 0; uint64_t time = 0; if(first) { @@ -116,85 +125,85 @@ class ecmcDAQChannelItem { } if(dataIndexToReturn_ >= dataElementCount_) { - printf("ERROR: Try to read outside data buffer for data item %s\n", name_); + printf("ERROR: Try to read outside data buffer for data item %s\n", name_.c_str()); return -1; } switch (dataType_) { case ECMC_EC_B1: - uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)(*uint8Ptr_ & 0x01); break; case ECMC_EC_B2: - uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)(*uint8Ptr_ & 0x03); break; case ECMC_EC_B3: - uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)(*uint8Ptr_ & 0x07); break; case ECMC_EC_B4: - uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)(*uint8Ptr_ & 0x0F); break; case ECMC_EC_U8: - uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *uint8Ptr_; data = (double)*uint8Ptr_; break; case ECMC_EC_S8: - int8Ptr_ = (int8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + int8Ptr_ = (int8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *int8Ptr_; data = (double)*int8Ptr_; break; case ECMC_EC_U16: - uint16Ptr_ = (uint16_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint16Ptr_ = (uint16_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *uint16Ptr_; data = (double)*uint16Ptr_; break; case ECMC_EC_S16: - int16Ptr_ = (int16_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + int16Ptr_ = (int16_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *int16Ptr_; data = (double)*int16Ptr_; break; case ECMC_EC_U32: - uint32Ptr_ = (uint32_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint32Ptr_ = (uint32_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *uint32Ptr_; data = (double)*uint32Ptr_; break; case ECMC_EC_S32: - int32Ptr_ = (int32_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + int32Ptr_ = (int32_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *int32Ptr_; data = (double)*int32Ptr_; break; case ECMC_EC_U64: - uint64Ptr_ = (uint64_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + uint64Ptr_ = (uint64_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *uint64Ptr_; data = (double)*uint64Ptr_; break; case ECMC_EC_S64: - int64Ptr_ = (int64_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + int64Ptr_ = (int64_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; time = *uint64Ptr_; data = (double)*int64Ptr_; break; case ECMC_EC_F32: - float32Ptr_ = (float *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + float32Ptr_ = (float *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)*float32Ptr_; break; case ECMC_EC_F64: - float64Ptr_ = (double *)&buffer_[dataIndexToReturn_ * bytesPerElement_]; + float64Ptr_ = (double *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_]; data = (double)*float64Ptr_; break; @@ -213,16 +222,16 @@ class ecmcDAQChannelItem { double formatData(double data, uint64_t time){ // Time format only works for integer values, otherwise a 0 will be returned switch(format_) { - case ecmcDAQDataFormat.time_micro_s: + case ecmcDAQDataFormat::time_micro_s: time = time / 1000; // micro seconds data = (double)(time & 0xFFFFFFFF); //keep 32bits break; - case ecmcDAQDataFormat.time_micro_s_minus_period: + case ecmcDAQDataFormat::time_micro_s_minus_period: time = time / 1000; // micro seconds data = (double)(time & 0xFFFFFFFF); //keep 32bits data = data - sampleTimeCompensation_; break; - case ecmcDAQDataFormat.time_ns_minus_period: + case ecmcDAQDataFormat::time_ns_minus_period: data = (double)(time - (uint64_t)sampleTimeCompensation_); break; default: @@ -246,6 +255,7 @@ class ecmcDAQChannelItem { ecmcDataItem* dataItem_; ecmcDataItemInfo* dataItemInfo_; std::string name_; + char *cstrName_; ecmcDAQDataFormat format_; double sampleTimeCompensation_; size_t dataIndexToReturn_; diff --git a/src/ecmcDAQDataArray.cpp b/src/ecmcDAQDataArray.cpp index 93b0344..0b47417 100644 --- a/src/ecmcDAQDataArray.cpp +++ b/src/ecmcDAQDataArray.cpp @@ -1,4 +1,4 @@ -7/*************************************************************************\ +/*************************************************************************\ * Copyright (c) 2024 PSI * ecmc is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. @@ -14,15 +14,41 @@ // Needed to get headers in ecmc right... #define ECMC_IS_PLUGIN +#define ECMC_PLUGIN_ASYN_PREFIX "plugin.daq" +#define ECMC_PLUGIN_ASYN_ENABLE "enable" +#define ECMC_PLUGIN_ASYN_RAWDATA "rawdata" + #include #include "ecmcDAQDataArray.h" #include "ecmcPluginClient.h" -ecmcDAQDataArray::ecmcDAQDataArray(size_t nelm){ - channelCounter_ = 0; - dataElementCount_= 0; - totalElementCount_ = 0; + + +ecmcDAQDataArray::ecmcDAQDataArray(const char* name, const 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 */ + { + channelCounter_ = 0; + dataElementCount_ = 0; + totalElementCount_ = 0; firstDataElementIndex_ = 0; + asynEnableId_ = 1; + asynRawDataId_ = -1; + enablePlugin_ = -1; + dataSourcesLinked_ = 0; + name_ = name; } ecmcDAQDataArray::~ecmcDAQDataArray() { @@ -30,17 +56,17 @@ ecmcDAQDataArray::~ecmcDAQDataArray() { } void ecmcDAQDataArray::addChannel(int type) { - dataChannels_.push_back(new ecmcDAQDataChannel(type); + dataChannels_.push_back(new ecmcDAQDataChannel(type)); channelCounter_++; } -void ecmcDAQDataArray::addDataItemToChannel(char* name, int format) { +void ecmcDAQDataArray::addDataItemToChannel(const char* name, int format) { // Always add to last added channel - dataChannels_.back().addDataItem(name, format); + dataChannels_.back()->addDataItem(name, format); } void ecmcDAQDataArray::connectToDataSources() { - if( dataSourceLinked_ ) { + if( dataSourcesLinked_ ) { return; } @@ -50,7 +76,7 @@ void ecmcDAQDataArray::connectToDataSources() { if(!(*pDataCh)) { throw std::runtime_error( "Channel empty.."); } - (*pDataCh)->connectToSources(); + (*pDataCh)->connectToDataSources(); dataElementCount_ = dataElementCount_ + (*pDataCh)->getDataElementCount(); } @@ -59,7 +85,7 @@ void ecmcDAQDataArray::connectToDataSources() { // Now we we can finally allocate teh buffer (ecmc is still not in realtime, enterRT) buffer_ = new double [totalElementCount_]; - memset(buffer_,0,sizeof(buffer_)) + memset(buffer_,0,totalElementCount_*sizeof(double)); // Build header buildArrayHeader(); @@ -67,7 +93,7 @@ void ecmcDAQDataArray::connectToDataSources() { // Register asyn parameters initAsyn(); - dataSourceLinked_ = 1; + dataSourcesLinked_ = 1; } /* Prepare header first in array, 4 elements per channel: @@ -90,7 +116,7 @@ void ecmcDAQDataArray::buildArrayHeader(){ size_t dataStartOffset = channelCounter_* 4 + 1; firstDataElementIndex_ = dataStartOffset; - if( nelm_ < dataStartOffset) { + if( totalElementCount_ < dataStartOffset) { throw std::runtime_error( "Array to small, header will not fit (array size must be bigger than total data size plus 4*data_channel_count+1).."); } @@ -120,13 +146,59 @@ void ecmcDAQDataArray::buildArrayHeader(){ } } +void ecmcDAQDataArray::setEnable(int enable) { + enablePlugin_ = enable; +} + void ecmcDAQDataArray::execute() { - + if(!enablePlugin_) { + return; + } + + size_t index = firstDataElementIndex_ ; + for(std::vector::iterator pDataCh = dataChannels_.begin(); pDataCh != dataChannels_.end(); ++pDataCh) { + //always atleast one data item in a channel. Set "first" bit in call to getData() + buffer_[index]=(*pDataCh)->getData(1); + index++; + while(!(*pDataCh)->empty()) { + buffer_[index]=(*pDataCh)->getData(0); + } + } + updateAsyn(); +} + +void ecmcDAQDataArray::updateAsyn() { + doCallbacksFloat64Array(buffer_, totalElementCount_, asynRawDataId_,0); + setIntegerParam(asynEnableId_, enablePlugin_); + // Update integers + callParamCallbacks(); } void ecmcDAQDataArray::initAsyn() { + + // Add enable "plugin.daq.enable" + std::string paramName =ECMC_PLUGIN_ASYN_PREFIX "."; + paramName += name_; + paramName += "."; + paramName += ECMC_PLUGIN_ASYN_ENABLE; + if( createParam(0, paramName.c_str(), asynParamInt32, &asynEnableId_) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter enable"); + } + setIntegerParam(asynEnableId_, enablePlugin_); + + // Add rawdata "plugin.fft%d.rawdata" + paramName =ECMC_PLUGIN_ASYN_PREFIX "."; + paramName += name_; + paramName += "."; + paramName += ECMC_PLUGIN_ASYN_RAWDATA; + + if( createParam(0, paramName.c_str(), asynParamFloat64Array, &asynRawDataId_ ) != asynSuccess ) { + throw std::runtime_error("Failed create asyn parameter rawdata"); + } + doCallbacksFloat64Array(buffer_, totalElementCount_, asynRawDataId_,0); + + // Update integers + callParamCallbacks(); + return; } - - - diff --git a/src/ecmcDAQDataArray.h b/src/ecmcDAQDataArray.h index 4245484..e8da595 100644 --- a/src/ecmcDAQDataArray.h +++ b/src/ecmcDAQDataArray.h @@ -16,28 +16,38 @@ #include #include #include "ecmcDAQDataChannel.h" +#include "ecmcAsynPortDriver.h" + +/* Class to format an array of ecmcDAQDataChannels with headers and push over asyn to epics */ +class ecmcDAQDataArray : public asynPortDriver { -/* Class to fromat an array of ecmcDAQDataChannels with headers and push over asyn to epics */ -class ecmcDAQDataArray { public: - ecmcDAQDataArray(size_t nelm); + ecmcDAQDataArray(const char* name, const char* portName); ~ecmcDAQDataArray(); void connectToDataSources(); void execute(); void addChannel(int type); // Always add to last added channel - void addDataItemToChannel(char* name, int format); + void addDataItemToChannel(const char* name, int format); + void setEnable(int enable); private: + void buildArrayHeader(); + void initAsyn(); + void updateAsyn(); + std::string name_; double *buffer_; std::vector dataChannels_; - size_t channelCounter_; - size_t dataElementCount_; - size_t totalElementCount_; - size_t firstDataElementIndex_; + size_t channelCounter_; + size_t dataElementCount_; + size_t totalElementCount_; + size_t firstDataElementIndex_; + bool dataSourcesLinked_; + // Asyn + int asynEnableId_; // Enable/disable + int asynRawDataId_; // Raw data buffer + int enablePlugin_; // Enable + }; #endif /* ECMC_DAQ_DATA_ARRAY_H_ */ - - - diff --git a/src/ecmcDAQDataChannel.cpp b/src/ecmcDAQDataChannel.cpp index bd33d49..a2fb011 100644 --- a/src/ecmcDAQDataChannel.cpp +++ b/src/ecmcDAQDataChannel.cpp @@ -1,4 +1,4 @@ -7/*************************************************************************\ +/*************************************************************************\ * Copyright (c) 2024 PSI * ecmc is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. @@ -16,25 +16,26 @@ #include #include "ecmcDAQDataChannel.h" -#include "ecmcPluginClient.h" ecmcDAQDataChannel::ecmcDAQDataChannel(int type){ - itemCounter_ = 0; - type_ = (double) type; - dataElementCount_ = 0; + itemCounter_ = 0; + type_ = (double) type; + dataElementCount_ = 0; + returnedDataCounter_ = 0; + currItemIndex_ = 0; + dataSourcesLinked_ = 0; } ecmcDAQDataChannel::~ecmcDAQDataChannel() { - } -void ecmcDAQDataChannel::addDataItem(char* name, int timeFormat) { - dataItems_.push_back(new ecmcDAQChannelItem(name, timeFormat); +void ecmcDAQDataChannel::addDataItem(const char* name, int format) { + dataItems_.push_back(new ecmcDAQChannelItem(name, (ecmcDAQDataFormat)format)); itemCounter_++; } void ecmcDAQDataChannel::connectToDataSources() { - if( dataSourceLinked_ ) { + if( dataSourcesLinked_ ) { return; } @@ -48,20 +49,40 @@ void ecmcDAQDataChannel::connectToDataSources() { dataElementCount_ = dataElementCount_ + (*pDataItem)->getDataElementCount(); } - dataSourceLinked_ = 1; + dataSourcesLinked_ = 1; } size_t ecmcDAQDataChannel::getDataElementCount(){ return dataElementCount_; } -double ecmcDAQDataChannel:getData(){ - +double ecmcDAQDataChannel::getType() { + return type_; } -bool ecmcDAQDataChannel:empty(){ +double ecmcDAQDataChannel::getData(int first){ + if(first) { + currItemIndex_ = 0; + } else { + first = false; + } + if(dataItems_[currItemIndex_]->empty()) { + // get first index of next dataItem + first = true; + currItemIndex_++; + } + + if(currItemIndex_>=itemCounter_) { + printf("No more data here!!!\n"); + return 0; + //throw std::runtime_error( "Item index out of range"); + } + + returnedDataCounter_++; + return dataItems_[currItemIndex_]->getData(first); } - - +bool ecmcDAQDataChannel::empty(){ + return dataElementCount_>=returnedDataCounter_; +} diff --git a/src/ecmcDAQDataChannel.h b/src/ecmcDAQDataChannel.h index 50c11e5..e60c7ea 100644 --- a/src/ecmcDAQDataChannel.h +++ b/src/ecmcDAQDataChannel.h @@ -15,23 +15,28 @@ #include #include #include +#include "ecmcDAQChannelItem.h" /* Class for an data channel */ class ecmcDAQDataChannel { public: ecmcDAQDataChannel(int type); ~ecmcDAQDataChannel(); - void connectToSources(); - void addDataItem(char* name, int timeFormat); + void connectToDataSources(); + void addDataItem(const char* name, int format); size_t getDataElementCount(); - double getData(); + double getData(int first); bool empty(); + double getType(); private: std::vector dataItems_; - size_t itemCounter_; double type_; + size_t itemCounter_; size_t dataElementCount_; + size_t returnedDataCounter_; + size_t currItemIndex_; + int dataSourcesLinked_; }; #endif /* ECMC_DAQ_DATA_CHANNEL_H_ */ diff --git a/src/ecmcDAQDefs.h b/src/ecmcDAQDefs.h index ebdd55b..06847cd 100644 --- a/src/ecmcDAQDefs.h +++ b/src/ecmcDAQDefs.h @@ -1,11 +1,11 @@ /*************************************************************************\ -* Copyright (c) 2019 European Spallation Source ERIC +* Copyright (c) 2024 PSI * ecmc is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. * -* ecmcScopeDefs.h +* ecmcDAQDefs.h * -* Created on: Sept 21, 2020 +* Created on: Mar. 04, 2024 * Author: anderssandstrom * Credits to https://github.com/sgreg/dynamic-loading * @@ -16,13 +16,9 @@ // Options #define ECMC_PLUGIN_DBG_PRINT_OPTION_CMD "DBG_PRINT=" -#define ECMC_PLUGIN_SOURCE_OPTION_CMD "SOURCE=" -#define ECMC_PLUGIN_SOURCE_NEXTTIME_OPTION_CMD "SOURCE_NEXTTIME=" -#define ECMC_PLUGIN_TRIGG_OPTION_CMD "TRIGG=" -#define ECMC_PLUGIN_RESULT_ELEMENTS_OPTION_CMD "RESULT_ELEMENTS=" #define ECMC_PLUGIN_ENABLE_OPTION_CMD "ENABLE=" -// Default size (must be n²) -#define ECMC_PLUGIN_DEFAULT_BUFFER_SIZE 4096 + +#define ERROR_MEM_INVALID_DATA_TYPE 1000; #endif /* ECMC_SCOPE_DEFS_H_ */ diff --git a/src/ecmcDAQWrap.cpp b/src/ecmcDAQWrap.cpp index 2106b95..a1f32a6 100644 --- a/src/ecmcDAQWrap.cpp +++ b/src/ecmcDAQWrap.cpp @@ -18,51 +18,77 @@ #include #include #include "ecmcDAQWrap.h" -#include "ecmcDAQChannel.h" +#include "ecmcDAQDataArray.h" #include "ecmcDAQDefs.h" #include +#include #define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.DAQ" #define ECMC_PLUGIN_DAQ_ERROR_CODE 1 -static std::vector channels; -static int channelCounter = 0; +static std::vector arrays; +static int arrayCounter = 0; -int createDAQ(char* name) { +int createDAQArray(const char* name, const char* portName ) { // create new ecmcFFT object - ecmcDAQChannel* channel = NULL; + ecmcDAQDataArray* array = NULL; try { - channel = new ecmcDAQChannel(name); + array = new ecmcDAQDataArray(name, portName); } catch(std::exception& e) { - if(scope) { - delete channel; + if(array) { + delete array; } printf("Exception: %s. Plugin will unload.\n",e.what()); return ECMC_PLUGIN_DAQ_ERROR_CODE; } - scopes.push_back(scope); - channelCounter++; + arrays.push_back(array); + arrayCounter++; return 0; } +int createDAQChannel(int type) { + + try { + arrays.back()->addChannel(type); + } + catch(std::exception& e) { + printf("Exception: %s. Plugin will unload.\n",e.what()); + return ECMC_PLUGIN_DAQ_ERROR_CODE; + } + + return 0; +} + +int createDAQItem(const char* name, int type) { + try { + arrays.back()->addDataItemToChannel(name,type); + } + catch(std::exception& e) { + printf("Exception: %s. Plugin will unload.\n",e.what()); + return ECMC_PLUGIN_DAQ_ERROR_CODE; + } + + return 0; +} + void deleteAllDAQs() { - for(std::vector::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) { - if(*pDAQChannel) { - delete (*pDAQChannel); + for(std::vector::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) { + if(*pDAQArray) { + delete (*pDAQArray); } } } int linkDataToDAQs() { - for(std::vector::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) { - if(*pDAQChannel) { + for(std::vector::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) { + if(*pDAQArray) { try { - (*pDAQChannel)->connectToDataSources(); + (*pDAQArray)->connectToDataSources(); } catch(std::exception& e) { printf("Exception: %s. Plugin will unload.\n",e.what()); @@ -73,22 +99,22 @@ int linkDataToDAQs() { return 0; } -int enableDAQ(int scopeIndex, int enable) { - try { - scopes.at(scopeIndex)->setEnable(enable); - } - catch(std::exception& e) { - printf("Exception: %s. DAQ index out of range.\n",e.what()); - return ECMC_PLUGIN_DAQ_ERROR_CODE; - } - return 0; -} +//int enableDAQ(int scopeIndex, int enable) { +// try { +// arrays.at(scopeIndex)->setEnable(enable); +// } +// catch(std::exception& e) { +// printf("Exception: %s. DAQ index out of range.\n",e.what()); +// return ECMC_PLUGIN_DAQ_ERROR_CODE; +// } +// return 0; +//} -int executeDAQCs() { +int executeDAQs() { try { - for(std::vector::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) { - if(*pDAQChannel) { - (*pDAQChannel)->execute(); + for(std::vector::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) { + if(*pDAQArray) { + (*pDAQArray)->execute(); } } } @@ -99,52 +125,122 @@ int executeDAQCs() { return 0; } - - - /** - * EPICS iocsh shell command: ecmcAddDataType1ToChannel + * EPICS iocsh shell command: ecmcAddDAQArray */ -void ecmcAddDataType1ToChannelPrintHelp() { +void ecmcAddDAQArrayHelp() { printf("\n"); - printf(" Use ecmcAddDataType1ToChannel(, )\n"); - printf(" : Name of channel to add data to.\n"); - printf(" : Axis index to add.\n"); - printf(" : Axis standstill velo limit [unit of axis].\n"); - printf("