272 lines
7.2 KiB
C++
272 lines
7.2 KiB
C++
/*************************************************************************\
|
|
* 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.
|
|
*
|
|
* ecmcDAQWrap.cpp
|
|
*
|
|
* Created on: Sept 21, 2020
|
|
* Author: anderssandstrom
|
|
* Credits to https://github.com/sgreg/dynamic-loading
|
|
*
|
|
\*************************************************************************/
|
|
|
|
// Needed to get headers in ecmc right...
|
|
#define ECMC_IS_PLUGIN
|
|
|
|
#include <vector>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include "ecmcDAQWrap.h"
|
|
#include "ecmcDAQDataArray.h"
|
|
#include "ecmcDAQDefs.h"
|
|
#include <epicsExport.h>
|
|
#include <iocsh.h>
|
|
|
|
#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.DAQ"
|
|
#define ECMC_PLUGIN_DAQ_ERROR_CODE 1
|
|
|
|
static std::vector<ecmcDAQDataArray*> arrays;
|
|
static int arrayCounter = 0;
|
|
|
|
int createDAQArray(const char* name, const char* portName ) {
|
|
|
|
// create new ecmcFFT object
|
|
ecmcDAQDataArray* array = NULL;
|
|
|
|
try {
|
|
array = new ecmcDAQDataArray(name, portName);
|
|
}
|
|
catch(std::exception& e) {
|
|
if(array) {
|
|
delete array;
|
|
}
|
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
}
|
|
|
|
arrays.push_back(array);
|
|
arrayCounter++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int createDAQChannel(int type) {
|
|
|
|
try {
|
|
arrays.back()->addChannel(type);
|
|
}
|
|
catch(std::exception& e) {
|
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int createDAQItem(const char* name, int type) {
|
|
try {
|
|
arrays.back()->addDataItemToChannel(name,type);
|
|
}
|
|
catch(std::exception& e) {
|
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void deleteAllDAQs() {
|
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
|
if(*pDAQArray) {
|
|
delete (*pDAQArray);
|
|
}
|
|
}
|
|
}
|
|
|
|
int linkDataToDAQs() {
|
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
|
if(*pDAQArray) {
|
|
try {
|
|
(*pDAQArray)->connectToDataSources();
|
|
}
|
|
catch(std::exception& e) {
|
|
printf("Exception: %s. Plugin will unload.\n",e.what());
|
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//int enableDAQ(int scopeIndex, int enable) {
|
|
// try {
|
|
// arrays.at(scopeIndex)->setEnable(enable);
|
|
// }
|
|
// catch(std::exception& e) {
|
|
// printf("Exception: %s. DAQ index out of range.\n",e.what());
|
|
// return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
// }
|
|
// return 0;
|
|
//}
|
|
|
|
int executeDAQs() {
|
|
try {
|
|
for(std::vector<ecmcDAQDataArray*>::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) {
|
|
if(*pDAQArray) {
|
|
(*pDAQArray)->execute();
|
|
}
|
|
}
|
|
}
|
|
catch(std::exception& e) {
|
|
printf("Exception: %s.\n",e.what());
|
|
return ECMC_PLUGIN_DAQ_ERROR_CODE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* EPICS iocsh shell command: ecmcAddDAQArray
|
|
*/
|
|
void ecmcAddDAQArrayHelp() {
|
|
printf("\n");
|
|
printf(" Use ecmcAddDAQArray(<name>,<asyn_port_name>)\n");
|
|
printf(" <name> : Name of DAQ array object.\n");
|
|
printf(" <asyn_port_name> : Asyn port name.\n");
|
|
printf("\n");
|
|
}
|
|
|
|
int ecmcAddDAQArray(const char* name,const char* portname) {
|
|
if(!name) {
|
|
ecmcAddDAQArrayHelp();
|
|
return asynError;
|
|
}
|
|
|
|
if(!portname) {
|
|
ecmcAddDAQArrayHelp();
|
|
return asynError;
|
|
}
|
|
|
|
if(strcmp(name,"-h") == 0 || strcmp(name,"--help") == 0 ) {
|
|
ecmcAddDAQArrayHelp();
|
|
return asynSuccess;
|
|
}
|
|
|
|
try {
|
|
return createDAQArray(name,portname);
|
|
}
|
|
catch(std::exception& e) {
|
|
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);
|
|
}
|
|
|
|
return asynSuccess;
|
|
}
|
|
|
|
static const iocshArg initArg0_2 =
|
|
{ "Data item name/path", iocshArgString };
|
|
|
|
static const iocshArg initArg1_2 =
|
|
{ "Type", iocshArgInt };
|
|
|
|
static const iocshArg *const initArgs_2[] = { &initArg0_2,
|
|
&initArg1_2};
|
|
|
|
static const iocshFuncDef initFuncDef_2 = { "ecmcAddDAQItem", 2, initArgs_2};
|
|
static void initCallFunc_2(const iocshArgBuf *args) {
|
|
ecmcAddDAQItem(args[0].sval,args[1].ival);
|
|
}
|
|
|
|
// Register
|
|
void ecmcDAQPlgRegister(void) {
|
|
iocshRegister(&initFuncDef_0, initCallFunc_0);
|
|
iocshRegister(&initFuncDef_1, initCallFunc_1);
|
|
iocshRegister(&initFuncDef_2, initCallFunc_2);
|
|
}
|
|
|
|
epicsExportRegistrar(ecmcDAQPlgRegister);
|