builds
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,4 +13,6 @@ core.*
|
|||||||
*_old/
|
*_old/
|
||||||
*PVs.list
|
*PVs.list
|
||||||
*-loc/*.Makefile
|
*-loc/*.Makefile
|
||||||
ecmc_plugin_scope/*.Makefile
|
ecmc_plugin_motion/*.Makefile
|
||||||
|
*__*
|
||||||
|
O*
|
||||||
51
.vscode/settings.json
vendored
Normal file
51
.vscode/settings.json
vendored
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
GNUmakefile
15
GNUmakefile
@@ -30,16 +30,15 @@ ecmc_VERSION = 9.1.0
|
|||||||
#USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
|
#USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
|
||||||
#USR_LDFLAGS += -L ${EC_MASTER_LIB}
|
#USR_LDFLAGS += -L ${EC_MASTER_LIB}
|
||||||
#
|
#
|
||||||
#BASE_DIR = .
|
BASE_DIR = .
|
||||||
#SRC_DIR = $(BASE_DIR)/src
|
SRC_DIR = $(BASE_DIR)/src
|
||||||
#DB_DIR = $(BASE_DIR)/Db
|
#DB_DIR = $(BASE_DIR)/Db
|
||||||
#
|
#
|
||||||
#SOURCES += $(SRC_DIR)/ecmcPluginSafety.c
|
|
||||||
#SOURCES += $(SRC_DIR)/ecmcSafetyPlgWrap.cpp
|
SOURCES += $(SRC_DIR)/ecmcDAQDataArray.cpp
|
||||||
#SOURCES += $(SRC_DIR)/ecmcSS1SafetyGroup.cpp
|
SOURCES += $(SRC_DIR)/ecmcDAQDataChannel.cpp
|
||||||
#
|
SOURCES += $(SRC_DIR)/ecmcDAQWrap.cpp
|
||||||
##SOURCES += $(foreach d,${SRC_DIR}, $(wildcard $d/*.c) $(wildcard $d/*.cpp))
|
|
||||||
#HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h))
|
|
||||||
#DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd))
|
#DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd))
|
||||||
#SCRIPTS += $(BASE_DIR)/startup.cmd
|
#SCRIPTS += $(BASE_DIR)/startup.cmd
|
||||||
#SCRIPTS += $(BASE_DIR)/scripts/addSS1Group.cmd
|
#SCRIPTS += $(BASE_DIR)/scripts/addSS1Group.cmd
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "string.h"
|
||||||
#include "ecmcDataItem.h"
|
#include "ecmcDataItem.h"
|
||||||
|
#include "ecmcPluginClient.h"
|
||||||
|
#include "ecmcDAQDefs.h"
|
||||||
|
|
||||||
enum class ecmcDAQDataFormat { raw = 0,
|
enum class ecmcDAQDataFormat { raw = 0,
|
||||||
time_micro_s = 1,
|
time_micro_s = 1,
|
||||||
@@ -36,10 +39,11 @@ enum class ecmcDAQDataFormat { raw = 0,
|
|||||||
|
|
||||||
class ecmcDAQChannelItem {
|
class ecmcDAQChannelItem {
|
||||||
public:
|
public:
|
||||||
ecmcDAQChannelItem(char* name, ecmcDAQDataFormat format) {
|
ecmcDAQChannelItem(const char* name, ecmcDAQDataFormat format) {
|
||||||
dataItem_ = NULL;
|
dataItem_ = NULL;
|
||||||
dataItemInfo_ = NULL;
|
dataItemInfo_ = NULL;
|
||||||
name_ = name;
|
name_ = name;
|
||||||
|
cstrName_ = strdup(name);
|
||||||
format_ = format; // micro s in int32
|
format_ = format; // micro s in int32
|
||||||
sampleTimeCompensation_ = 0;
|
sampleTimeCompensation_ = 0;
|
||||||
dataIndexToReturn_ = 0;
|
dataIndexToReturn_ = 0;
|
||||||
@@ -57,10 +61,15 @@ class ecmcDAQChannelItem {
|
|||||||
float64Ptr_ = NULL;
|
float64Ptr_ = NULL;
|
||||||
dataType_ = ECMC_EC_NONE;
|
dataType_ = ECMC_EC_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ecmcDAQChannelItem() {
|
||||||
|
free(cstrName_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void connectToSource() {
|
void connectToSource() {
|
||||||
// Get data item
|
// Get data item
|
||||||
dataItem_ = (ecmcDataItem*) getEcmcDataItem(name_.c_str());
|
dataItem_ = (ecmcDataItem*) getEcmcDataItem(cstrName_);
|
||||||
if(!dataItem_) {
|
if(!dataItem_) {
|
||||||
printf("ERROR: DataItem %s NULL.\n", name_.c_str());
|
printf("ERROR: DataItem %s NULL.\n", name_.c_str());
|
||||||
throw std::runtime_error( "ERROR: DataItem NULL." );
|
throw std::runtime_error( "ERROR: DataItem NULL." );
|
||||||
@@ -77,10 +86,10 @@ class ecmcDAQChannelItem {
|
|||||||
dataType_= dataItemInfo_->dataType;
|
dataType_= dataItemInfo_->dataType;
|
||||||
// Execute here to be sure that startup.cmd of ecmc(cfg) has been executed.
|
// Execute here to be sure that startup.cmd of ecmc(cfg) has been executed.
|
||||||
switch(format_) {
|
switch(format_) {
|
||||||
case ecmcDAQDataFormat.time_micro_s_minus_period:
|
case ecmcDAQDataFormat::time_micro_s_minus_period:
|
||||||
sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000;
|
sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000;
|
||||||
break;
|
break;
|
||||||
case ecmcDAQDataFormat.time_ns_minus_period:
|
case ecmcDAQDataFormat::time_ns_minus_period:
|
||||||
sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000000;
|
sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -108,7 +117,7 @@ class ecmcDAQChannelItem {
|
|||||||
* looping with false will return new data for each call untill theres no more data
|
* looping with false will return new data for each call untill theres no more data
|
||||||
* before call, check if data is available with notEmpty()
|
* before call, check if data is available with notEmpty()
|
||||||
*/
|
*/
|
||||||
double getData(bool first) {
|
double getData(int first) {
|
||||||
double data = 0;
|
double data = 0;
|
||||||
uint64_t time = 0;
|
uint64_t time = 0;
|
||||||
if(first) {
|
if(first) {
|
||||||
@@ -116,85 +125,85 @@ class ecmcDAQChannelItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dataIndexToReturn_ >= dataElementCount_) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dataType_) {
|
switch (dataType_) {
|
||||||
case ECMC_EC_B1:
|
case ECMC_EC_B1:
|
||||||
uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)(*uint8Ptr_ & 0x01);
|
data = (double)(*uint8Ptr_ & 0x01);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_B2:
|
case ECMC_EC_B2:
|
||||||
uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)(*uint8Ptr_ & 0x03);
|
data = (double)(*uint8Ptr_ & 0x03);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_B3:
|
case ECMC_EC_B3:
|
||||||
uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)(*uint8Ptr_ & 0x07);
|
data = (double)(*uint8Ptr_ & 0x07);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_B4:
|
case ECMC_EC_B4:
|
||||||
uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)(*uint8Ptr_ & 0x0F);
|
data = (double)(*uint8Ptr_ & 0x0F);
|
||||||
break;
|
break;
|
||||||
case ECMC_EC_U8:
|
case ECMC_EC_U8:
|
||||||
uint8Ptr_ = (uint8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint8Ptr_ = (uint8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *uint8Ptr_;
|
time = *uint8Ptr_;
|
||||||
data = (double)*uint8Ptr_;
|
data = (double)*uint8Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_S8:
|
case ECMC_EC_S8:
|
||||||
int8Ptr_ = (int8_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
int8Ptr_ = (int8_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *int8Ptr_;
|
time = *int8Ptr_;
|
||||||
data = (double)*int8Ptr_;
|
data = (double)*int8Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_U16:
|
case ECMC_EC_U16:
|
||||||
uint16Ptr_ = (uint16_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint16Ptr_ = (uint16_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *uint16Ptr_;
|
time = *uint16Ptr_;
|
||||||
data = (double)*uint16Ptr_;
|
data = (double)*uint16Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_S16:
|
case ECMC_EC_S16:
|
||||||
int16Ptr_ = (int16_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
int16Ptr_ = (int16_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *int16Ptr_;
|
time = *int16Ptr_;
|
||||||
data = (double)*int16Ptr_;
|
data = (double)*int16Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_U32:
|
case ECMC_EC_U32:
|
||||||
uint32Ptr_ = (uint32_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint32Ptr_ = (uint32_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *uint32Ptr_;
|
time = *uint32Ptr_;
|
||||||
data = (double)*uint32Ptr_;
|
data = (double)*uint32Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_S32:
|
case ECMC_EC_S32:
|
||||||
int32Ptr_ = (int32_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
int32Ptr_ = (int32_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *int32Ptr_;
|
time = *int32Ptr_;
|
||||||
data = (double)*int32Ptr_;
|
data = (double)*int32Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_U64:
|
case ECMC_EC_U64:
|
||||||
uint64Ptr_ = (uint64_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
uint64Ptr_ = (uint64_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *uint64Ptr_;
|
time = *uint64Ptr_;
|
||||||
data = (double)*uint64Ptr_;
|
data = (double)*uint64Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_S64:
|
case ECMC_EC_S64:
|
||||||
int64Ptr_ = (int64_t *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
int64Ptr_ = (int64_t *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
time = *uint64Ptr_;
|
time = *uint64Ptr_;
|
||||||
data = (double)*int64Ptr_;
|
data = (double)*int64Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_F32:
|
case ECMC_EC_F32:
|
||||||
float32Ptr_ = (float *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
float32Ptr_ = (float *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)*float32Ptr_;
|
data = (double)*float32Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECMC_EC_F64:
|
case ECMC_EC_F64:
|
||||||
float64Ptr_ = (double *)&buffer_[dataIndexToReturn_ * bytesPerElement_];
|
float64Ptr_ = (double *)&dataItemInfo_->data[dataIndexToReturn_ * bytesPerElement_];
|
||||||
data = (double)*float64Ptr_;
|
data = (double)*float64Ptr_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -213,16 +222,16 @@ class ecmcDAQChannelItem {
|
|||||||
double formatData(double data, uint64_t time){
|
double formatData(double data, uint64_t time){
|
||||||
// Time format only works for integer values, otherwise a 0 will be returned
|
// Time format only works for integer values, otherwise a 0 will be returned
|
||||||
switch(format_) {
|
switch(format_) {
|
||||||
case ecmcDAQDataFormat.time_micro_s:
|
case ecmcDAQDataFormat::time_micro_s:
|
||||||
time = time / 1000; // micro seconds
|
time = time / 1000; // micro seconds
|
||||||
data = (double)(time & 0xFFFFFFFF); //keep 32bits
|
data = (double)(time & 0xFFFFFFFF); //keep 32bits
|
||||||
break;
|
break;
|
||||||
case ecmcDAQDataFormat.time_micro_s_minus_period:
|
case ecmcDAQDataFormat::time_micro_s_minus_period:
|
||||||
time = time / 1000; // micro seconds
|
time = time / 1000; // micro seconds
|
||||||
data = (double)(time & 0xFFFFFFFF); //keep 32bits
|
data = (double)(time & 0xFFFFFFFF); //keep 32bits
|
||||||
data = data - sampleTimeCompensation_;
|
data = data - sampleTimeCompensation_;
|
||||||
break;
|
break;
|
||||||
case ecmcDAQDataFormat.time_ns_minus_period:
|
case ecmcDAQDataFormat::time_ns_minus_period:
|
||||||
data = (double)(time - (uint64_t)sampleTimeCompensation_);
|
data = (double)(time - (uint64_t)sampleTimeCompensation_);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -246,6 +255,7 @@ class ecmcDAQChannelItem {
|
|||||||
ecmcDataItem* dataItem_;
|
ecmcDataItem* dataItem_;
|
||||||
ecmcDataItemInfo* dataItemInfo_;
|
ecmcDataItemInfo* dataItemInfo_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
char *cstrName_;
|
||||||
ecmcDAQDataFormat format_;
|
ecmcDAQDataFormat format_;
|
||||||
double sampleTimeCompensation_;
|
double sampleTimeCompensation_;
|
||||||
size_t dataIndexToReturn_;
|
size_t dataIndexToReturn_;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
7/*************************************************************************\
|
/*************************************************************************\
|
||||||
* Copyright (c) 2024 PSI
|
* Copyright (c) 2024 PSI
|
||||||
* ecmc is distributed subject to a Software License Agreement found
|
* ecmc is distributed subject to a Software License Agreement found
|
||||||
* in file LICENSE that is included with this distribution.
|
* in file LICENSE that is included with this distribution.
|
||||||
@@ -14,15 +14,41 @@
|
|||||||
// Needed to get headers in ecmc right...
|
// Needed to get headers in ecmc right...
|
||||||
#define ECMC_IS_PLUGIN
|
#define ECMC_IS_PLUGIN
|
||||||
|
|
||||||
|
#define ECMC_PLUGIN_ASYN_PREFIX "plugin.daq"
|
||||||
|
#define ECMC_PLUGIN_ASYN_ENABLE "enable"
|
||||||
|
#define ECMC_PLUGIN_ASYN_RAWDATA "rawdata"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "ecmcDAQDataArray.h"
|
#include "ecmcDAQDataArray.h"
|
||||||
#include "ecmcPluginClient.h"
|
#include "ecmcPluginClient.h"
|
||||||
|
|
||||||
ecmcDAQDataArray::ecmcDAQDataArray(size_t nelm){
|
|
||||||
channelCounter_ = 0;
|
|
||||||
dataElementCount_= 0;
|
ecmcDAQDataArray::ecmcDAQDataArray(const char* name, const char* portName)
|
||||||
totalElementCount_ = 0;
|
: 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;
|
firstDataElementIndex_ = 0;
|
||||||
|
asynEnableId_ = 1;
|
||||||
|
asynRawDataId_ = -1;
|
||||||
|
enablePlugin_ = -1;
|
||||||
|
dataSourcesLinked_ = 0;
|
||||||
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecmcDAQDataArray::~ecmcDAQDataArray() {
|
ecmcDAQDataArray::~ecmcDAQDataArray() {
|
||||||
@@ -30,17 +56,17 @@ ecmcDAQDataArray::~ecmcDAQDataArray() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ecmcDAQDataArray::addChannel(int type) {
|
void ecmcDAQDataArray::addChannel(int type) {
|
||||||
dataChannels_.push_back(new ecmcDAQDataChannel(type);
|
dataChannels_.push_back(new ecmcDAQDataChannel(type));
|
||||||
channelCounter_++;
|
channelCounter_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ecmcDAQDataArray::addDataItemToChannel(char* name, int format) {
|
void ecmcDAQDataArray::addDataItemToChannel(const char* name, int format) {
|
||||||
// Always add to last added channel
|
// Always add to last added channel
|
||||||
dataChannels_.back().addDataItem(name, format);
|
dataChannels_.back()->addDataItem(name, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ecmcDAQDataArray::connectToDataSources() {
|
void ecmcDAQDataArray::connectToDataSources() {
|
||||||
if( dataSourceLinked_ ) {
|
if( dataSourcesLinked_ ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +76,7 @@ void ecmcDAQDataArray::connectToDataSources() {
|
|||||||
if(!(*pDataCh)) {
|
if(!(*pDataCh)) {
|
||||||
throw std::runtime_error( "Channel empty..");
|
throw std::runtime_error( "Channel empty..");
|
||||||
}
|
}
|
||||||
(*pDataCh)->connectToSources();
|
(*pDataCh)->connectToDataSources();
|
||||||
dataElementCount_ = dataElementCount_ + (*pDataCh)->getDataElementCount();
|
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)
|
// Now we we can finally allocate teh buffer (ecmc is still not in realtime, enterRT)
|
||||||
buffer_ = new double [totalElementCount_];
|
buffer_ = new double [totalElementCount_];
|
||||||
memset(buffer_,0,sizeof(buffer_))
|
memset(buffer_,0,totalElementCount_*sizeof(double));
|
||||||
|
|
||||||
// Build header
|
// Build header
|
||||||
buildArrayHeader();
|
buildArrayHeader();
|
||||||
@@ -67,7 +93,7 @@ void ecmcDAQDataArray::connectToDataSources() {
|
|||||||
// Register asyn parameters
|
// Register asyn parameters
|
||||||
initAsyn();
|
initAsyn();
|
||||||
|
|
||||||
dataSourceLinked_ = 1;
|
dataSourcesLinked_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare header first in array, 4 elements per channel:
|
/* Prepare header first in array, 4 elements per channel:
|
||||||
@@ -90,7 +116,7 @@ void ecmcDAQDataArray::buildArrayHeader(){
|
|||||||
size_t dataStartOffset = channelCounter_* 4 + 1;
|
size_t dataStartOffset = channelCounter_* 4 + 1;
|
||||||
firstDataElementIndex_ = dataStartOffset;
|
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)..");
|
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() {
|
void ecmcDAQDataArray::execute() {
|
||||||
|
if(!enablePlugin_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t index = firstDataElementIndex_ ;
|
||||||
|
for(std::vector<ecmcDAQDataChannel*>::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() {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,28 +16,38 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "ecmcDAQDataChannel.h"
|
#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:
|
public:
|
||||||
ecmcDAQDataArray(size_t nelm);
|
ecmcDAQDataArray(const char* name, const char* portName);
|
||||||
~ecmcDAQDataArray();
|
~ecmcDAQDataArray();
|
||||||
void connectToDataSources();
|
void connectToDataSources();
|
||||||
void execute();
|
void execute();
|
||||||
void addChannel(int type);
|
void addChannel(int type);
|
||||||
// Always add to last added channel
|
// Always add to last added channel
|
||||||
void addDataItemToChannel(char* name, int format);
|
void addDataItemToChannel(const char* name, int format);
|
||||||
|
void setEnable(int enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void buildArrayHeader();
|
||||||
|
void initAsyn();
|
||||||
|
void updateAsyn();
|
||||||
|
std::string name_;
|
||||||
double *buffer_;
|
double *buffer_;
|
||||||
std::vector<ecmcDAQDataChannel*> dataChannels_;
|
std::vector<ecmcDAQDataChannel*> dataChannels_;
|
||||||
size_t channelCounter_;
|
size_t channelCounter_;
|
||||||
size_t dataElementCount_;
|
size_t dataElementCount_;
|
||||||
size_t totalElementCount_;
|
size_t totalElementCount_;
|
||||||
size_t firstDataElementIndex_;
|
size_t firstDataElementIndex_;
|
||||||
|
bool dataSourcesLinked_;
|
||||||
|
// Asyn
|
||||||
|
int asynEnableId_; // Enable/disable
|
||||||
|
int asynRawDataId_; // Raw data buffer
|
||||||
|
int enablePlugin_; // Enable
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ECMC_DAQ_DATA_ARRAY_H_ */
|
#endif /* ECMC_DAQ_DATA_ARRAY_H_ */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
7/*************************************************************************\
|
/*************************************************************************\
|
||||||
* Copyright (c) 2024 PSI
|
* Copyright (c) 2024 PSI
|
||||||
* ecmc is distributed subject to a Software License Agreement found
|
* ecmc is distributed subject to a Software License Agreement found
|
||||||
* in file LICENSE that is included with this distribution.
|
* in file LICENSE that is included with this distribution.
|
||||||
@@ -16,25 +16,26 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "ecmcDAQDataChannel.h"
|
#include "ecmcDAQDataChannel.h"
|
||||||
#include "ecmcPluginClient.h"
|
|
||||||
|
|
||||||
ecmcDAQDataChannel::ecmcDAQDataChannel(int type){
|
ecmcDAQDataChannel::ecmcDAQDataChannel(int type){
|
||||||
itemCounter_ = 0;
|
itemCounter_ = 0;
|
||||||
type_ = (double) type;
|
type_ = (double) type;
|
||||||
dataElementCount_ = 0;
|
dataElementCount_ = 0;
|
||||||
|
returnedDataCounter_ = 0;
|
||||||
|
currItemIndex_ = 0;
|
||||||
|
dataSourcesLinked_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecmcDAQDataChannel::~ecmcDAQDataChannel() {
|
ecmcDAQDataChannel::~ecmcDAQDataChannel() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ecmcDAQDataChannel::addDataItem(char* name, int timeFormat) {
|
void ecmcDAQDataChannel::addDataItem(const char* name, int format) {
|
||||||
dataItems_.push_back(new ecmcDAQChannelItem(name, timeFormat);
|
dataItems_.push_back(new ecmcDAQChannelItem(name, (ecmcDAQDataFormat)format));
|
||||||
itemCounter_++;
|
itemCounter_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ecmcDAQDataChannel::connectToDataSources() {
|
void ecmcDAQDataChannel::connectToDataSources() {
|
||||||
if( dataSourceLinked_ ) {
|
if( dataSourcesLinked_ ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,20 +49,40 @@ void ecmcDAQDataChannel::connectToDataSources() {
|
|||||||
dataElementCount_ = dataElementCount_ + (*pDataItem)->getDataElementCount();
|
dataElementCount_ = dataElementCount_ + (*pDataItem)->getDataElementCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
dataSourceLinked_ = 1;
|
dataSourcesLinked_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ecmcDAQDataChannel::getDataElementCount(){
|
size_t ecmcDAQDataChannel::getDataElementCount(){
|
||||||
return dataElementCount_;
|
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_;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,23 +15,28 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "ecmcDAQChannelItem.h"
|
||||||
|
|
||||||
/* Class for an data channel */
|
/* Class for an data channel */
|
||||||
class ecmcDAQDataChannel {
|
class ecmcDAQDataChannel {
|
||||||
public:
|
public:
|
||||||
ecmcDAQDataChannel(int type);
|
ecmcDAQDataChannel(int type);
|
||||||
~ecmcDAQDataChannel();
|
~ecmcDAQDataChannel();
|
||||||
void connectToSources();
|
void connectToDataSources();
|
||||||
void addDataItem(char* name, int timeFormat);
|
void addDataItem(const char* name, int format);
|
||||||
size_t getDataElementCount();
|
size_t getDataElementCount();
|
||||||
double getData();
|
double getData(int first);
|
||||||
bool empty();
|
bool empty();
|
||||||
|
double getType();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ecmcDAQChannelItem*> dataItems_;
|
std::vector<ecmcDAQChannelItem*> dataItems_;
|
||||||
size_t itemCounter_;
|
|
||||||
double type_;
|
double type_;
|
||||||
|
size_t itemCounter_;
|
||||||
size_t dataElementCount_;
|
size_t dataElementCount_;
|
||||||
|
size_t returnedDataCounter_;
|
||||||
|
size_t currItemIndex_;
|
||||||
|
int dataSourcesLinked_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ECMC_DAQ_DATA_CHANNEL_H_ */
|
#endif /* ECMC_DAQ_DATA_CHANNEL_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
|
* ecmc is distributed subject to a Software License Agreement found
|
||||||
* in file LICENSE that is included with this distribution.
|
* 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
|
* Author: anderssandstrom
|
||||||
* Credits to https://github.com/sgreg/dynamic-loading
|
* Credits to https://github.com/sgreg/dynamic-loading
|
||||||
*
|
*
|
||||||
@@ -16,13 +16,9 @@
|
|||||||
|
|
||||||
// Options
|
// Options
|
||||||
#define ECMC_PLUGIN_DBG_PRINT_OPTION_CMD "DBG_PRINT="
|
#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="
|
#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_ */
|
#endif /* ECMC_SCOPE_DEFS_H_ */
|
||||||
|
|||||||
@@ -18,51 +18,77 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "ecmcDAQWrap.h"
|
#include "ecmcDAQWrap.h"
|
||||||
#include "ecmcDAQChannel.h"
|
#include "ecmcDAQDataArray.h"
|
||||||
#include "ecmcDAQDefs.h"
|
#include "ecmcDAQDefs.h"
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
#include <iocsh.h>
|
||||||
|
|
||||||
#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.DAQ"
|
#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.DAQ"
|
||||||
#define ECMC_PLUGIN_DAQ_ERROR_CODE 1
|
#define ECMC_PLUGIN_DAQ_ERROR_CODE 1
|
||||||
|
|
||||||
static std::vector<ecmcDAQChannel*> channels;
|
static std::vector<ecmcDAQDataArray*> arrays;
|
||||||
static int channelCounter = 0;
|
static int arrayCounter = 0;
|
||||||
|
|
||||||
int createDAQ(char* name) {
|
int createDAQArray(const char* name, const char* portName ) {
|
||||||
|
|
||||||
// create new ecmcFFT object
|
// create new ecmcFFT object
|
||||||
ecmcDAQChannel* channel = NULL;
|
ecmcDAQDataArray* array = NULL;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
channel = new ecmcDAQChannel(name);
|
array = new ecmcDAQDataArray(name, portName);
|
||||||
}
|
}
|
||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
if(scope) {
|
if(array) {
|
||||||
delete channel;
|
delete array;
|
||||||
}
|
}
|
||||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||||
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes.push_back(scope);
|
arrays.push_back(array);
|
||||||
channelCounter++;
|
arrayCounter++;
|
||||||
|
|
||||||
return 0;
|
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() {
|
void deleteAllDAQs() {
|
||||||
for(std::vector<ecmcDAQChannel*>::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) {
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
||||||
if(*pDAQChannel) {
|
if(*pDAQArray) {
|
||||||
delete (*pDAQChannel);
|
delete (*pDAQArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int linkDataToDAQs() {
|
int linkDataToDAQs() {
|
||||||
for(std::vector<ecmcDAQChannel*>::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) {
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
||||||
if(*pDAQChannel) {
|
if(*pDAQArray) {
|
||||||
try {
|
try {
|
||||||
(*pDAQChannel)->connectToDataSources();
|
(*pDAQArray)->connectToDataSources();
|
||||||
}
|
}
|
||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||||
@@ -73,22 +99,22 @@ int linkDataToDAQs() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int enableDAQ(int scopeIndex, int enable) {
|
//int enableDAQ(int scopeIndex, int enable) {
|
||||||
try {
|
// try {
|
||||||
scopes.at(scopeIndex)->setEnable(enable);
|
// arrays.at(scopeIndex)->setEnable(enable);
|
||||||
}
|
// }
|
||||||
catch(std::exception& e) {
|
// catch(std::exception& e) {
|
||||||
printf("Exception: %s. DAQ index out of range.\n",e.what());
|
// printf("Exception: %s. DAQ index out of range.\n",e.what());
|
||||||
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
// return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
||||||
}
|
// }
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
//}
|
||||||
|
|
||||||
int executeDAQCs() {
|
int executeDAQs() {
|
||||||
try {
|
try {
|
||||||
for(std::vector<ecmcDAQChannel*>::iterator pDAQChannel = scopes.begin(); pDAQChannel != scopes.end(); ++pDAQChannel) {
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
||||||
if(*pDAQChannel) {
|
if(*pDAQArray) {
|
||||||
(*pDAQChannel)->execute();
|
(*pDAQArray)->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,52 +125,122 @@ int executeDAQCs() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EPICS iocsh shell command: ecmcAddDataType1ToChannel
|
* EPICS iocsh shell command: ecmcAddDAQArray
|
||||||
*/
|
*/
|
||||||
void ecmcAddDataType1ToChannelPrintHelp() {
|
void ecmcAddDAQArrayHelp() {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" Use ecmcAddDataType1ToChannel(<ch_name>, <axis_index>)\n");
|
printf(" Use ecmcAddDAQArray(<name>,<asyn_port_name>)\n");
|
||||||
printf(" <ch_name> : Name of channel to add data to.\n");
|
printf(" <name> : Name of DAQ array object.\n");
|
||||||
printf(" <Axis id> : Axis index to add.\n");
|
printf(" <asyn_port_name> : Asyn port name.\n");
|
||||||
printf(" <velo limit> : Axis standstill velo limit [unit of axis].\n");
|
|
||||||
printf(" <time> : Time for axis to be below velo limit [ms].\n");
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ecmcAddAxisToSafetyGroup(const char* name, int axis_id, double velo_lim, int stand_still_time) {
|
int ecmcAddDAQArray(const char* name,const char* portname) {
|
||||||
if(!name) {
|
if(!name) {
|
||||||
ecmcAddAxisToSafetyGroupPrintHelp();
|
ecmcAddDAQArrayHelp();
|
||||||
|
return asynError;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!portname) {
|
||||||
|
ecmcAddDAQArrayHelp();
|
||||||
return asynError;
|
return asynError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(name,"-h") == 0 || strcmp(name,"--help") == 0 ) {
|
if(strcmp(name,"-h") == 0 || strcmp(name,"--help") == 0 ) {
|
||||||
ecmcAddAxisToSafetyGroupPrintHelp();
|
ecmcAddDAQArrayHelp();
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(axis_id <= 0) {
|
|
||||||
printf("Error: Invalid axis id.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(velo_lim < 0) {
|
|
||||||
printf("Error: Invalid velocity limit.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(stand_still_time < 0) {
|
|
||||||
printf("Error: Invalid stand still filter time.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
return addAxisToSafetyGroup(name,axis_id, velo_lim, stand_still_time);
|
return createDAQArray(name,portname);
|
||||||
}
|
}
|
||||||
catch(std::exception& e) {
|
catch(std::exception& e) {
|
||||||
printf("Exception: %s. Add axis to safety group failed.\n",e.what());
|
printf("Exception: %s. Create DAQ array failed.\n",e.what());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const iocshArg initArg0_0 =
|
||||||
|
{ "Array name", iocshArgString };
|
||||||
|
|
||||||
|
static const iocshArg initArg1_0 =
|
||||||
|
{ "Asyn port name", iocshArgString };
|
||||||
|
|
||||||
|
static const iocshArg *const initArgs_0[] = { &initArg0_0,
|
||||||
|
&initArg1_0};
|
||||||
|
|
||||||
|
|
||||||
|
static const iocshFuncDef initFuncDef_0 = { "ecmcAddDAQArray", 2, initArgs_0};
|
||||||
|
static void initCallFunc_0(const iocshArgBuf *args) {
|
||||||
|
ecmcAddDAQArray(args[0].sval, args[1].sval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPICS iocsh shell command: ecmcAddDAQChannel
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ecmcAddDAQChannelHelp() {
|
||||||
|
printf("\n");
|
||||||
|
printf(" Use ecmcAddDAQChannel(<type>)\n");
|
||||||
|
printf(" <type> : Type identifier if channel (int).\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecmcAddDAQChannel(int type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return createDAQChannel(type);
|
||||||
|
}
|
||||||
|
catch(std::exception& e) {
|
||||||
|
ecmcAddDAQChannelHelp();
|
||||||
|
printf("Exception: %s. Create DAQ channel failed.\n",e.what());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const iocshArg initArg0_1 =
|
||||||
|
{ "Type", iocshArgInt };
|
||||||
|
|
||||||
|
static const iocshArg *const initArgs_1[] = { &initArg0_1};
|
||||||
|
|
||||||
|
static const iocshFuncDef initFuncDef_1 = { "ecmcAddDAQChannel", 1, initArgs_1};
|
||||||
|
static void initCallFunc_1(const iocshArgBuf *args) {
|
||||||
|
ecmcAddDAQChannel(args[0].ival);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EPICS iocsh shell command: ecmcAddDAQItem
|
||||||
|
*/
|
||||||
|
void ecmcAddDAQItemHelp() {
|
||||||
|
printf("\n");
|
||||||
|
printf(" Use ecmcAddDAQItem(<dataitem_name>, <format>)\n");
|
||||||
|
printf(" <dataitem_name> : Data item name ex: 'ec0.s11.analogInput01' .\n");
|
||||||
|
printf(" <format> : Optional format conversion of data:.\n");
|
||||||
|
printf(" 0 = raw : Take raw value (do not apply special format)\n");
|
||||||
|
printf(" 1 = time_micro_s : Time: Recalc 64bit nano seconds to 32 bit micro second counter\n");
|
||||||
|
printf(" 2 = time_micro_s_minus_period : Time: Recalc 64bit nano seconds to 32 bit micro second counter minus one ec-period.\n");
|
||||||
|
printf(" Useful for oversampling slaves where normally the nextsync time is available.\n");
|
||||||
|
printf(" The calculated time then would correspond to the first data in the array recived.\n");
|
||||||
|
printf(" 3 = time_ns_minus_period : Time: Raw value minus one period.\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecmcAddDAQItem(const char* name, int format) {
|
||||||
|
if(strcmp(name,"-h") == 0 || strcmp(name,"--help") == 0 ) {
|
||||||
|
ecmcAddDAQItemHelp();
|
||||||
|
return asynSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return createDAQItem(name,format);
|
||||||
|
}
|
||||||
|
catch(std::exception& e) {
|
||||||
|
printf("Exception: %s. Create DAQ item failed.\n",e.what());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,33 +248,24 @@ int ecmcAddAxisToSafetyGroup(const char* name, int axis_id, double velo_lim, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const iocshArg initArg0_2 =
|
static const iocshArg initArg0_2 =
|
||||||
{ "Group name", iocshArgString };
|
{ "Data item name/path", iocshArgString };
|
||||||
|
|
||||||
static const iocshArg initArg1_2 =
|
static const iocshArg initArg1_2 =
|
||||||
{ "Axis id []", iocshArgInt };
|
{ "Type", iocshArgInt };
|
||||||
static const iocshArg initArg2_2 =
|
|
||||||
{ "Velo limit [unit same as axis cfg]", iocshArgDouble };
|
|
||||||
static const iocshArg initArg3_2 =
|
|
||||||
{ "Velo stand still filter time [ms]", iocshArgInt };
|
|
||||||
|
|
||||||
static const iocshArg *const initArgs_2[] = { &initArg0_2,
|
static const iocshArg *const initArgs_2[] = { &initArg0_2,
|
||||||
&initArg1_2,
|
&initArg1_2};
|
||||||
&initArg2_2,
|
|
||||||
&initArg3_2};
|
|
||||||
|
|
||||||
static const iocshFuncDef initFuncDef_2 = { "ecmcAddAxisToSafetyGroup", 4, initArgs_2};
|
static const iocshFuncDef initFuncDef_2 = { "ecmcAddDAQItem", 2, initArgs_2};
|
||||||
static void initCallFunc_2(const iocshArgBuf *args) {
|
static void initCallFunc_2(const iocshArgBuf *args) {
|
||||||
ecmcAddAxisToSafetyGroup(args[0].sval, args[1].ival, args[2].dval, args[3].ival);
|
ecmcAddDAQItem(args[0].sval,args[1].ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ecmcSafetyPlgRegister(void) {
|
// Register
|
||||||
|
void ecmcDAQPlgRegister(void) {
|
||||||
|
iocshRegister(&initFuncDef_0, initCallFunc_0);
|
||||||
iocshRegister(&initFuncDef_1, initCallFunc_1);
|
iocshRegister(&initFuncDef_1, initCallFunc_1);
|
||||||
iocshRegister(&initFuncDef_2, initCallFunc_2);
|
iocshRegister(&initFuncDef_2, initCallFunc_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
epicsExportRegistrar(ecmcSafetyPlgRegister);
|
epicsExportRegistrar(ecmcDAQPlgRegister);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* ecmc is distributed subject to a Software License Agreement found
|
* ecmc is distributed subject to a Software License Agreement found
|
||||||
* in file LICENSE that is included with this distribution.
|
* in file LICENSE that is included with this distribution.
|
||||||
*
|
*
|
||||||
* ecmcScopeWrap.h
|
* ecmcDAQWrap.h
|
||||||
*
|
*
|
||||||
* Created on: Sept 21, 2020
|
* Created on: Sept 21, 2020
|
||||||
* Author: anderssandstrom
|
* Author: anderssandstrom
|
||||||
@@ -11,39 +11,30 @@
|
|||||||
\*************************************************************************/
|
\*************************************************************************/
|
||||||
#ifndef ECMC_SCOPE_WRAP_H_
|
#ifndef ECMC_SCOPE_WRAP_H_
|
||||||
#define ECMC_SCOPE_WRAP_H_
|
#define ECMC_SCOPE_WRAP_H_
|
||||||
#include "ecmcScopeDefs.h"
|
#include "ecmcDAQDefs.h"
|
||||||
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
# endif // ifdef __cplusplus
|
# endif // ifdef __cplusplus
|
||||||
|
|
||||||
int createScope(char *configStr);
|
int executeDAQs();
|
||||||
|
|
||||||
int enableScope(int scopeIndex, int enable);
|
|
||||||
|
|
||||||
//int clearScope(int scopeIndex);
|
|
||||||
|
|
||||||
int triggScope(int scopeIndex);
|
|
||||||
|
|
||||||
|
|
||||||
int executeScopes();
|
|
||||||
|
|
||||||
/** \brief Link data to _all_ scope objects
|
/** \brief Link data to _all_ scope objects
|
||||||
*
|
*
|
||||||
* This tells the Scope lib to connect to ecmc to find it's data source.\n
|
* This tells the DAQ lib to connect to ecmc to find it's data source.\n
|
||||||
* This function should be called just before entering realtime since then all\n
|
* This function should be called just before entering realtime since then all\n
|
||||||
* data sources in ecmc will be definded (plc sources are compiled just before runtime\n
|
* data sources in ecmc will be definded (plc sources are compiled just before runtime\n
|
||||||
* so are only fist accesible now).\n
|
* so are only fist accesible now).\n
|
||||||
* \return 0 if success or otherwise an error code.\n
|
* \return 0 if success or otherwise an error code.\n
|
||||||
*/
|
*/
|
||||||
int linkDataToScopes();
|
int linkDataToDAQs();
|
||||||
|
|
||||||
/** \brief Deletes all created scope objects\n
|
/** \brief Deletes all created scope objects\n
|
||||||
*
|
*
|
||||||
* Should be called when destructs.\n
|
* Should be called when destructs.\n
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void deleteAllScopes();
|
void deleteAllDAQs();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ extern "C" {
|
|||||||
static int lastEcmcError = 0;
|
static int lastEcmcError = 0;
|
||||||
static char* lastConfStr = NULL;
|
static char* lastConfStr = NULL;
|
||||||
|
|
||||||
|
static int alreadyLoaded = 0;
|
||||||
|
|
||||||
/** Optional.
|
/** Optional.
|
||||||
* Will be called once after successfull load into ecmc.
|
* Will be called once after successfull load into ecmc.
|
||||||
* Return value other than 0 will be considered error.
|
* Return value other than 0 will be considered error.
|
||||||
@@ -36,11 +38,14 @@ static char* lastConfStr = NULL;
|
|||||||
**/
|
**/
|
||||||
int daqConstruct(char *configStr)
|
int daqConstruct(char *configStr)
|
||||||
{
|
{
|
||||||
//This module is allowed to load several times so no need to check if loaded
|
if(alreadyLoaded) {
|
||||||
|
printf("Error: Plugin ecmc_plugin_daq already loaded and can only be loaded once.")
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// create FFT object and register data callback
|
// create FFT object and register data callback
|
||||||
lastConfStr = strdup(configStr);
|
lastConfStr = strdup(configStr);
|
||||||
return 0; //createDAQ(configStr);
|
return 0 //createDAQ(configStr); //create from iocsh commands instead
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Optional function.
|
/** Optional function.
|
||||||
|
|||||||
Reference in New Issue
Block a user