Files
ecmc_plugin_daq/src/ecmcDAQWrap.cpp
2024-03-04 11:22:34 +01:00

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);