From 42d2b54c83977f3daf9386f232f169abcb43701c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Sat, 2 Mar 2024 20:56:55 +0100 Subject: [PATCH] WIP --- src/ecmcDAQChannelItem.h | 124 +++++++++++++++++++++++++++++++++++++ src/ecmcDAQDataArray.cpp | 42 ++++++++++--- src/ecmcDAQDataArray.h | 7 ++- src/ecmcDAQDataChannel.cpp | 17 +++-- src/ecmcDAQDataChannel.h | 37 ++--------- 5 files changed, 180 insertions(+), 47 deletions(-) create mode 100644 src/ecmcDAQChannelItem.h diff --git a/src/ecmcDAQChannelItem.h b/src/ecmcDAQChannelItem.h new file mode 100644 index 0000000..b907a8d --- /dev/null +++ b/src/ecmcDAQChannelItem.h @@ -0,0 +1,124 @@ +/*************************************************************************\ +* Copyright (c) 2024 PSI +* ecmc is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +* +* ecmcDAQChannelItem.h +* +* Created on: Mar 01, 2024 +* Author: anders sandstrom +* +\*************************************************************************/ +#ifndef ECMC_DAQ_CHANNEL_ITEM_H_ +#define ECMC_DAQ_CHANNEL_ITEM_H_ + +#include +#include +#include +#include "ecmcDataItem.h" + +enum class ecmcDAQDataFormat { raw = 0, + time_micro_s = 1, + time_micro_s_minus_period = 2, + time_ns_minus_period = 3 + }; + +/* Class to store one data item +* name : ecmc parameter name, example ec0.s1.positionActual01, ax1.enc.posact, ... +* format : Format the data in these ways: +* 0=raw : Take raw value (do not apply special format) +* 1=time_micro_s : Time: Recalc 64bit nano seconds to 32 bit micro second counter +* 2=time_micro_s_minus_period : Time: Recalc 64bit nano seconds to 32 bit micro second counter minus one ec-period. +* Useful for oversampling slaves where normally the nextsync time is available. +* The calculated time then would correspond to the first data in the array recived. +* 3=time_ns_minus_period : Time: Raw value minus one period. +*/ + +class ecmcDAQChannelItem { + public: + ecmcDAQChannelItem(char* name, ecmcDAQDataFormat format) { + dataItem_ = NULL; + dataItemInfo_ = NULL; + name_ = name; + format_ = format; // micro s in int32 + sampleTimeCompensation_ = 0; + dataIndexToReturn_ = 0; + dataElementCount_ = 0; + } + + void connectToSource() { + // Get data item + dataItem_ = (ecmcDataItem*) getEcmcDataItem(name_.c_str()); + if(!dataItem_) { + printf("ERROR: DataItem %s NULL.\n", name_.c_str()); + throw std::runtime_error( "ERROR: DataItem NULL." ); + } + + dataItemInfo_ = dataItem_->getDataItemInfo(); + if(!dataItemInfo_) { + printf("ERROR: DataItemInfo %s NULL.\n", name_.c_str()); + throw std::runtime_error( "ERROR: DataItemInfo NULL." ); + } + + dataElementCount_ = dataItemInfo_->dataSize / dataItemInfo_->dataElementSize; + // Execute here to be sure that startup.cmd of ecmc(cfg) has been executed. + switch(format_) { + case ecmcDAQDataFormat.time_micro_s_minus_period: + sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000; + break; + case ecmcDAQDataFormat.time_ns_minus_period: + sampleTimeCompensation_ = getEcmcSampleTimeMS()*1000000; + break; + default: + sampleTimeCompensation_ = 0; + break; + } + } + + + /*struct ecmcDataItemInfo { + char *name; + uint8_t *data; + size_t dataSize; + size_t dataElementSize; + size_t dataBitCount; + ecmcEcDataType dataType; + ecmcDataDir dataDirection; + double dataUpdateRateMs; + int dataPointerValid; + };*/ + + /* Return data: + * if "first" is set to true the first data point will be returned. + * if "first" is set to false the the next data point will be returned. + * 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) { + if(first) { + dataIndexToReturn_ = 0; + } + + dataIndexToReturn_++; + } + + /* Retruns true if all data have been retruned with getData(). + */ + bool empty(){ + return dataIndexToReturn_ >= dataElementCount_; + } + + size_t getDataElementCount(){ + return dataElementCount_; + } + + ecmcDataItem* dataItem_; + ecmcDataItemInfo* dataItemInfo_; + std::string name_; + ecmcDAQDataFormat format_; + double sampleTimeCompensation_; + size_t dataIndexToReturn_; + size_t dataElementCount_; +}; +#endif /* ECMC_DAQ_CHANNEL_ITEM_H_ */ + diff --git a/src/ecmcDAQDataArray.cpp b/src/ecmcDAQDataArray.cpp index fe011a9..d732c10 100644 --- a/src/ecmcDAQDataArray.cpp +++ b/src/ecmcDAQDataArray.cpp @@ -19,32 +19,50 @@ #include "ecmcPluginClient.h" ecmcDAQDataArray::ecmcDAQDataArray(size_t nelm){ - buffer_ = new double [nelm]; - memset(buffer_,0,sizeof(buffer_)) - nelm_ = nelm; channelCounter_ = 0; + dataElementCount_= 0; + totalElementCount_ = 0; + firstDataElementIndex_ = 0; } ecmcDAQDataArray::~ecmcDAQDataArray() { } -void ecmcDAQDataArray::addDataItem(int type) { +void ecmcDAQDataArray::addChannel(int type) { dataChannels_.push_back(new ecmcDAQDataChannel(type); channelCounter_++; } +void ecmcDAQDataArray::addDataItemToChannel(char* name, int format) { + // Always add to last added channel + dataChannels_.back().addDataItem(name, format); +} + void ecmcDAQDataArray::connectToDataSources() { if( dataSourceLinked_ ) { return; } + dataElementCount_ = 0; + for(std::vector::iterator pDataCh = dataChannels_.begin(); pDataCh != dataChannels_.end(); ++pDataCh) { if(!(*pDataCh)) { throw std::runtime_error( "Channel empty.."); } (*pDataCh)->connectToSources(); + dataElementCount_ = dataElementCount_ + (*pDataCh)->getDataElementCount(); } + + // Header: First element is time stamp then 4 elements per channel + totalElementCount_ = dataElementCount_ + channelCounter_ * 4 + 1; + + // Now we we can finally allocate teh buffer (ecmc is still not in realtime, enterRT) + buffer_ = new double [totalElementCount_]; + memset(buffer_,0,sizeof(buffer_)) + + // Build header + buildArrayHeader(); // Register asyn parameters initAsyn(); @@ -53,7 +71,7 @@ void ecmcDAQDataArray::connectToDataSources() { } /* Prepare header first in array, 4 elements per channel: -* array[0] = Ec timestamp, updated each cycle +* array[0] = Ec timestamp, updated each cycle, the reset of header is static * Channel 1: * array[1] = Channel type * array[2] = Data start index @@ -67,8 +85,10 @@ void ecmcDAQDataArray::connectToDataSources() { *.... */ void ecmcDAQDataArray::buildArrayHeader(){ - // 4 elements plus first timestamp to first data element + // 4 elements plus first timestamp to first data element, only first element will change in realtime + size_t dataStartOffset = channelCounter_* 4 + 1; + firstDataElementIndex_ = dataStartOffset; if( nelm_ < 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).."); @@ -90,18 +110,22 @@ void ecmcDAQDataArray::buildArrayHeader(){ buffer_[index] = (double)dataStartOffset; index++; // Third element: Data element count (size) - buffer_[index] = (double)(*pDataCh)->getElementCount(); + buffer_[index] = (double)(*pDataCh)->getDataElementCount(); // Prepare data start index for next data item - dataStartOffset = dataStartOffset + (*pDataCh)->getElementCount(); + dataStartOffset = dataStartOffset + (*pDataCh)->getDataElementCount(); index++; // Forth index spare... - buffer_[index] = 0.0; + buffer_[index] = -1234567890; index++; } } void ecmcDAQDataArray::execute() { + +} +void ecmcDAQDataArray::initAsyn() { + } diff --git a/src/ecmcDAQDataArray.h b/src/ecmcDAQDataArray.h index ea6cf77..4245484 100644 --- a/src/ecmcDAQDataArray.h +++ b/src/ecmcDAQDataArray.h @@ -24,12 +24,17 @@ class ecmcDAQDataArray { ~ecmcDAQDataArray(); void connectToDataSources(); void execute(); - void addDataItem(char* name, int timeFormat); + void addChannel(int type); + // Always add to last added channel + void addDataItemToChannel(char* name, int format); private: double *buffer_; std::vector dataChannels_; size_t channelCounter_; + size_t dataElementCount_; + size_t totalElementCount_; + size_t firstDataElementIndex_; }; #endif /* ECMC_DAQ_DATA_ARRAY_H_ */ diff --git a/src/ecmcDAQDataChannel.cpp b/src/ecmcDAQDataChannel.cpp index fe59c1e..bd33d49 100644 --- a/src/ecmcDAQDataChannel.cpp +++ b/src/ecmcDAQDataChannel.cpp @@ -21,6 +21,7 @@ ecmcDAQDataChannel::ecmcDAQDataChannel(int type){ itemCounter_ = 0; type_ = (double) type; + dataElementCount_ = 0; } ecmcDAQDataChannel::~ecmcDAQDataChannel() { @@ -37,20 +38,28 @@ void ecmcDAQDataChannel::connectToDataSources() { return; } + dataElementCount_ = 0; + for(std::vector::iterator pDataItem = dataItems_.begin(); pDataItem != dataItems_.end(); ++pDataItem) { if(!(*pDataItem)) { throw std::runtime_error( "Channel empty.."); } (*pDataItem)->connectToSource(); + dataElementCount_ = dataElementCount_ + (*pDataItem)->getDataElementCount(); } - // Register asyn parameters - initAsyn(); - dataSourceLinked_ = 1; } -void ecmcDAQDataChannel::execute() { +size_t ecmcDAQDataChannel::getDataElementCount(){ + return dataElementCount_; +} + +double ecmcDAQDataChannel:getData(){ + +} + +bool ecmcDAQDataChannel:empty(){ } diff --git a/src/ecmcDAQDataChannel.h b/src/ecmcDAQDataChannel.h index cc429fc..50c11e5 100644 --- a/src/ecmcDAQDataChannel.h +++ b/src/ecmcDAQDataChannel.h @@ -15,38 +15,6 @@ #include #include #include -#include "ecmcDataItem.h" - -/* Class to store data channels */ -class ecmcDAQChannelItem { - public: - ecmcDAQChannelItem(char* name, int formatAsTime) { - dataItem_ = NULL; - dataItemInfo_ = NULL; - name_ = name; - timeFormat_ = formatAsTime; // micro s in int32 - } - - void connectToSource() { - // Get data item - dataItem_ = (ecmcDataItem*) getEcmcDataItem(name_.c_str()); - if(!dataItem_) { - printf("ERROR: DataItem %s NULL.\n", name_.c_str()); - throw std::runtime_error( "ERROR: DataItem NULL." ); - } - - dataItemInfo_ = dataItem_->getDataItemInfo(); - if(!dataItemInfo_) { - printf("ERROR: DataItemInfo %s NULL.\n", name_.c_str()); - throw std::runtime_error( "ERROR: DataItemInfo NULL." ); - } - } - - ecmcDataItem* dataItem_; - ecmcDataItemInfo* dataItemInfo_; - std::string name_; - int timeFormat_; -}; /* Class for an data channel */ class ecmcDAQDataChannel { @@ -54,13 +22,16 @@ class ecmcDAQDataChannel { ecmcDAQDataChannel(int type); ~ecmcDAQDataChannel(); void connectToSources(); - void execute(); void addDataItem(char* name, int timeFormat); + size_t getDataElementCount(); + double getData(); + bool empty(); private: std::vector dataItems_; size_t itemCounter_; double type_; + size_t dataElementCount_; }; #endif /* ECMC_DAQ_DATA_CHANNEL_H_ */