From c5c1278bdedb397b43e1a3af9746a118255ae693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Thu, 2 Apr 2020 09:51:49 +0200 Subject: [PATCH] Start from new plugin --- .gitignore | 16 ++ Makefile | 28 ++ README.md | 259 ++++++++++++++++++ cmds/.keep | 0 configure/CONFIG | 11 + configure/CONFIG_MODULE | 37 +++ configure/CONFIG_OPTIONS | 6 + configure/RELEASE | 11 + configure/RULES | 12 + configure/module/RULES_DKMS_L | 38 +++ configure/module/RULES_MODULE | 20 ++ docs/.MODULE_LOG | 28 ++ docs/ecmcPlugin_Simple.conf | 4 + ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/.keep | 0 .../ecmcPlugin_FFTApp/src/.keep | 0 .../ecmcPlugin_FFTApp/src/ecmcAdvanced.cpp | 75 +++++ .../ecmcPlugin_FFTApp/src/ecmcAdvanced.h | 32 +++ .../ecmcPlugin_FFTApp/src/ecmcPluginExample.c | 225 +++++++++++++++ ecmcPlugin_FFT.Makefile | 63 +++++ iocsh/.keep | 0 opi/.keep | 0 patch/Site/HISTORY.md | 7 + patch/Site/README.md | 22 ++ template/.keep | 0 24 files changed, 894 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 cmds/.keep create mode 100644 configure/CONFIG create mode 100644 configure/CONFIG_MODULE create mode 100644 configure/CONFIG_OPTIONS create mode 100644 configure/RELEASE create mode 100644 configure/RULES create mode 100644 configure/module/RULES_DKMS_L create mode 100644 configure/module/RULES_MODULE create mode 100644 docs/.MODULE_LOG create mode 100644 docs/ecmcPlugin_Simple.conf create mode 100644 ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/.keep create mode 100644 ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/.keep create mode 100644 ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.cpp create mode 100644 ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.h create mode 100644 ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcPluginExample.c create mode 100644 ecmcPlugin_FFT.Makefile create mode 100644 iocsh/.keep create mode 100644 opi/.keep create mode 100644 patch/Site/HISTORY.md create mode 100644 patch/Site/README.md create mode 100644 template/.keep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62c86fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*~ +*-dev +modules.order +Module.symvers +Mkfile.old +core.* +#* +.#* +\#* +*.local +\#* +.cvsignore +*_old/ +*PVs.list +*-loc/*.Makefile +ecmcPlugin_Simple-loc/*.Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..48d516b --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +# +# Copyright (c) 2018 - 2019 European Spallation Source ERIC +# +# The program is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 2 of the +# License, or any newer version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see https://www.gnu.org/licenses/gpl-2.0.txt +# +# +# Author : Jeong Han Lee +# email : han.lee@esss.se +# Date : 2020Mar22-1607-33CET +# version : 1.0.0 + +TOP:=$(CURDIR) + +include $(TOP)/configure/CONFIG + +include $(TOP)/configure/RULES + diff --git a/README.md b/README.md new file mode 100644 index 0000000..3847782 --- /dev/null +++ b/README.md @@ -0,0 +1,259 @@ +e3-ecmcPlugin_Advanced +====== +ESS Site-specific EPICS module : ecmcPlugin_Advanced + +Example illustrating how to implement plugins for use with ecmc (https://github.com/icshwi/ecmc). + +Shows how to implement: +* callbacks +* custom ecmc plc-functions +* custom ecmc plc-constants +* access to ecmcAsynPort object to add plugin specific asyn parameter. + +# Interface +The interface is defined in the structure ecmcPluginData in ecmcPluginDefs.h: +``` +struct ecmcPluginData { + // Name + const char *name; + // Description + const char *desc; + // Plugin version + int version; + // ECMC_PLUG_VERSION_MAGIC + int ifVersion; + // Optional construct func, called once at load + int (*constructFnc)(void); + // Optional destruct func, called once at unload + void (*destructFnc)(void); + // Optional func that will be called once just before enter realtime mode + int (*realtimeEnterFnc)(void*); + // Optional func that will be called once just before exit realtime mode + int (*realtimeExitFnc)(void); + // Optional func that will be called each realtime cycle + int (*realtimeFnc)(int); + // Allow max ECMC_PLUGIN_MAX_PLC_FUNC_COUNT custom plc functions + struct ecmcOnePlcFunc funcs[ECMC_PLUGIN_MAX_PLC_FUNC_COUNT]; + // Allow max ECMC_PLUGIN_MAX_PLC_CONST_COUNT custom plc constants + struct ecmcOnePlcConst consts[ECMC_PLUGIN_MAX_PLC_CONST_COUNT]; +}; +``` +## Callbacks: +All callbacks are optional. If the callbacks are not used then set the func pointer to NULL +("ecmcPluginData.*Fnc=NULL"). + +Example: +``` +ecmcPluginData.destructFnc=NULL +ecmcPluginData.constructFnc=NULL +... +``` + +### int constructFnc(), optional +This callback is called once when the plugin is loaded into ecmc. This is a good place to put code for any initialization needed in the plugin module. + +Return value: 0 for success or error code. + +In this example plugin only a printout is made in this callback. + +### void destructFnc(), optional +This callback is called once when the plugin is unloaded. This is a good place to put cleanup code needed by the plugin module. + +In this example plugin only a printout is made in this callback. + +### int realtimeFnc(int ecmcErrorId), optional +This callback is called once in each realtime loop (sync to ecmc). This is a good place to put any cyclic processing needed by the plugin module. + +NOTE: This callback is executed by ecmc realtime thread. Take measures to stay as short time as possible in this function. If lots of processing is needed a separate worker thread might be a solution. + +Parameters: ecmcErrorId: reflects the current errorstate of ecmc. + +Return value: 0 for success or error code. + +In this example a counter value is increased for each call and the coresponding asyn parameter is updated. + +### int realtimeEnterFnc(void* ecmcRefs), optional +This callback is called once just before ecmc enters realtime mode (starts rt-thread). This is a good place to make any prepartions needed before cyclic processing starts. + +Parameters: ecmcRefs: ref to ecmcdata that can be cast to ecmcPluginDataRefs +``` +struct ecmcPluginDataRefs { + double sampleTimeMS; + ecmcAsynPortDriver *ecmcAsynPort; +}; +``` +Return value: 0 for success or error code. + +In this example a asyn parameter called "plugin.adv.counter" is registered. The ecmc realtime samplerate is also determined from the ecmcRefs + +### int realtimeExitFnc(), optional +This callback is called once just before ecmc exits realtime mode (exits rt-thread). + +Return value: 0 for success or error code. + +In this example plugin only a printout is made in this callback. + +### Example: +``` +// Compile data for lib so ecmc now what to use +struct ecmcPluginData pluginDataDef = { + // Name + .name = "ecmcExamplePlugin", + // Description + .desc = "Advanced example with use of asynport obj.", + // Plugin version + .version = ECMC_EXAMPLE_PLUGIN_VERSION, + // ECMC_PLUG_VERSION_MAGIC + .ifVersion = ECMC_PLUG_VERSION_MAGIC, + // Optional construct func, called once at load. NULL if not definded. + .constructFnc = adv_exampleConstruct, + // Optional destruct func, called once at unload. NULL if not definded. + .destructFnc = adv_exampleDestruct, + // Optional func that will be called each rt cycle. NULL if not definded. + .realtimeFnc = adv_exampleRealtime, + // Optional func that will be called once just before enter realtime mode + .realtimeEnterFnc = adv_exampleEnterRT, + // Optional func that will be called once just before exit realtime mode + .realtimeExitFnc = adv_exampleExitRT, +... +... + +``` +## PLC functions: +Custom ecmc PLC-functions can be implemented in plugins. Currentlly the interface supports implementation of up to 64 plc functions. Each plc function needs to be defined by the struct "ecmcOnePlcFunc": +``` +struct ecmcOnePlcFunc { + // Function name (this is the name you use in ecmc plc-code) + const char *funcName; + // Function description + const char *funcDesc; + /** + * 7 different prototypes allowed (only doubles since reg in plc). + * Only one funcArg func shall be assigned the rest set to NULL + **/ + double (*funcArg0)(); + double (*funcArg1)(double); + double (*funcArg2)(double,double); + double (*funcArg3)(double,double,double); + double (*funcArg4)(double,double,double,double); + double (*funcArg5)(double,double,double,double,double); + double (*funcArg6)(double,double,double,double,double,double); +}; + +``` +Example: +``` +.funcs[0] = + { /*----customPlcFunc1----*/ + // Function name (this is the name you use in ecmc plc-code) + .funcName = "adv_plugin_func_1", + // Function description + .funcDesc = "Multiply arg0 with arg1.", + /** + * 7 different prototypes allowed (only doubles since reg in plc). + * Only funcArg one func shall be assigned the rest set to NULL. + **/ + .funcArg0 = NULL, + .funcArg1 = NULL, + .funcArg2 = adv_customPlcFunc1, // Func 1 has 2 args + .funcArg3 = NULL, + .funcArg4 = NULL, + .funcArg5 = NULL, + .funcArg6 = NULL + }, +``` +Note: Only the first non NULL function will be used (starting from funcArg0...) + +## PLC constants +Custom ecmc PLC-constants can be implemented in plugins. Currentlly the interface supports implementation of up to 64 plc constants. Each plc constant needs to be defined by the struct "ecmcOnePlcConst": +``` +struct ecmcOnePlcConst{ + const char *constName; + const char *constDesc; + double constValue; +}; + +``` +Example: +``` +.consts[0] = { + .constName = "adv_CONST_1", + .constDesc = "Test constant \"adv_CONST_1\" = 1.234567890", + .constValue = 1.234567890, + }, +``` +## Dependencies: + +All needed headers are available in ecmc (https://github.com/icshwi/ecmc) +### Simple plugins + +Only the "ecmcPluginDefs.h" header is needed. + +### Advanced plugins +When using the "void* ecmcRefs" param (cast to ecmcPluginDataRefs)in the "realtimeEnterFnc()" these additional headers are needed: +* from ecmc: + * ecmcAsynPortDriver.h + * ecmcAsynDataItem.h + * ecmcAsynPortDriverUtils.h + * ecmcDefinitions.h + * ecmcErrorsList.h + * ecmcPluginDataRefs.h +* from asyn: + * asynPortDriver.h + +Note: This define is needed in the plugin sources: +``` +#define ECMC_IS_PLUGIN +``` +## Plugin info for ecmcPlugin_Advanced +``` + Plugin info: + Name = ecmcExamplePlugin + Description = Advanced example with use of asynport obj. + Version = 1 + Interface version = 512 (ecmc = 512) + max plc funcs = 64 + max plc consts = 64 + Construct func = @0x7fac4353d190 + Enter realtime func = @0x7fac4353d200 + Exit realtime func = @0x7fac4353d1c0 + Realtime func = @0x7fac4353d1e0 + Destruct func = @0x7fac4353d1b0 + dlhandle = @0x182e580 + Plc functions: + funcs[00]: + Name = "adv_plugin_func_1(arg0, arg1);" + Desc = Multiply arg0 with arg1. + Arg count = 2 + func = @0x7fac4353d170 + funcs[01]: + Name = "adv_plugin_func_2(arg0, arg1, arg2);" + Desc = Multiply arg0, arg1 and arg2. + Arg count = 3 + func = @0x7fac4353d180 + Plc constants: + consts[00]: + Name = "adv_CONST_1" = 1.235 + Desc = Test constant "adv_CONST_1" = 1.234567890 + consts[01]: + Name = "adv_CONST_2" = 9.877 + Desc = Test constant "adv_CONST_2" = 9.876543210 +``` + +## Access to asyn parameter (linked to record IOC_TEST:Plugin-Adv-Counter) +``` +camonitor IOC_TEST:Plugin-Adv-Counter +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:21.535547 23 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:21.630954 24 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:21.740799 25 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:21.838110 26 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:21.930354 27 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.034919 28 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.130358 29 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.234041 30 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.334133 31 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.434937 32 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.530212 33 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.634437 34 +IOC_TEST:Plugin-Adv-Counter 2020-03-26 15:45:22.734606 35 +``` diff --git a/cmds/.keep b/cmds/.keep new file mode 100644 index 0000000..e69de29 diff --git a/configure/CONFIG b/configure/CONFIG new file mode 100644 index 0000000..2286cf9 --- /dev/null +++ b/configure/CONFIG @@ -0,0 +1,11 @@ +# +VARS_EXCLUDES := $(.VARIABLES) + +include $(TOP)/configure/RELEASE +include $(TOP)/configure/CONFIG_MODULE + +E3_REQUIRE_LOCATION := $(EPICS_BASE)/$(E3_REQUIRE_NAME)/$(E3_REQUIRE_VERSION) +REQUIRE_CONFIG := $(E3_REQUIRE_LOCATION)/configure + +include $(REQUIRE_CONFIG)/CONFIG + diff --git a/configure/CONFIG_MODULE b/configure/CONFIG_MODULE new file mode 100644 index 0000000..704f557 --- /dev/null +++ b/configure/CONFIG_MODULE @@ -0,0 +1,37 @@ +# +EPICS_MODULE_NAME:=ecmcPlugin_FFT + +EPICS_MODULE_TAG:=master +# +E3_MODULE_VERSION:=master + +# DEPENDENT MODULE VERSION +# For Example, + +ECMC_DEP_VERSION:=master +ASYN_DEP_VERSION:=4.36.0 + +#DEVLIB2_DEP_VERSION:=2.9.0 +#PCRE_DEP_VERSION:=8.41.0 +#ADCORE_DEP_VERSION:=3.7.0 +#ADSUPPORT_DEP_VERSION:=1.9.0 +#LOKI_DEP_VERSION=1.0.0 +#NDS_DEP_VERSION=2.3.3 +#SIS8300DRV_DEP_VERSION=4.3.1 +#SEQUENCER_DEP_VERSION=2.2.7 +# +# +#E3_KMOD_SRC_PATH:=$(E3_MODULE_SRC_PATH) +# +# In most case, we don't need to touch the following variables. +# + +E3_MODULE_NAME:=$(EPICS_MODULE_NAME) +E3_MODULE_SRC_PATH:=ecmcPlugin_Advanced-loc +E3_MODULE_MAKEFILE:=$(EPICS_MODULE_NAME).Makefile + + +-include $(TOP)/configure/CONFIG_OPTIONS +# The definitions shown below can also be placed in an untracked CONFIG_MODULE.local +-include $(TOP)/configure/CONFIG_MODULE.local + diff --git a/configure/CONFIG_OPTIONS b/configure/CONFIG_OPTIONS new file mode 100644 index 0000000..2e022c1 --- /dev/null +++ b/configure/CONFIG_OPTIONS @@ -0,0 +1,6 @@ +# +# WITH_PVA:=NO +# +# The definitions shown below can also be placed in an untracked CONFIG_OPTIONS.local +-include $(TOP)/configure/CONFIG_OPTIONS.local + diff --git a/configure/RELEASE b/configure/RELEASE new file mode 100644 index 0000000..772abc6 --- /dev/null +++ b/configure/RELEASE @@ -0,0 +1,11 @@ +# +EPICS_BASE:=/epics/base-7.0.3.1 + +E3_REQUIRE_NAME:=require +E3_REQUIRE_VERSION:=3.1.2 + +# The definitions shown below can also be placed in an untracked RELEASE.local +-include $(TOP)/../../RELEASE.local +-include $(TOP)/../RELEASE.local +-include $(TOP)/configure/RELEASE.local + diff --git a/configure/RULES b/configure/RULES new file mode 100644 index 0000000..56e9524 --- /dev/null +++ b/configure/RULES @@ -0,0 +1,12 @@ + +include $(REQUIRE_CONFIG)/RULES_E3 +include $(REQUIRE_CONFIG)/DEFINES_FT +include $(REQUIRE_CONFIG)/RULES_PATCH +include $(REQUIRE_CONFIG)/RULES_E3_SITELIBS + +include $(REQUIRE_CONFIG)/RULES_VLIBS +include $(REQUIRE_CONFIG)/RULES_VARS + +include $(TOP)/configure/module/RULES_MODULE +-include $(TOP)/configure/module/RULES_DKMS_L + diff --git a/configure/module/RULES_DKMS_L b/configure/module/RULES_DKMS_L new file mode 100644 index 0000000..c66bf32 --- /dev/null +++ b/configure/module/RULES_DKMS_L @@ -0,0 +1,38 @@ + +# KMOD_NAME := mrf + +# .PHONY: dkms_add + +# dkms_add: conf +# $(MSI) -M name="$(E3_MODULE_NAME)" -M version="$(E3_MODULE_VERSION)" -M kmod_name="$(KMOD_NAME)" $(TOP)/dkms/dkms_with_msi.conf.in > $(TOP)/dkms/dkms_with_msi.conf +# $(QUIET) cat $(TOP)/dkms/dkms_with_msi.conf $(TOP)/dkms/dkms_without_msi.conf > $(TOP)/dkms/dkms.conf +# $(QUIET) install -m 644 $(TOP)/dkms/dkms.conf $(E3_KMOD_SRC_PATH)/ +# $(SUDO) install -d /usr/src/$(E3_MODULE_NAME)-$(E3_MODULE_VERSION) +# $(SUDO) cp -r $(TOP)/$(E3_KMOD_SRC_PATH)/* /usr/src/$(E3_MODULE_NAME)-$(E3_MODULE_VERSION)/ +# $(SUDO) $(DKMS) add $(DKMS_ARGS) + + +# setup: +# $(QUIET) $(SUDO2) 'echo KERNEL==\"uio*\", ATTR{name}==\"mrf-pci\", MODE=\"0666\" | tee /etc/udev/rules.d/99-$(KMOD_NAME).rules' +# $(QUIET) $(SUDO) /bin/udevadm control --reload-rules +# $(QUIET) $(SUDO) /bin/udevadm trigger +# $(QUIET) $(SUDO2) 'echo $(KMOD_NAME) | tee /etc/modules-load.d/$(KMOD_NAME).conf' +# $(QUIET) $(SUDO) depmod --quick +# $(QUIET) $(SUDO) modprobe -rv $(KMOD_NAME) +# $(QUIET) $(SUDO) modprobe -v $(KMOD_NAME) +# $(QUIET) echo "" +# $(QUIET) echo "" +# $(QUIET) echo "It is OK to see \"E3/RULES_DKMS:37: recipe for target 'setup' failed\"" +# $(QUIET) echo "---------------------------------------------------------------------" +# $(QUIET) -ls -l /dev/uio* 2>/dev/null +# $(QUIET) echo "---------------------------------------------------------------------" + + +# setup_clean: +# $(QUIET) $(SUDO) modprobe -rv $(KMOD_NAME) +# $(SUDO) rm -f /etc/modules-load.d/$(KMOD_NAME).conf +# $(SUDO) rm -f /etc/udev/rules.d/99-$(KMOD_NAME).rules + + +# .PHONY: setup setup_clean + diff --git a/configure/module/RULES_MODULE b/configure/module/RULES_MODULE new file mode 100644 index 0000000..775070a --- /dev/null +++ b/configure/module/RULES_MODULE @@ -0,0 +1,20 @@ +# +.PHONY: db hdrs + +db: conf + $(QUIET) $(E3_MODULE_MAKE_CMDS) db + +hdrs: +# $(SUDO) install -m 755 -d $(E3_MODULES_INSTALL_LOCATION_INC)/pv +# cd $(E3_MODULES_INSTALL_LOCATION_INC) && $(SUDO) mv *.h pv/ + +#.PHONY: epics +#epics: +# $(QUIET)echo "EPICS_BASE:=$(EPICS_BASE)" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE +# $(QUIET)echo "ASYN:=$(M_ASYN)" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE +# $(QUIET)echo "SSCAN:=$(M_SSCAN)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE +# $(QUIET)echo "SNCSEQ:=$(M_SNCSEQ)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE +# $(QUIET)echo "CHECK_RELEASE:=YES" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/CONFIG_SITE +# $(QUIET)echo "INSTALL_LOCATION:=$(M_DEVLIB2)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/CONFIG_SITE +# $(SUDOBASH) "$(MAKE) -C $(E3_MODULE_SRC_PATH)" + diff --git a/docs/.MODULE_LOG b/docs/.MODULE_LOG new file mode 100644 index 0000000..b60b012 --- /dev/null +++ b/docs/.MODULE_LOG @@ -0,0 +1,28 @@ +>> +Script is used : e3TemplateGenerator.bash +Script Path : /home/anderssandstrom/plugin_ecmc/e3-tools/e3TemplateGenerator +Script Version : 1.0.8 +Script Run Time : 2020Mar22-1607-33CET +User : anderssandstrom +e3-tools Hash : bf03d40 +>> +>> git diff + +>> +>> git diff --cached + +>> +>> git diff HEAD + + +>> +>> Your sources are located in e3-ecmcPlugin_Simple. +>> +EPICS_MODULE_NAME : ecmcPlugin_Simple +E3_MODULE_SRC_PATH : ecmcPlugin_Simple +E3_TARGET_URL : https://github.com/anderssandstrom +>> +e3 module name : e3-ecmcPlugin_Simple +e3 target url full : https://github.com/anderssandstrom/e3-ecmcPlugin_Simple.git +>> +e3 module is located in siteMods diff --git a/docs/ecmcPlugin_Simple.conf b/docs/ecmcPlugin_Simple.conf new file mode 100644 index 0000000..aeb5756 --- /dev/null +++ b/docs/ecmcPlugin_Simple.conf @@ -0,0 +1,4 @@ +EPICS_MODULE_NAME:=ecmcPlugin_Simple +E3_TARGET_URL:=https://github.com/anderssandstrom +E3_MODULE_SRC_PATH:=ecmcPlugin_Simple +# diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/.keep b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/Db/.keep new file mode 100644 index 0000000..e69de29 diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/.keep b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/.keep new file mode 100644 index 0000000..e69de29 diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.cpp b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.cpp new file mode 100644 index 0000000..5a889ab --- /dev/null +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.cpp @@ -0,0 +1,75 @@ +/*************************************************************************\ +* 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. +* +* ecmcAdvanced.cpp +* +* Created on: Mar 22, 2020 +* Author: anderssandstrom +* Credits to https://github.com/sgreg/dynamic-loading +* +\*************************************************************************/ + +// Needed to get headers in ecmc right... +#define ECMC_IS_PLUGIN + +// Error Codes +#define ECMC_ERROR_ASYNPORT_NULL 1 +#define ECMC_ERROR_ASYN_PARAM_FAIL 2 + +#include "ecmcAdvanced.h" +#include "ecmcPluginClient.h" +#include "ecmcAsynPortDriver.h" + +// Vars +static int counter = 0; +static ecmcAsynDataItem *paramCount = NULL; + +// Use ecmcPluginClient.h interface +double getSampleRate() { + + return getEcmcSampleRate(); +} + +// Use ecmcPluginClient.h interface +void* getAsynPort() { + return getEcmcAsynPortDriver(); +} + +// register a dummy asyn parameter "plugin.adv.counter" +int initAsyn() { + + ecmcAsynPortDriver *ecmcAsynPort = (ecmcAsynPortDriver *)getEcmcAsynPortDriver(); + if(!ecmcAsynPort) { + printf("Error: ecmcPlugin_Advanced: ecmcAsynPortDriver NULL."); + return ECMC_ERROR_ASYNPORT_NULL; + } + + // Add a dummy counter that incraeses one for each rt cycle + paramCount = ecmcAsynPort->addNewAvailParam( + "plugin.adv.counter", // name + asynParamInt32, // asyn type + (uint8_t *)&(counter),// pointer to data + sizeof(counter), // size of data + ECMC_EC_S32, // ecmc data type + 0); // die if fail + if(!paramCount) { + printf("Error: ecmcPlugin_Advanced: Failed to create asyn param \"plugin.adv.counter\"."); + return ECMC_ERROR_ASYN_PARAM_FAIL; + } + paramCount->addSupportedAsynType(asynParamInt32); // Only allw records of this type + paramCount->setAllowWriteToEcmc(false); // read only + paramCount->refreshParam(1); // read once into asyn param lib + ecmcAsynPort->callParamCallbacks(ECMC_ASYN_DEFAULT_LIST, ECMC_ASYN_DEFAULT_ADDR); + return 0; +} + +// increase value of counter and refresh asyn param +void increaseCounter(){ + counter++; + if(paramCount){ + paramCount->refreshParamRT(0); + // "callParamCallbacks" are handled in ecmc rt thread so don't call + } +} diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.h b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.h new file mode 100644 index 0000000..2d4d1eb --- /dev/null +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcAdvanced.h @@ -0,0 +1,32 @@ +/*************************************************************************\ +* 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. +* +* ecmcAdvanced.h +* +* Created on: Mar 22, 2020 +* Author: anderssandstrom +* +\*************************************************************************/ +#ifndef ECMC_ADVANCED_H_ +#define ECMC_ADVANCED_H_ + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +// get ecmc rt sample rate from ecmcPluginClient.h funcs +double getSampleRate(); +// get ecmcAsynPort from ecmcPluginClient.h funcs +void* getAsynPort(); +// register a dummy asyn parameter "plugin.adv.counter" +int initAsyn(); +// increase value of counter and refresh asyn param +void increaseCounter(); + +#ifdef __cplusplus +} +#endif // ifdef __cplusplus + +#endif /* ECMC_ADVANCED_H_ */ diff --git a/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcPluginExample.c b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcPluginExample.c new file mode 100644 index 0000000..de9c0c6 --- /dev/null +++ b/ecmcPlugin_FFT-loc/ecmcPlugin_FFTApp/src/ecmcPluginExample.c @@ -0,0 +1,225 @@ +/*************************************************************************\ +* 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. +* +* ecmcPluginExample.cpp +* +* Created on: Mar 21, 2020 +* Author: anderssandstrom +* +\*************************************************************************/ + +// Needed to get headers in ecmc right... +#define ECMC_IS_PLUGIN +#define ECMC_EXAMPLE_PLUGIN_VERSION 1 + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +#include +#include +#include + +#include "ecmcPluginDefs.h" +#include "ecmcAdvanced.h" +#include "ecmcPLC.h" + +#define ECMC_PLUGIN_DBG_OPTION_CMD "DBG_PRINT" + +#define PRINT_IF_DBG_MODE(fmt, ...) \ + { \ + if(dbgModeOption){ \ + printf(fmt, ## __VA_ARGS__); \ + } \ + } \ + +static int lastEcmcError = 0; +static double ecmcSampleRate = 0; +static void* ecmcAsynPort = NULL; +static char* confStr = NULL; +static int dbgModeOption = 0; + +/** Optional. + * Will be called once after successfull load into ecmc. + * Return value other than 0 will be considered error. + * configStr can be used for configuration parameters. + **/ +int adv_exampleConstruct(char * configStr) +{ + confStr = strdup(configStr); + //Only one option defined "DBG_PRINT=" (no need for loop) + int tempValue=0; + int nvals = sscanf(confStr, ECMC_PLUGIN_DBG_OPTION_CMD"=%d",&tempValue); + if (nvals == 1) { + dbgModeOption = tempValue; + } + + PRINT_IF_DBG_MODE("%s/%s:%d: ConfigStr=\"%s\"...\n",__FILE__, __FUNCTION__, __LINE__,configStr); + // Determine ecmc sample rate (just for demo) + ecmcSampleRate = getSampleRate(); + PRINT_IF_DBG_MODE("%s/%s:%d Ecmc sample rate is: %lf ms\n",__FILE__, __FUNCTION__, __LINE__,ecmcSampleRate); + + // Use ecmcAsynPort (just for demo) + ecmcAsynPort = getAsynPort(); + + // init asyn param counter + initAsyn(ecmcAsynPort); + + return 0; +} + +/** Optional function. + * Will be called once at unload. + **/ +void adv_exampleDestruct(void) +{ + PRINT_IF_DBG_MODE("%s/%s:%d...\n",__FILE__, __FUNCTION__, __LINE__); + + if(confStr){ + free(confStr); + } +} + +/** Optional function. + * Will be called each realtime cycle if definded + * ecmcError: Error code of ecmc. Makes it posible for + * this plugin to react on ecmc errors + * Return value other than 0 will be considered to be an error code in ecmc. + **/ +int adv_exampleRealtime(int ecmcError) +{ + // Check if plc 0 is enabled.. Just to show something with the ecmc headers + int plcEnabled = 0; + getPLCEnable(0,&plcEnabled); + + PRINT_IF_DBG_MODE("%s/%s:%d: plc0.enabled=%d\n",__FILE__, __FUNCTION__, __LINE__,plcEnabled); + + //Update asynparam counter + increaseCounter(); + lastEcmcError = ecmcError; + return 0; +} + +/** Optional function. + * Will be called once just before going to realtime mode + * Return value other than 0 will be considered error. + **/ +int adv_exampleEnterRT(){ + return 0; +} + +/** Optional function. + * Will be called once just before leaving realtime mode + * Return value other than 0 will be considered error. + **/ +int adv_exampleExitRT(void){ + PRINT_IF_DBG_MODE("%s/%s:%d...\n",__FILE__, __FUNCTION__, __LINE__); + return 0; +} + +/** Optional plc function 1*/ +double adv_customPlcFunc1(double arg1, double arg2) +{ + PRINT_IF_DBG_MODE("%s/%s:%d...\n",__FILE__, __FUNCTION__, __LINE__); + return arg1 * arg2; +} + +/** Optional plc function 2*/ +double adv_customPlcFunc2(double arg1, double arg2, double arg3) +{ + PRINT_IF_DBG_MODE("%s/%s:%d...\n",__FILE__, __FUNCTION__, __LINE__); + return arg1 * arg2 * arg3; +} + +// Register data for plugin so ecmc know what to use +struct ecmcPluginData pluginDataDef = { + // Allways use ECMC_PLUG_VERSION_MAGIC + .ifVersion = ECMC_PLUG_VERSION_MAGIC, + // Name + .name = "ecmcExamplePlugin", + // Description + .desc = "Advanced example with use of asynport obj.", + // Option description + .optionDesc = ECMC_PLUGIN_DBG_OPTION_CMD"=1/0 : Enables/disables printouts from plugin.", + // Plugin version + .version = ECMC_EXAMPLE_PLUGIN_VERSION, + // Optional construct func, called once at load. NULL if not definded. + .constructFnc = adv_exampleConstruct, + // Optional destruct func, called once at unload. NULL if not definded. + .destructFnc = adv_exampleDestruct, + // Optional func that will be called each rt cycle. NULL if not definded. + .realtimeFnc = adv_exampleRealtime, + // Optional func that will be called once just before enter realtime mode + .realtimeEnterFnc = adv_exampleEnterRT, + // Optional func that will be called once just before exit realtime mode + .realtimeExitFnc = adv_exampleExitRT, + + // Allow max s custom plc funcs + .funcs[0] = + { /*----customPlcFunc1----*/ + // Function name (this is the name you use in ecmc plc-code) + .funcName = "adv_plugin_func_1", + // Function description + .funcDesc = "Multiply arg0 with arg1.", + /** + * 11 different prototypes allowed (only doubles since reg in plc). + * Only one funcArg func shall be assigned the rest set to NULL. + **/ + .funcArg0 = NULL, + .funcArg1 = NULL, + .funcArg2 = adv_customPlcFunc1, // Func 1 has 2 args + .funcArg3 = NULL, + .funcArg4 = NULL, + .funcArg5 = NULL, + .funcArg6 = NULL, + .funcArg7 = NULL, + .funcArg8 = NULL, + .funcArg9 = NULL, + .funcArg10 = NULL + }, + .funcs[1] = + { /*----customPlcFunc2----*/ + // Function name (this is the name you use in ecmc plc-code) + .funcName = "adv_plugin_func_2", + // Function description + .funcDesc = "Multiply arg0, arg1 and arg2.", + /** + * 11 different prototypes allowed (only doubles since reg in plc). + * Only funcArg${argCount} func shall be assigned the rest set to NULL. + **/ + .funcArg0 = NULL, + .funcArg1 = NULL, + .funcArg2 = NULL, + .funcArg3 = adv_customPlcFunc2, // Func 2 has 3 args + .funcArg4 = NULL, + .funcArg5 = NULL, + .funcArg6 = NULL, + .funcArg7 = NULL, + .funcArg8 = NULL, + .funcArg9 = NULL, + .funcArg10 = NULL + }, + .funcs[2] = {0}, // last element set all to zero.. + + /** Plugin specific constants (add prefix to not risc collide with + * names from other modules) */ + .consts[0] = { + .constName = "adv_CONST_1", + .constDesc = "Test constant \"adv_CONST_1\" = 1.234567890", + .constValue = 1.234567890, + }, + .consts[1] = { + .constName = "adv_CONST_2", + .constDesc = "Test constant \"adv_CONST_2\" = 9.876543210", + .constValue = 9.876543210, + }, + .consts[2] = {0}, // last element set all to zero.. +}; + +ecmc_plugin_register(pluginDataDef); + +# ifdef __cplusplus +} +# endif // ifdef __cplusplus diff --git a/ecmcPlugin_FFT.Makefile b/ecmcPlugin_FFT.Makefile new file mode 100644 index 0000000..0392ac5 --- /dev/null +++ b/ecmcPlugin_FFT.Makefile @@ -0,0 +1,63 @@ +# +# Copyright (c) 2019 European Spallation Source ERIC +# +# The program is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 2 of the +# License, or any newer version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see https://www.gnu.org/licenses/gpl-2.0.txt +# +# +# Author : anderssandstrom +# email : anderssandstrom@esss.se +# Date : 2020Mar22-1607-33CET +# version : 0.0.0 +# +# template file is generated by ./e3TemplateGenerator.bash with bf03d40 +# Please look at many other _module_.Makefile in e3-* repository +# + + + + +## The following lines are mandatory, please don't change them. +where_am_I := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +include $(E3_REQUIRE_TOOLS)/driver.makefile +include $(E3_REQUIRE_CONFIG)/DECOUPLE_FLAGS + +ifneq ($(strip $(ASYN_DEP_VERSION)),) +asyn_VERSION=$(ASYN_DEP_VERSION) +endif + +ifneq ($(strip $(ECMC_DEP_VERSION)),) +ecmc_VERSION=$(ECMC_DEP_VERSION) +endif + +APP:=ecmcPlugin_AdvancedApp +APPDB:=$(APP)/Db +APPSRC:=$(APP)/src + +USR_CFLAGS += -shared -fPIC -Wall -Wextra +USR_LDFLAGS += -lstdc++ +USR_INCLUDES += -I$(where_am_I)$(APPSRC) + +TEMPLATES += $(wildcard $(APPDB)/*.db) +SOURCES += $(APPSRC)/ecmcPluginExample.c +SOURCES += $(APPSRC)/ecmcAdvanced.cpp + +db: + +.PHONY: db + +vlibs: + +.PHONY: vlibs + +### diff --git a/iocsh/.keep b/iocsh/.keep new file mode 100644 index 0000000..e69de29 diff --git a/opi/.keep b/opi/.keep new file mode 100644 index 0000000..e69de29 diff --git a/patch/Site/HISTORY.md b/patch/Site/HISTORY.md new file mode 100644 index 0000000..3516ac7 --- /dev/null +++ b/patch/Site/HISTORY.md @@ -0,0 +1,7 @@ +# E3_MODULE_VERSION-what_ever_filename.p0.patch + +Generic Description..... + +* created by Jeong Han Lee, han.lee@esss.se +* related URL or reference https://github.com/icshwi +* Tuesday, February 13 13:24:57 CET 2018 diff --git a/patch/Site/README.md b/patch/Site/README.md new file mode 100644 index 0000000..fbed8e6 --- /dev/null +++ b/patch/Site/README.md @@ -0,0 +1,22 @@ +# Site Specific EPICS Module Patch Files + +## Changes +The changes were tested in local environemnt, and commits to the forked repository and do pull request to the epics community module repository. + +* Check the original HASH, and your own master +* feb8856 : The original HASH +* master : Changed + + +## How to create a p0 patch file between commits + + +* Show what the difference between commits + + +* Create p0 patch + +``` +$git diff feb8856 master --no-prefix > ../patch/Site/E3_MODULE_VERSION-what_ever_filename.p0.patch +``` + diff --git a/template/.keep b/template/.keep new file mode 100644 index 0000000..e69de29