WIP
This commit is contained in:
124
src/ecmcDAQChannelItem.h
Normal file
124
src/ecmcDAQChannelItem.h
Normal file
@@ -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 <stdexcept>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#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_ */
|
||||
|
||||
@@ -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<ecmcDAQDataChannel*>::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() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<ecmcDAQDataChannel*> dataChannels_;
|
||||
size_t channelCounter_;
|
||||
size_t dataElementCount_;
|
||||
size_t totalElementCount_;
|
||||
size_t firstDataElementIndex_;
|
||||
};
|
||||
|
||||
#endif /* ECMC_DAQ_DATA_ARRAY_H_ */
|
||||
|
||||
@@ -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<ecmcDAQChannelItem*>::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(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,38 +15,6 @@
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#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<ecmcDAQChannelItem*> dataItems_;
|
||||
size_t itemCounter_;
|
||||
double type_;
|
||||
size_t dataElementCount_;
|
||||
};
|
||||
|
||||
#endif /* ECMC_DAQ_DATA_CHANNEL_H_ */
|
||||
|
||||
Reference in New Issue
Block a user