/*************************************************************************\ * 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 #include #include #include "ecmcDAQWrap.h" #include "ecmcDAQDataArray.h" #include "ecmcDAQDefs.h" #include #include #define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.DAQ" #define ECMC_PLUGIN_DAQ_ERROR_CODE 1 static std::vector 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::iterator pDAQArray = arrays.begin(); pDAQArray != arrays.end(); ++pDAQArray) { if(*pDAQArray) { delete (*pDAQArray); } } } int linkDataToDAQs() { for(std::vector::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::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(,)\n"); printf(" : Name of DAQ array object.\n"); printf(" : 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()\n"); printf(" : 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(, )\n"); printf(" : Data item name ex: 'ec0.s11.analogInput01' .\n"); printf(" : 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);