From c1b77425611125f5d39f49ea5c9b4fae8a7a6c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Fri, 1 Mar 2024 20:18:52 +0100 Subject: [PATCH] WIP --- src/ecmcDAQChannel.cpp | 1002 -------------------------------- src/ecmcDAQChannel.h | 117 ---- src/ecmcDAQDataArray.cpp | 63 ++ src/ecmcDAQDataArray.h | 70 +++ src/ecmcDAQDataTypeBase.cpp | 290 --------- src/ecmcDAQDataTypeBase.h | 57 -- src/ecmcDAQDataTypeGeneric.cpp | 116 ---- src/ecmcDAQDataTypeGeneric.h | 47 -- 8 files changed, 133 insertions(+), 1629 deletions(-) delete mode 100644 src/ecmcDAQChannel.cpp delete mode 100644 src/ecmcDAQChannel.h create mode 100644 src/ecmcDAQDataArray.cpp create mode 100644 src/ecmcDAQDataArray.h delete mode 100644 src/ecmcDAQDataTypeBase.cpp delete mode 100644 src/ecmcDAQDataTypeBase.h delete mode 100644 src/ecmcDAQDataTypeGeneric.cpp delete mode 100644 src/ecmcDAQDataTypeGeneric.h diff --git a/src/ecmcDAQChannel.cpp b/src/ecmcDAQChannel.cpp deleted file mode 100644 index a20bc29..0000000 --- a/src/ecmcDAQChannel.cpp +++ /dev/null @@ -1,1002 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2019 European Spallation Source ERIC -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQChannel.cpp -* -* Created on: Sept 22, 2020 -* Author: anderssandstrom -* Credits to https://github.com/sgreg/dynamic-loading -* -\*************************************************************************/ - -// 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_RESULTDATA "resultdata" -#define ECMC_PLUGIN_ASYN_SCOPE_SOURCE "source" -#define ECMC_PLUGIN_ASYN_SCOPE_TRIGG "trigg" -#define ECMC_PLUGIN_ASYN_SCOPE_NEXT_SYNC "nexttime" -#define ECMC_PLUGIN_ASYN_MISSED "missed" -#define ECMC_PLUGIN_ASYN_TRIGG_COUNT "count" -#define ECMC_PLUGIN_ASYN_SCAN_TO_TRIGG_OFFSET "scantotrigg" - - -#define SCOPE_DBG_PRINT(str) \ -if(cfgDbgMode_) { \ - printf(str); \ -} \ - -#define ECMC_MAX_32BIT 0xFFFFFFFF - -#include -#include "ecmcDAQChannel.h" -#include "ecmcPluginClient.h" -#include - -/** ecmc Scope class - * This object can throw: - * - bad_alloc - * - invalid_argument - * - runtime_error -*/ -ecmcDAQChannel::ecmcDAQChannel(int scopeIndex, // index of this object (if several is created) - char* configStr){ - SCOPE_DBG_PRINT("ecmcDAQChannel::ecmcDAQChannel()"); - cfgDataSourceStr_ = NULL; - cfgDataNexttimeStr_ = NULL; - cfgTriggStr_ = NULL; - resultDataBuffer_ = NULL; - lastScanSourceDataBuffer_ = NULL; - missedTriggs_ = 0; - triggerCounter_ = 0; - objectId_ = scopeIndex; - triggOnce_ = 0; - dataSourceLinked_ = 0; - resultDataBufferBytes_ = 0; - bytesInResultBuffer_ = 0; - oldTriggTime_ = 0; - triggTime_ = 0; - sourceNexttime_ = 0; - sourceSampleRateNS_ = 0; - sourceElementsPerSample_ = 0; - firstTrigg_ = 1; // Avoid first trigger (0 timestamp..) - scopeState_ = ECMC_SCOPE_STATE_INVALID; - ecmcSmapleTimeNS_ = (uint64_t)getEcmcSampleTimeMS()*1E6; - samplesSinceLastTrigg_ = 0; - - // Asyn - sourceStrParam_ = NULL; - sourceNexttimeStrParam_ = NULL; - triggStrParam_ = NULL; - enbaleParam_ = NULL; - resultParam_ = NULL; - asynMissedTriggs_ = NULL; - asynTriggerCounter_ = NULL; - asynTimeTrigg2Sample_ = NULL; - - // ecmcDataItems - sourceDataItem_ = NULL; - sourceDataNexttimeItem_ = NULL; - sourceTriggItem_ = NULL; - - sourceDataItemInfo_ = NULL; - sourceDataNexttimeItemInfo_ = NULL; - sourceTriggItemInfo_ = NULL; - - // Config defaults - cfgDbgMode_ = 0; - cfgBufferElementCount_ = ECMC_PLUGIN_DEFAULT_BUFFER_SIZE; - cfgEnable_ = 1; // start enabled (enable over asyn) - - parseConfigStr(configStr); // Assigns all configs - - // Check valid buffer size - if(cfgBufferElementCount_ <= 0) { - SCOPE_DBG_PRINT("ERROR: Configuration buffer size must be > 0."); - throw std::out_of_range("ERROR: Configuration Buffer Size must be > 0."); - } - - // Allocate buffers first at enter RT (since datatype is unknown here) - resultDataBuffer_ = NULL; - resultDataBufferBytes_ = 0; -} - -ecmcDAQChannel::~ecmcDAQChannel() { - - if(resultDataBuffer_) { - delete[] resultDataBuffer_; - } - - if(lastScanSourceDataBuffer_) { - delete[] lastScanSourceDataBuffer_; - } - - if(cfgDataSourceStr_) { - free(cfgDataSourceStr_); - } - if(cfgTriggStr_) { - free(cfgTriggStr_); - } - if(cfgDataNexttimeStr_) { - free(cfgDataNexttimeStr_); - } - -} - -void ecmcDAQChannel::parseConfigStr(char *configStr) { - SCOPE_DBG_PRINT("ecmcDAQChannel::parseConfigStr()"); - // check config parameters - if (configStr && configStr[0]) { - char *pOptions = strdup(configStr); - char *pThisOption = pOptions; - char *pNextOption = pOptions; - - while (pNextOption && pNextOption[0]) { - pNextOption = strchr(pNextOption, ';'); - if (pNextOption) { - *pNextOption = '\0'; /* Terminate */ - pNextOption++; /* Jump to (possible) next */ - } - - // ECMC_PLUGIN_DBG_PRINT_OPTION_CMD (1/0) - if (!strncmp(pThisOption, ECMC_PLUGIN_DBG_PRINT_OPTION_CMD, strlen(ECMC_PLUGIN_DBG_PRINT_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_DBG_PRINT_OPTION_CMD); - cfgDbgMode_ = atoi(pThisOption); - } - - // ECMC_PLUGIN_SOURCE_OPTION_CMD (Source string) - else if (!strncmp(pThisOption, ECMC_PLUGIN_SOURCE_OPTION_CMD, strlen(ECMC_PLUGIN_SOURCE_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_SOURCE_OPTION_CMD); - cfgDataSourceStr_=strdup(pThisOption); - } - - // ECMC_PLUGIN_RESULT_ELEMENTS_OPTION_CMD (1/0) - else if (!strncmp(pThisOption, ECMC_PLUGIN_RESULT_ELEMENTS_OPTION_CMD, strlen(ECMC_PLUGIN_RESULT_ELEMENTS_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_RESULT_ELEMENTS_OPTION_CMD); - cfgBufferElementCount_ = atoi(pThisOption); - } - - // ECMC_PLUGIN_ENABLE_OPTION_CMD (1/0) - else if (!strncmp(pThisOption, ECMC_PLUGIN_ENABLE_OPTION_CMD, strlen(ECMC_PLUGIN_ENABLE_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_ENABLE_OPTION_CMD); - cfgEnable_ = atoi(pThisOption); - } - - // ECMC_PLUGIN_TRIGG_OPTION_CMD (string) - else if (!strncmp(pThisOption, ECMC_PLUGIN_TRIGG_OPTION_CMD, strlen(ECMC_PLUGIN_TRIGG_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_TRIGG_OPTION_CMD); - cfgTriggStr_ = strdup(pThisOption); - } - - // ECMC_PLUGIN_SOURCE_NEXTTIME_OPTION_CMD (string) - else if (!strncmp(pThisOption, ECMC_PLUGIN_SOURCE_NEXTTIME_OPTION_CMD, strlen(ECMC_PLUGIN_SOURCE_NEXTTIME_OPTION_CMD))) { - pThisOption += strlen(ECMC_PLUGIN_SOURCE_NEXTTIME_OPTION_CMD); - cfgDataNexttimeStr_ = strdup(pThisOption); - } - - - // ECMC_PLUGIN_MODE_OPTION_CMD CONT/TRIGG - // else if (!strncmp(pThisOption, ECMC_PLUGIN_MODE_OPTION_CMD, strlen(ECMC_PLUGIN_MODE_OPTION_CMD))) { - // pThisOption += strlen(ECMC_PLUGIN_MODE_OPTION_CMD); - // if(!strncmp(pThisOption, ECMC_PLUGIN_MODE_CONT_OPTION,strlen(ECMC_PLUGIN_MODE_CONT_OPTION))){ - // cfgMode_ = CONT; - // } - // if(!strncmp(pThisOption, ECMC_PLUGIN_MODE_TRIGG_OPTION,strlen(ECMC_PLUGIN_MODE_TRIGG_OPTION))){ - // cfgMode_ = TRIGG; - // } - // } - - pThisOption = pNextOption; - } - free(pOptions); - } - - // Data source must be defined... - if(!cfgDataSourceStr_) { - SCOPE_DBG_PRINT("ERROR: Configuration Data source not defined.\n"); - throw std::invalid_argument( "ERROR: Data source not defined."); - } - if(!cfgTriggStr_) { - SCOPE_DBG_PRINT("ERROR: Configuration Trigger not defined.\n"); - throw std::invalid_argument( "ERROR: Configuration Trigger not defined."); - } - if(!cfgDataNexttimeStr_) { - SCOPE_DBG_PRINT("ERROR: Configuration Nexttime not defined.\n"); - throw std::invalid_argument( "ERROR: Configuration Nexttime not defined."); - } -} - -void ecmcDAQChannel::connectToDataSources() { - SCOPE_DBG_PRINT("ecmcDAQChannel::connectToDataSources()"); - /* Check if already linked (one call to connectToDataSources (enterRT) per loaded Scope lib (Scope object)) - But link should only happen once!!*/ - if( dataSourceLinked_ ) { - return; - } - - // Get source dataItem - sourceDataItem_ = (ecmcDataItem*) getEcmcDataItem(cfgDataSourceStr_); - if(!sourceDataItem_) { - SCOPE_DBG_PRINT("ERROR: Source dataitem NULL.\n"); - throw std::runtime_error( "ERROR: Source dataitem NULL." ); - } - sourceDataItemInfo_ = sourceDataItem_->getDataItemInfo(); - - if(!sourceDataItemInfo_) { - SCOPE_DBG_PRINT("ERROR: Source dataitem info NULL.\n"); - throw std::runtime_error( "ERROR: Source dataitem info NULL." ); - } - - // Allocate buffer for result - resultDataBuffer_ = new uint8_t[cfgBufferElementCount_ * sourceDataItemInfo_->dataElementSize]; - memset(&resultDataBuffer_[0],0,cfgBufferElementCount_ * sourceDataItemInfo_->dataElementSize); - resultDataBufferBytes_ = cfgBufferElementCount_ * sourceDataItemInfo_->dataElementSize; - // Data for last scan cycle - lastScanSourceDataBuffer_ = new uint8_t[sourceDataItemInfo_->dataSize]; - memset(&lastScanSourceDataBuffer_[0],0,sourceDataItemInfo_->dataSize); - sourceElementsPerSample_ = sourceDataItemInfo_->dataSize / sourceDataItemInfo_->dataElementSize; - sourceSampleRateNS_ = ecmcSmapleTimeNS_ / sourceElementsPerSample_; - - // Get source nexttime dataItem - sourceDataNexttimeItem_ = (ecmcDataItem*) getEcmcDataItem(cfgDataNexttimeStr_); - if(!sourceDataNexttimeItem_) { - SCOPE_DBG_PRINT("ERROR: Source nexttime dataitem NULL.\n"); - throw std::runtime_error( "ERROR: Source nexttime dataitem NULL." ); - } - sourceDataNexttimeItemInfo_ = sourceDataNexttimeItem_->getDataItemInfo(); - - if(!sourceDataNexttimeItemInfo_) { - SCOPE_DBG_PRINT("ERROR: Source nexttime dataitem info NULL.\n"); - throw std::runtime_error( "ERROR: Source nexttime dataitem info NULL." ); - } - - // Get trigg dataItem - sourceTriggItem_ = (ecmcDataItem*) getEcmcDataItem(cfgTriggStr_); - if(!sourceTriggItem_) { - SCOPE_DBG_PRINT("ERROR: Trigg dataitem NULL.\n"); - throw std::runtime_error( "ERROR: Trigg dataitem NULL." ); - } - - sourceTriggItemInfo_ = sourceTriggItem_->getDataItemInfo(); - if(!sourceTriggItemInfo_) { - SCOPE_DBG_PRINT("ERROR: Trigg dataitem info NULL.\n"); - throw std::runtime_error( "ERROR: Trigg dataitem info NULL." ); - } - - if( sourceTriggItem_->read((uint8_t*)(&oldTriggTime_),sourceTriggItemInfo_->dataElementSize)){ - SCOPE_DBG_PRINT("ERROR: Failed read trigg time.\n"); - throw std::runtime_error( "ERROR: Failed read trigg time." ); - } - - if(!sourceDataTypeSupported(sourceDataItem_->getEcmcDataType())) { - SCOPE_DBG_PRINT("ERROR: Source data type not suppported.\n"); - throw std::runtime_error( "ERROR: Source data type not suppported."); - } - - // Register asyn parameters - initAsyn(); - - dataSourceLinked_ = 1; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; -} - -bool ecmcDAQChannel::sourceDataTypeSupported(ecmcEcDataType dt) { - - SCOPE_DBG_PRINT("ecmcDAQChannel::sourceDataTypeSupported()"); - - switch(dt) { - case ECMC_EC_NONE: - return 0; - break; - case ECMC_EC_B1: - return 0; - break; - case ECMC_EC_B2: - return 0; - break; - case ECMC_EC_B3: - return 0; - break; - case ECMC_EC_B4: - return 0; - break; - default: - return 1; - break; - } - return 1; -} - -/** - * Note: The code needs to handle triggers in the current and the past ethercat scan. - * If the trigger is newer than "NEXT_TIME" then the dc clocks must be out of sync (see readme) - * The analog samples from the prev cycles is always buffered to be able to also handle older timestamps (up to 2*NELM back in time) -*/ -void ecmcDAQChannel::execute() { - - size_t bytesToCp = 0; - - // Ensure ethercat bus is started - if(getEcmcEpicsIOCState() < 15) { - bytesInResultBuffer_ = 0; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - // Wait for new trigg - setWaitForNextTrigg(); - return; - } - - // Read trigg data - if( sourceTriggItem_->read((uint8_t*)&triggTime_,sourceTriggItemInfo_->dataElementSize)){ - SCOPE_DBG_PRINT("ERROR: Failed read trigg time.\n"); - throw std::runtime_error( "ERROR: Failed read trigg time." ); - } - - // Read next sync timestamp - if( sourceDataNexttimeItem_->read((uint8_t*)&sourceNexttime_,sourceDataNexttimeItemInfo_->dataElementSize)){ - SCOPE_DBG_PRINT("ERROR: Failed read ai nexttime.\n"); - throw std::runtime_error( "ERROR: Failed read nexttime." ); - } - - // Ensure enabled - if(!cfgEnable_) { - bytesInResultBuffer_ = 0; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - // Wait for new trigg - setWaitForNextTrigg(); - return; - } - - switch(scopeState_) { - case ECMC_SCOPE_STATE_INVALID: - SCOPE_DBG_PRINT("ERROR: Invalid state (state = ECMC_SCOPE_STATE_INVALID)."); - SCOPE_DBG_PRINT("INFO: Change state to ECMC_SCOPE_STATE_WAIT_TRIGG.\n"); - bytesInResultBuffer_ = 0; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - // Wait for new trigg - setWaitForNextTrigg(); - return; - break; - - case ECMC_SCOPE_STATE_WAIT_TRIGG: - - // New trigger then collect data (or wait ) - if(oldTriggTime_ != triggTime_ && !firstTrigg_) { - //printf("sourceNexttime_=%" PRIu64 " ,sourceDataNexttimeItemInfo_->dataSize = %zu\n",sourceNexttime_,sourceDataNexttimeItemInfo_->dataSize); - - // calculate how many samples ago trigger occured - samplesSinceLastTrigg_ = timeDiff() / sourceSampleRateNS_; - asynTimeTrigg2Sample_->refreshParam(1); - - if( samplesSinceLastTrigg_ > sourceElementsPerSample_ * 2 || samplesSinceLastTrigg_ < 0) { - SCOPE_DBG_PRINT("WARNING: Invalid trigger (occured more than two ethercat cycles ago or in future).."); - missedTriggs_++; - asynMissedTriggs_->refreshParam(1); - // Wait for new trigg (skip this trigger) - setWaitForNextTrigg(); - return; - } - - // printf("samplesSinceLastTrigg_=%lf\n",samplesSinceLastTrigg_); - - SCOPE_DBG_PRINT("INFO: New trigger detected.\n"); - - // Copy from last scan buffer if needed (if trigger occured during last scan) - if(samplesSinceLastTrigg_ > sourceElementsPerSample_) { - bytesToCp = (samplesSinceLastTrigg_ - sourceElementsPerSample_) * sourceDataItemInfo_->dataElementSize; - if(resultDataBufferBytes_ < bytesToCp) { - bytesToCp = resultDataBufferBytes_; - } - size_t startByte = (sourceElementsPerSample_*2-samplesSinceLastTrigg_) * sourceDataItemInfo_->dataElementSize; - - - memcpy( &resultDataBuffer_[0], &lastScanSourceDataBuffer_[startByte], bytesToCp); - bytesInResultBuffer_ = bytesToCp; - } - - // Copy from current scan if needed - if(bytesInResultBuffer_ < resultDataBufferBytes_) { - bytesToCp = sourceDataItemInfo_->dataSize; - // Ensure not to much data is copied - if(bytesToCp > (resultDataBufferBytes_ - bytesInResultBuffer_)) { - bytesToCp = resultDataBufferBytes_ - bytesInResultBuffer_; - } - - // Write directtly into results buffer - if( sourceDataItem_->read((uint8_t*)&resultDataBuffer_[bytesInResultBuffer_],bytesToCp)){ - SCOPE_DBG_PRINT("ERROR: Failed read data source.\n"); - throw std::runtime_error( "ERROR: Failed read data source." ); - } - bytesInResultBuffer_ += bytesToCp; - } - - // If more data is needed the go to collect state. - if(bytesInResultBuffer_ < resultDataBufferBytes_) { - // Fill more data from next scan - scopeState_ = ECMC_SCOPE_STATE_COLLECT; - } - else { // The data from current scan was enough. send over asyn and then start over (wait for next trigger) - resultParam_->refreshParam(1); - bytesInResultBuffer_ = 0; - - triggerCounter_++; - asynTriggerCounter_->refreshParam(1); - - SCOPE_DBG_PRINT("INFO: Result Buffer full. Data push over asyn..\n"); - - if(cfgDbgMode_) { - printEcDataArray(resultDataBuffer_,resultDataBufferBytes_,sourceDataItemInfo_->dataType,objectId_); - } - } - } - - // Avoid first rubbish trigger timestamp (when first value is read from bus it will differ from "0" and therefor trigger) - if(oldTriggTime_ != triggTime_) { - firstTrigg_ = 0; - } - - // This trigg is handled. Wait for next trigger - setWaitForNextTrigg(); - - break; - - case ECMC_SCOPE_STATE_COLLECT: - - if (oldTriggTime_ != triggTime_) { - SCOPE_DBG_PRINT("WARNING: Latch during sampling of data. This trigger will be disregarded.\n"); - setWaitForNextTrigg(); - missedTriggs_++; - asynMissedTriggs_->refreshParam(1); - } - - // Ensure not to much data is copied - if(bytesInResultBuffer_ < resultDataBufferBytes_) { - bytesToCp = sourceDataItemInfo_->dataSize; - if(bytesToCp > (resultDataBufferBytes_ - bytesInResultBuffer_)) { - bytesToCp = resultDataBufferBytes_ - bytesInResultBuffer_; - } - - // Write directtly into results buffer - if( sourceDataItem_->read((uint8_t*)&resultDataBuffer_[bytesInResultBuffer_],bytesToCp)){ - SCOPE_DBG_PRINT("ERROR: Failed read data source..\n"); - throw std::runtime_error( "ERROR: Failed read data source." ); - } - bytesInResultBuffer_ += bytesToCp; - } - - if(bytesInResultBuffer_ >= resultDataBufferBytes_) { - resultParam_->refreshParam(1); - bytesInResultBuffer_ = 0; - triggerCounter_++; - asynTriggerCounter_->refreshParam(1); - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - // Wait for next trigger. - setWaitForNextTrigg(); - SCOPE_DBG_PRINT("INFO: Change state to ECMC_SCOPE_STATE_WAIT_TRIGG.\n"); - SCOPE_DBG_PRINT("INFO: Result Buffer full. Data push over asyn..\n"); - if(cfgDbgMode_) { - printEcDataArray(resultDataBuffer_,resultDataBufferBytes_,sourceDataItemInfo_->dataType,objectId_); - } - } - - // Wait for next trigger. - setWaitForNextTrigg(); - - break; - default: - SCOPE_DBG_PRINT("ERROR: Invalid state (state = default)."); - bytesInResultBuffer_ = 0; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - // Wait for new trigg - setWaitForNextTrigg(); - return; - - return; - break; - } - - // Read source data to last scan buffer (only one "old" scan seems to be needed) - if( sourceDataItem_->read((uint8_t*)&lastScanSourceDataBuffer_[0],sourceDataItemInfo_->dataSize)){ - SCOPE_DBG_PRINT("ERROR: Failed read data source..\n"); - throw std::runtime_error( "ERROR: Failed source data." ); - } - -} - -/** Calculate depending on bits (32 or 64 bit dc) - * If one is 32 bit then only compare lower 32 bits - * sourceDataNexttimeItemInfo_ is always considered to happen in the future (after trigg) - * If 32 bit registers then it can max be 2^32 ns between trigg and nexttime (approx 4s). -*/ -int64_t ecmcDAQChannel::timeDiff() { - // retrun time from trigg to next - int64_t retVal = 0; - if(sourceTriggItemInfo_->dataBitCount < 64 || sourceDataNexttimeItemInfo_->dataBitCount < 64) { - // use only 32bit dc info - uint32_t trigg = getUint32((uint8_t*)&triggTime_); - uint32_t next = getUint32((uint8_t*)&sourceNexttime_); - - // Overflow... always report shortest timediff - if (std::abs( ((int64_t)next)-((int64_t)trigg)) > (int64_t)(ECMC_MAX_32BIT / 2)) { - if(next > trigg) { - retVal = -(((int64_t)trigg) + ECMC_MAX_32BIT - ((int64_t)next)); - //if(std::abs(retVal)>ECMC_MAX_32BIT/2) printf("Overflow 1! %" PRId64 "\n", retVal); - } - else { - retVal = ((int64_t)next) + ECMC_MAX_32BIT - ((int64_t)trigg); - //if(std::abs(retVal)>ECMC_MAX_32BIT/2) printf("Overflow 2! %" PRId64 "\n", retVal); - } - } - else { - retVal = ((int64_t)next)-((int64_t)trigg); - //if(std::abs(retVal)>ECMC_MAX_32BIT/2) printf("timediff 3! %" PRId64 "\n", retVal); - } - } - else { - // Both are 64 bit dc timestamps - retVal = sourceNexttime_ - triggTime_; - //if(std::abs(retVal)>ECMC_MAX_32BIT/2) printf("timediff 4! %" PRId64 "\n", retVal); - } - - return retVal; -} - -void ecmcDAQChannel::printEcDataArray(uint8_t* data, - size_t size, - ecmcEcDataType dt, - int objId) { - printf("INFO: Scope id: %d, data: ",objId); - - size_t dataElementSize = getEcDataTypeByteSize(dt); - - uint8_t *pData = data; - for(unsigned int i = 0; i < size / dataElementSize; ++i) { - if(i % 10 == 0) { - printf("\n"); - } else { - printf(", "); - } - switch(dt) { - case ECMC_EC_U8: - printf("%hhu",getUint8(pData)); - break; - case ECMC_EC_S8: - printf("%hhd",getInt8(pData)); - break; - case ECMC_EC_U16: - printf("%hu",getUint16(pData)); - break; - case ECMC_EC_S16: - printf("%hd",getInt16(pData)); - break; - case ECMC_EC_U32: - printf("%u",getUint32(pData)); - break; - case ECMC_EC_S32: - printf("%d",getInt32(pData)); - break; - case ECMC_EC_U64: - printf("%" PRIu64 "",getInt64(pData)); - break; - case ECMC_EC_S64: - printf("%" PRId64 "",getInt64(pData)); - break; - case ECMC_EC_F32: - printf("%f",getFloat32(pData)); - break; - case ECMC_EC_F64: - printf("%lf",getFloat64(pData)); - break; - default: - break; - } - - pData += dataElementSize; - } - printf("\n"); -} - -uint8_t ecmcDAQChannel::getUint8(uint8_t* data) { - return *data; -} - -int8_t ecmcDAQChannel::getInt8(uint8_t* data) { - int8_t* p=(int8_t*)data; - return *p; -} - -uint16_t ecmcDAQChannel::getUint16(uint8_t* data) { - uint16_t* p=(uint16_t*)data; - return *p; -} - -int16_t ecmcDAQChannel::getInt16(uint8_t* data) { - int16_t* p=(int16_t*)data; - return *p; -} - -uint32_t ecmcDAQChannel::getUint32(uint8_t* data) { - uint32_t* p=(uint32_t*)data; - return *p; -} - -int32_t ecmcDAQChannel::getInt32(uint8_t* data) { - int32_t* p=(int32_t*)data; - return *p; -} - -uint64_t ecmcDAQChannel::getUint64(uint8_t* data) { - uint64_t* p=(uint64_t*)data; - return *p; -} - -int64_t ecmcDAQChannel::getInt64(uint8_t* data) { - int64_t* p=(int64_t*)data; - return *p; -} - -float ecmcDAQChannel::getFloat32(uint8_t* data) { - float* p=(float*)data; - return *p; -} - -double ecmcDAQChannel::getFloat64(uint8_t* data) { - double* p=(double*)data; - return *p; -} - -size_t ecmcDAQChannel::getEcDataTypeByteSize(ecmcEcDataType dt){ - switch(dt) { - case ECMC_EC_NONE: - return 0; - break; - - case ECMC_EC_B1: - return 1; - break; - - case ECMC_EC_B2: - return 1; - break; - - case ECMC_EC_B3: - return 1; - break; - - case ECMC_EC_B4: - return 1; - break; - - case ECMC_EC_U8: - return 1; - break; - - case ECMC_EC_S8: - return 1; - break; - - case ECMC_EC_U16: - return 2; - break; - - case ECMC_EC_S16: - return 2; - break; - - case ECMC_EC_U32: - return 4; - break; - - case ECMC_EC_S32: - return 4; - break; - - case ECMC_EC_U64: - return 8; - break; - - case ECMC_EC_S64: - return 8; - break; - - case ECMC_EC_F32: - return 4; - break; - - case ECMC_EC_F64: - return 8; - break; - - default: - return 0; - break; - } - - return 0; -} - -void ecmcDAQChannel::initAsyn() { - - ecmcAsynPortDriver *ecmcAsynPort = (ecmcAsynPortDriver *)getEcmcAsynPortDriver(); - if(!ecmcAsynPort) { - SCOPE_DBG_PRINT("ERROR: ecmcAsynPort NULL."); - throw std::runtime_error( "ERROR: ecmcAsynPort NULL." ); - } - - // Add resultdata "plugin.scope%d.resultdata" - std::string paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_RESULTDATA; - asynParamType asynType = getResultAsynDTFromEcDT(sourceDataItemInfo_->dataType); - - if(asynType == asynParamNotDefined) { - SCOPE_DBG_PRINT("ERROR: ecmc data type not supported for param."); - throw std::runtime_error( "ERROR: ecmc data type not supported for param: " + paramName); - } - - resultParam_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynType, // asyn type - resultDataBuffer_, // pointer to data - resultDataBufferBytes_,// size of data - sourceDataItemInfo_->dataType, // ecmc data type - 0); // die if fail - - if(!resultParam_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for result."); - throw std::runtime_error( "ERROR: Failed create asyn param for result: " + paramName); - } - - resultParam_->setAllowWriteToEcmc(false); // read only - resultParam_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add enable "plugin.scope%d.enable" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_ENABLE; - - enbaleParam_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t*)&cfgEnable_, // pointer to data - sizeof(cfgEnable_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - - if(!enbaleParam_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for enable."); - throw std::runtime_error( "ERROR: Failed create asyn param for enable: " + paramName); - } - - enbaleParam_->setAllowWriteToEcmc(true); - enbaleParam_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add missed triggers "plugin.scope%d.missed" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_MISSED; - - asynMissedTriggs_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t*)&missedTriggs_, // pointer to data - sizeof(missedTriggs_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - - if(!asynMissedTriggs_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for missed trigg counter."); - throw std::runtime_error( "ERROR: Failed create asyn param for missed trigg counter: " + paramName); - } - - asynMissedTriggs_->setAllowWriteToEcmc(false); - asynMissedTriggs_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add trigger counter "plugin.scope%d.count" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_TRIGG_COUNT; - - asynTriggerCounter_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt32, // asyn type - (uint8_t*)&triggerCounter_, // pointer to data - sizeof(triggerCounter_), // size of data - ECMC_EC_S32, // ecmc data type - 0); // die if fail - - if(!asynTriggerCounter_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for trigg counter."); - throw std::runtime_error( "ERROR: Failed create asyn param for trigg counter: " + paramName); - } - - asynTriggerCounter_->setAllowWriteToEcmc(false); - asynTriggerCounter_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add trigger counter "plugin.scope%d.scantotrigg" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_SCAN_TO_TRIGG_OFFSET; - - asynTimeTrigg2Sample_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamFloat64, // asyn type - (uint8_t*)&samplesSinceLastTrigg_, // pointer to data - sizeof(samplesSinceLastTrigg_), // size of data - ECMC_EC_S64, // ecmc data type - 0); // die if fail - - if(!asynTimeTrigg2Sample_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for time trigg to sample."); - throw std::runtime_error( "ERROR: Failed create asyn param for time trigg to sample: " + paramName); - } - - asynTimeTrigg2Sample_->addSupportedAsynType(asynParamFloat64); - asynTimeTrigg2Sample_->setAllowWriteToEcmc(false); - asynTimeTrigg2Sample_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add enable "plugin.scope%d.source" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_SCOPE_SOURCE; - - sourceStrParam_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt8Array, // asyn type - (uint8_t*)cfgDataSourceStr_,// pointer to data - strlen(cfgDataSourceStr_), // size of data - ECMC_EC_U8, // ecmc data type - 0); // die if fail - - if(!sourceStrParam_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for data source."); - throw std::runtime_error( "ERROR: Failed create asyn param for data source: " + paramName); - } - - sourceStrParam_->setAllowWriteToEcmc(false); // read only - sourceStrParam_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add enable "plugin.scope%d.trigg" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_SCOPE_TRIGG; - - triggStrParam_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt8Array, // asyn type - (uint8_t*)cfgTriggStr_,// pointer to data - strlen(cfgTriggStr_), // size of data - ECMC_EC_U8, // ecmc data type - 0); // die if fail - - if(!triggStrParam_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for trigger."); - throw std::runtime_error( "ERROR: Failed create asyn param for trigger: " + paramName); - } - - triggStrParam_->setAllowWriteToEcmc(false); // read only - triggStrParam_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - - // Add enable "plugin.scope%d.nexttime" - paramName = ECMC_PLUGIN_ASYN_PREFIX + to_string(objectId_) + - "." + ECMC_PLUGIN_ASYN_SCOPE_NEXT_SYNC; - - sourceNexttimeStrParam_ = ecmcAsynPort->addNewAvailParam( - paramName.c_str(), // name - asynParamInt8Array, // asyn type - (uint8_t*)cfgDataNexttimeStr_,// pointer to data - strlen(cfgDataNexttimeStr_), // size of data - ECMC_EC_U8, // ecmc data type - 0); // die if fail - - if(!sourceNexttimeStrParam_) { - SCOPE_DBG_PRINT("ERROR: Failed create asyn param for nexttime."); - throw std::runtime_error( "ERROR: Failed create asyn param for nexttime: " + paramName); - } - - sourceNexttimeStrParam_->setAllowWriteToEcmc(false); // read only - sourceNexttimeStrParam_->refreshParam(1); // read once into asyn param lib - ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); - -} - -asynParamType ecmcDAQChannel::getResultAsynDTFromEcDT(ecmcEcDataType ecDT) { - -/*typedef enum { - asynParamNotDefined, - asynParamInt32, - asynParamUInt32Digital, - asynParamFloat64, - asynParamOctet, - asynParamInt8Array, - asynParamInt16Array, - asynParamInt32Array, - asynParamFloat32Array, - asynParamFloat64Array, - asynParamGenericPointer -} asynParamType;*/ - - switch(ecDT) { - case ECMC_EC_NONE: - return asynParamNotDefined; - break; - case ECMC_EC_B1 : - return asynParamNotDefined; - break; - case ECMC_EC_B2 : - return asynParamNotDefined; - break; - case ECMC_EC_B3 : - return asynParamNotDefined; - break; - case ECMC_EC_B4 : - return asynParamNotDefined; - break; - case ECMC_EC_U8 : - return asynParamInt8Array; - break; - case ECMC_EC_S8 : - return asynParamInt8Array; - break; - case ECMC_EC_U16: - return asynParamInt16Array; - break; - case ECMC_EC_S16: - return asynParamInt16Array; - break; - case ECMC_EC_U32: - return asynParamInt32Array; - break; - case ECMC_EC_S32: - return asynParamInt32Array; - break; - case ECMC_EC_U64: - return asynParamNotDefined; - break; - case ECMC_EC_S64: - return asynParamNotDefined; - break; - case ECMC_EC_F32: - return asynParamFloat32Array; - break; - case ECMC_EC_F64: - return asynParamFloat64Array; - break; - default: - return asynParamNotDefined; - break; - } - return asynParamNotDefined; -} - -// Avoid issues with std:to_string() -std::string ecmcDAQChannel::to_string(int value) { - std::ostringstream os; - os << value; - return os.str(); -} - -void ecmcDAQChannel::setEnable(int enable) { - if(enable) { - SCOPE_DBG_PRINT("INFO: Scope enabled.\n"); - } - else { - SCOPE_DBG_PRINT("INFO: Scope disabled.\n"); - } - - cfgEnable_ = enable; - enbaleParam_->refreshParam(1); -} - -void ecmcDAQChannel::triggScope() { - triggOnce_ = 1; -} - -void ecmcDAQChannel::setWaitForNextTrigg() { - oldTriggTime_ = triggTime_; -} - - diff --git a/src/ecmcDAQChannel.h b/src/ecmcDAQChannel.h deleted file mode 100644 index 5fb0e39..0000000 --- a/src/ecmcDAQChannel.h +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2019 European Spallation Source ERIC -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQChannel.h -* -* Created on: Mar 22, 2020 -* Author: anderssandstrom -* -\*************************************************************************/ -#ifndef ECMC_SCOPE_H_ -#define ECMC_SCOPE_H_ - -#include -#include "ecmcDataItem.h" -#include "ecmcAsynPortDriver.h" -#include "ecmcDAQDefs.h" -#include "inttypes.h" -#include - -class ecmcDAQChannel { - public: - - /** ecmc Scope class - * This object can throw: - * - bad_alloc - * - invalid_argument - * - runtime_error - * - out_of_range - */ - ecmcDAQChannel(int index, char* name); - ~ecmcDAQChannel(); - - void connectToDataSources(); - void setEnable(int enable); - void execute(); - - private: - void parseConfigStr(char *configStr); - void addDataToBuffer(double data); - bool sourceDataTypeSupported(ecmcEcDataType dt); - void initAsyn(); - int64_t timeDiff(); - asynParamType getResultAsynDTFromEcDT(ecmcEcDataType ecDT); - void setWaitForNextTrigg(); - - - - uint8_t* resultDataBuffer_; - uint8_t* lastScanSourceDataBuffer_; - size_t resultDataBufferBytes_; - size_t bytesInResultBuffer_; - ecmcDataItem *sourceDataItem_; - ecmcDataItemInfo *sourceDataItemInfo_; - ecmcDataItem *sourceDataNexttimeItem_; - ecmcDataItemInfo *sourceDataNexttimeItemInfo_; - ecmcDataItem *sourceTriggItem_; - ecmcDataItemInfo *sourceTriggItemInfo_; - - int dataSourceLinked_; // To avoid link several times - int objectId_; // Unique object id - int triggOnce_; - int firstTrigg_; - - uint64_t triggTime_; - uint64_t oldTriggTime_; - uint64_t sourceNexttime_; - int64_t sourceSampleRateNS_; // nanoseconds - ecmcDAQChannelState scopeState_; - uint64_t ecmcSmapleTimeNS_; - int64_t sourceElementsPerSample_; - size_t elementsInResultBuffer_; - double samplesSinceLastTrigg_; - - // Config options - char* cfgDataSourceStr_; // Config: data source string - char* cfgDataNexttimeStr_; // Config: data source string - char* cfgTriggStr_; // Config: trigg string - int cfgDbgMode_; // Config: allow dbg printouts - size_t cfgBufferElementCount_; // Config: Data set size - int cfgEnable_; // Config: Enable data acq./calc. - - int missedTriggs_; - int triggerCounter_; - - // Asyn - ecmcAsynDataItem *sourceStrParam_; - ecmcAsynDataItem *triggStrParam_; - ecmcAsynDataItem *enbaleParam_; - ecmcAsynDataItem *resultParam_; - ecmcAsynDataItem *sourceNexttimeStrParam_; - ecmcAsynDataItem *asynMissedTriggs_; - ecmcAsynDataItem *asynTriggerCounter_; - ecmcAsynDataItem *asynTimeTrigg2Sample_; - - - // Some generic utility functions - static uint8_t getUint8(uint8_t* data); - static int8_t getInt8(uint8_t* data); - static uint16_t getUint16(uint8_t* data); - static int16_t getInt16(uint8_t* data); - static uint32_t getUint32(uint8_t* data); - static int32_t getInt32(uint8_t* data); - static uint64_t getUint64(uint8_t* data); - static int64_t getInt64(uint8_t* data); - static float getFloat32(uint8_t* data); - static double getFloat64(uint8_t* data); - static size_t getEcDataTypeByteSize(ecmcEcDataType dt); - static void printEcDataArray(uint8_t* data, - size_t size, - ecmcEcDataType dt, - int objId); - static std::string to_string(int value); -}; - -#endif /* ECMC_SCOPE_H_ */ diff --git a/src/ecmcDAQDataArray.cpp b/src/ecmcDAQDataArray.cpp new file mode 100644 index 0000000..4d4dee6 --- /dev/null +++ b/src/ecmcDAQDataArray.cpp @@ -0,0 +1,63 @@ +7/*************************************************************************\ +* Copyright (c) 2024 PSI +* ecmc is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +* +* ecmcDAQDataArray.cpp +* +* Created on: March 1, 2024 +* Author: anders sandstrom +* Credits to https://github.com/sgreg/dynamic-loading +* +\*************************************************************************/ + +// Needed to get headers in ecmc right... +#define ECMC_IS_PLUGIN + +#include +#include "ecmcDAQDataArray.h" +#include "ecmcPluginClient.h" + +ecmcDAQDataArray::ecmcDAQDataArray(size_t nelm){ + buffer_ = new double [nelm]; + nelm_ = nelm; + channelCounter_ = 0; +} + +ecmcDAQDataArray::~ecmcDAQDataArray() { + +} + +void ecmcDAQDataArray::addDataItem(char* name, int timeFormat) { + dataChannels_.push_back(new ecmcDataChannel(name, timeFormat); + channelCounter_++; +} + +void ecmcDAQDataArray::connectToDataSources() { + if( dataSourceLinked_ ) { + return; + } + + for(std::vector::iterator pDataCh = dataChannels_.begin(); pDataCh != dataChannels_.end(); ++pDataCh) { + if(!(*pDataCh)) { + throw std::runtime_error( "Channel empty.."); + } + (*pDataCh)->connectToSource(); + } + + // Register asyn parameters + initAsyn(); + + dataSourceLinked_ = 1; +} + +void ecmcDAQDataArray::buildHeader(){ + // Each Data channel takes 4 doubles +} + +void ecmcDAQDataArray::execute() { + +} + + + diff --git a/src/ecmcDAQDataArray.h b/src/ecmcDAQDataArray.h new file mode 100644 index 0000000..4392921 --- /dev/null +++ b/src/ecmcDAQDataArray.h @@ -0,0 +1,70 @@ +/*************************************************************************\ +* Copyright (c) 2024 PSI +* ecmc is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +* +* ecmcDAQDataArray.h +* +* Created on: Mar 01, 2024 +* Author: anders sandstrom +* +\*************************************************************************/ +#ifndef ECMC_DAQ_DATA_ARRAY_H_ +#define ECMC_DAQ_DATA_ARRAY_H_ + +#include +#include +#include +#include "ecmcDAQDataArray.h" +#include "ecmcDataItem.h" + +/* Class to store data channels */ +class ecmcDataChannel { + public: + ecmcDataChannel(char* name, int formatAsTime) { + dataItem_ = NULL; + dataItemInfo_ = NULL; + name_ = name; + timeFormat_ = formatAsTime; + } + + void connectToSource() { + // Get data item for + 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 to fromat an array of ecmcDataChannels with headers and push over asyn to epics */ +class ecmcDAQDataArray { + public: + ecmcDAQDataArray(size_t nelm); + ~ecmcDAQDataArray(); + void connectToDataSources(); + void execute(); + void addDataItem(char* name, int timeFormat); + +private: + double *buffer_; + std::vector dataChannels_; + size_t channelCounter_; +}; + +#endif /* ECMC_DAQ_DATA_ARRAY_H_ */ + + + diff --git a/src/ecmcDAQDataTypeBase.cpp b/src/ecmcDAQDataTypeBase.cpp deleted file mode 100644 index bf76287..0000000 --- a/src/ecmcDAQDataTypeBase.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2024 PSI -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQDataTypeBase.cpp -* -* Created on: March 1, 2024 -* Author: anders sandstrom -* Credits to https://github.com/sgreg/dynamic-loading -* -\*************************************************************************/ - -// Needed to get headers in ecmc right... -#define ECMC_IS_PLUGIN - -#include -#include "ecmcDAQDataTypeBase.h" -#include "ecmcPluginClient.h" - -ecmcDAQDataTypeBase::ecmcDAQDataTypeBase(int type, char* name){ - dataSourceLinked_ = 0; - name_ = name; - type_ = type; -} - -ecmcDAQDataTypeBase::~ecmcDAQDataTypeBase() { -} - -bool ecmcDAQDataTypeBase::getDataSourcesLinked() { - return dataSourceLinked_; -} - -char* ecmcDAQDataTypeBase::getName() { - return name_.c_str(); -} - -int ecmcDAQDataTypeBase::getType() { - return type_; -} - -void ecmcDAQDataTypeBase::printEcDataArray(uint8_t* data, - size_t size, - ecmcEcDataType dt, - int objId) { - printf("INFO: Scope id: %d, data: ",objId); - - size_t dataElementSize = getEcDataTypeByteSize(dt); - - uint8_t *pData = data; - for(unsigned int i = 0; i < size / dataElementSize; ++i) { - if(i % 10 == 0) { - printf("\n"); - } else { - printf(", "); - } - switch(dt) { - case ECMC_EC_U8: - printf("%hhu",getUint8(pData)); - break; - case ECMC_EC_S8: - printf("%hhd",getInt8(pData)); - break; - case ECMC_EC_U16: - printf("%hu",getUint16(pData)); - break; - case ECMC_EC_S16: - printf("%hd",getInt16(pData)); - break; - case ECMC_EC_U32: - printf("%u",getUint32(pData)); - break; - case ECMC_EC_S32: - printf("%d",getInt32(pData)); - break; - case ECMC_EC_U64: - printf("%" PRIu64 "",getInt64(pData)); - break; - case ECMC_EC_S64: - printf("%" PRId64 "",getInt64(pData)); - break; - case ECMC_EC_F32: - printf("%f",getFloat32(pData)); - break; - case ECMC_EC_F64: - printf("%lf",getFloat64(pData)); - break; - default: - break; - } - - pData += dataElementSize; - } - printf("\n"); -} - -uint8_t ecmcDAQDataTypeBase::getUint8(uint8_t* data) { - return *data; -} - -int8_t ecmcDAQDataTypeBase::getInt8(uint8_t* data) { - int8_t* p=(int8_t*)data; - return *p; -} - -uint16_t ecmcDAQDataTypeBase::getUint16(uint8_t* data) { - uint16_t* p=(uint16_t*)data; - return *p; -} - -int16_t ecmcDAQDataTypeBase::getInt16(uint8_t* data) { - int16_t* p=(int16_t*)data; - return *p; -} - -uint32_t ecmcDAQDataTypeBase::getUint32(uint8_t* data) { - uint32_t* p=(uint32_t*)data; - return *p; -} - -int32_t ecmcDAQDataTypeBase::getInt32(uint8_t* data) { - int32_t* p=(int32_t*)data; - return *p; -} - -uint64_t ecmcDAQDataTypeBase::getUint64(uint8_t* data) { - uint64_t* p=(uint64_t*)data; - return *p; -} - -int64_t ecmcDAQDataTypeBase::getInt64(uint8_t* data) { - int64_t* p=(int64_t*)data; - return *p; -} - -float ecmcDAQDataTypeBase::getFloat32(uint8_t* data) { - float* p=(float*)data; - return *p; -} - -double ecmcDAQDataTypeBase::getFloat64(uint8_t* data) { - double* p=(double*)data; - return *p; -} - -size_t ecmcDAQDataTypeBase::getEcDataTypeByteSize(ecmcEcDataType dt){ - switch(dt) { - case ECMC_EC_NONE: - return 0; - break; - - case ECMC_EC_B1: - return 1; - break; - - case ECMC_EC_B2: - return 1; - break; - - case ECMC_EC_B3: - return 1; - break; - - case ECMC_EC_B4: - return 1; - break; - - case ECMC_EC_U8: - return 1; - break; - - case ECMC_EC_S8: - return 1; - break; - - case ECMC_EC_U16: - return 2; - break; - - case ECMC_EC_S16: - return 2; - break; - - case ECMC_EC_U32: - return 4; - break; - - case ECMC_EC_S32: - return 4; - break; - - case ECMC_EC_U64: - return 8; - break; - - case ECMC_EC_S64: - return 8; - break; - - case ECMC_EC_F32: - return 4; - break; - - case ECMC_EC_F64: - return 8; - break; - - default: - return 0; - break; - } - - return 0; -} - -asynParamType ecmcDAQDataTypeBase::getResultAsynDTFromEcDT(ecmcEcDataType ecDT) { - -/*typedef enum { - asynParamNotDefined, - asynParamInt32, - asynParamUInt32Digital, - asynParamFloat64, - asynParamOctet, - asynParamInt8Array, - asynParamInt16Array, - asynParamInt32Array, - asynParamFloat32Array, - asynParamFloat64Array, - asynParamGenericPointer -} asynParamType;*/ - - switch(ecDT) { - case ECMC_EC_NONE: - return asynParamNotDefined; - break; - case ECMC_EC_B1 : - return asynParamNotDefined; - break; - case ECMC_EC_B2 : - return asynParamNotDefined; - break; - case ECMC_EC_B3 : - return asynParamNotDefined; - break; - case ECMC_EC_B4 : - return asynParamNotDefined; - break; - case ECMC_EC_U8 : - return asynParamInt8Array; - break; - case ECMC_EC_S8 : - return asynParamInt8Array; - break; - case ECMC_EC_U16: - return asynParamInt16Array; - break; - case ECMC_EC_S16: - return asynParamInt16Array; - break; - case ECMC_EC_U32: - return asynParamInt32Array; - break; - case ECMC_EC_S32: - return asynParamInt32Array; - break; - case ECMC_EC_U64: - return asynParamNotDefined; - break; - case ECMC_EC_S64: - return asynParamNotDefined; - break; - case ECMC_EC_F32: - return asynParamFloat32Array; - break; - case ECMC_EC_F64: - return asynParamFloat64Array; - break; - default: - return asynParamNotDefined; - break; - } - return asynParamNotDefined; -} - -// Avoid issues with std:to_string() -std::string ecmcDAQDataTypeBase::to_string(int value) { - std::ostringstream os; - os << value; - return os.str(); -} diff --git a/src/ecmcDAQDataTypeBase.h b/src/ecmcDAQDataTypeBase.h deleted file mode 100644 index a48ca10..0000000 --- a/src/ecmcDAQDataTypeBase.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2024 PSI -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQDataTypeBase.h -* -* Created on: Mar 01, 2024 -* Author: anders sandstrom -* -\*************************************************************************/ -#ifndef ECMC_DAQ_DATATYPE_BASE_H_ -#define ECMC_DAQ_DATATYPE_BASE_H_ - -#include -#include "ecmcDataItem.h" -#include - -class ecmcDAQDataTypeBase { - public: - - ecmcDAQDataTypeBase(int type, char* name); - ~ecmcDAQDataTypeBase(); - - virtual void connectToDataSources() = 0; - virtual void execute() = 0; - virtual size_t getDataElementCount() = 0; - virtual double* getDataPtr() = 0; - bool getDataSourcesLinked(); - char* getName(); - int getType(); - - protected: - bool dataSourceLinked_; - std::string name_; - int type_; - - // Some generic utility functions - static uint8_t getUint8(uint8_t* data); - static int8_t getInt8(uint8_t* data); - static uint16_t getUint16(uint8_t* data); - static int16_t getInt16(uint8_t* data); - static uint32_t getUint32(uint8_t* data); - static int32_t getInt32(uint8_t* data); - static uint64_t getUint64(uint8_t* data); - static int64_t getInt64(uint8_t* data); - static float getFloat32(uint8_t* data); - static double getFloat64(uint8_t* data); - static size_t getEcDataTypeByteSize(ecmcEcDataType dt); - static void printEcDataArray(uint8_t* data, - size_t size, - ecmcEcDataType dt, - int objId); - static std::string to_string(int value); -}; - -#endif /* ECMC_DAQ_DATATYPE_BASE_H_ */ diff --git a/src/ecmcDAQDataTypeGeneric.cpp b/src/ecmcDAQDataTypeGeneric.cpp deleted file mode 100644 index b0a15bc..0000000 --- a/src/ecmcDAQDataTypeGeneric.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2024 PSI -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQDataTypeGeneric.cpp -* -* Created on: March 1, 2024 -* Author: anders sandstrom -* Credits to https://github.com/sgreg/dynamic-loading -* -\*************************************************************************/ - -// Needed to get headers in ecmc right... -#define ECMC_IS_PLUGIN - -#include -#include "ecmcDAQDataTypeGeneric.h" -#include "ecmcPluginClient.h" - -ecmcDAQDataTypeGeneric::ecmcDAQDataTypeGeneric(char *ecTimeRising,char *ecTimeFalling){ - - sEcTimeRising_ = ecTimeRising; - sEcTimeFalling_ = ecTimeFalling; - dataItemTimeRising_ = NULL; - dataItemInfoTimeRising_ = NULL; - dataItemTimeFalling_ = NULL; - dataItemInfoTimeFalling_ = NULL; - for(int i=0; i< ECMC_DAQ_DATA_TYPE_1_DATA_ELEMENTS, ++i) { - buffer_[i] = 0.0; - } -} - -ecmcDAQDataTypeGeneric::~ecmcDAQDataTypeGeneric() { - delete(dataItemTimeRising_); - delete(dataItemInfoTimeRising_); - delete(dataItemTimeFalling_); - delete(dataItemInfoTimeFalling_); -} - -void ecmcDAQDataTypeGeneric::connectToDataSources() { - if( dataSourceLinked_ ) { - return; - } - - // Get data item for - dataItemTimeRising_ = (ecmcDataItem*) getEcmcDataItem(sEcTimeRising_.c_str()); - - if(!dataItemTimeRising_) { - throw std::runtime_error( "ERROR: Dataitem for time rinsing edge NULL." ); - } - dataItemInfoTimeRising_ = dataItemTimeRising_->getDataItemInfo(); - - if(!dataItemInfoTimeRising_) { - throw std::runtime_error( "ERROR: Dataiteminfo for time rising edge NULL." ); - } - - // Get source nexttime dataItem - sourceDataNexttimeItem_ = (ecmcDataItem*) getEcmcDataItem(cfgDataNexttimeStr_); - if(!sourceDataNexttimeItem_) { - SCOPE_DBG_PRINT("ERROR: Source nexttime dataitem NULL.\n"); - throw std::runtime_error( "ERROR: Source nexttime dataitem NULL." ); - } - sourceDataNexttimeItemInfo_ = sourceDataNexttimeItem_->getDataItemInfo(); - - if(!sourceDataNexttimeItemInfo_) { - SCOPE_DBG_PRINT("ERROR: Source nexttime dataitem info NULL.\n"); - throw std::runtime_error( "ERROR: Source nexttime dataitem info NULL." ); - } - - // Get trigg dataItem - sourceTriggItem_ = (ecmcDataItem*) getEcmcDataItem(cfgTriggStr_); - if(!sourceTriggItem_) { - SCOPE_DBG_PRINT("ERROR: Trigg dataitem NULL.\n"); - throw std::runtime_error( "ERROR: Trigg dataitem NULL." ); - } - - sourceTriggItemInfo_ = sourceTriggItem_->getDataItemInfo(); - if(!sourceTriggItemInfo_) { - SCOPE_DBG_PRINT("ERROR: Trigg dataitem info NULL.\n"); - throw std::runtime_error( "ERROR: Trigg dataitem info NULL." ); - } - - if( sourceTriggItem_->read((uint8_t*)(&oldTriggTime_),sourceTriggItemInfo_->dataElementSize)){ - SCOPE_DBG_PRINT("ERROR: Failed read trigg time.\n"); - throw std::runtime_error( "ERROR: Failed read trigg time." ); - } - - if(!sourceDataTypeSupported(sourceDataItem_->getEcmcDataType())) { - SCOPE_DBG_PRINT("ERROR: Source data type not suppported.\n"); - throw std::runtime_error( "ERROR: Source data type not suppported."); - } - - // Register asyn parameters - initAsyn(); - - dataSourceLinked_ = 1; - scopeState_ = ECMC_SCOPE_STATE_WAIT_TRIGG; - -} - -void ecmcDAQDataTypeGeneric::execute() { - -} - -size_t ecmcDAQDataTypeGeneric::getDataElementCount() { - return ECMC_DAQ_DATA_TYPE_1_DATA_ELEMENTS; -} - -double* ecmcDAQDataTypeGeneric::getDataPtr() { - return &buffer[0]; -} - -double ecmcDAQDataTypeGeneric::getType() { - return ECMC_DAQ_DATA_TYPE_1_ID; -} diff --git a/src/ecmcDAQDataTypeGeneric.h b/src/ecmcDAQDataTypeGeneric.h deleted file mode 100644 index eeef7f5..0000000 --- a/src/ecmcDAQDataTypeGeneric.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2024 PSI -* ecmc is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -* -* ecmcDAQDataTypeGeneric.h -* -* Created on: Mar 01, 2024 -* Author: anders sandstrom -* -\*************************************************************************/ -#ifndef ECMC_DAQ_DATATYPE_1_H_ -#define ECMC_DAQ_DATATYPE_1_H_ - -#include -#include "ecmcDataItem.h" -#include -#include "ecmcDAQDataTypeBase.h" -#include "ecmcDataItem.h" -#include - -#define ECMC_DAQ_DATA_TYPE_1_DATA_ELEMENTS 2 -class ecmcDAQDataTypeGeneric : public ecmcDAQDataTypeBase { - public: - - ecmcDAQDataTypeGeneric(); - ~ecmcDAQDataTypeGeneric(); - void connectToDataSources(); - void execute(); - size_t getDataElementCount(); - double* getDataPtr(); - double getType(); - void addEcData(char* ec) - -private: - std::string sEcTimeRising_; - std::string sEcTimeFalling_; - - double *buffer_; - ecmcEc *ecMaster_; - static std::vector entries; -}; - -#endif /* ECMC_DAQ_DATATYPE_1_H_ */ - - - \ No newline at end of file