Start with motion plugin as base (just minor cleanup and renaming made) WIP
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcPluginExample.cpp
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
|
||||
// Needed to get headers in ecmc right...
|
||||
#define ECMC_IS_PLUGIN
|
||||
#define ECMC_EXAMPLE_PLUGIN_VERSION 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // ifdef __cplusplus
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ecmcPluginDefs.h"
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
#include "ecmcMotionPlgWrap.h"
|
||||
|
||||
static int lastEcmcError = 0;
|
||||
static char* lastConfStr = NULL;
|
||||
|
||||
/** 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 motionConstruct(char *configStr)
|
||||
{
|
||||
//This module is allowed to load several times so no need to check if loaded
|
||||
|
||||
// create FFT object and register data callback
|
||||
lastConfStr = strdup(configStr);
|
||||
return createMotionObj(configStr);
|
||||
}
|
||||
|
||||
/** Optional function.
|
||||
* Will be called once at unload.
|
||||
**/
|
||||
void motionDestruct(void)
|
||||
{
|
||||
deleteAllMotionObjs();
|
||||
if(lastConfStr){
|
||||
free(lastConfStr);
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 motionRealtime(int ecmcError)
|
||||
{
|
||||
executeMotionObjs();
|
||||
lastEcmcError = ecmcError;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Link to data source here since all sources should be availabe at this stage
|
||||
* (for example ecmc PLC variables are defined only at enter of realtime)
|
||||
**/
|
||||
int motionEnterRT(){
|
||||
return linkDataTomotionObjs();
|
||||
}
|
||||
|
||||
/** Optional function.
|
||||
* Will be called once just before leaving realtime mode
|
||||
* Return value other than 0 will be considered error.
|
||||
**/
|
||||
int motionExitRT(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
//// Plc function for clear of buffers
|
||||
//double fft_clear(double index) {
|
||||
// return (double)clearFFT((int)index);
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_enable(double index, double enable) {
|
||||
// return (double)enableFFT((int)index, (int)enable);
|
||||
//}
|
||||
//
|
||||
//// Plc function for trigg new measurement (will clear buffers)
|
||||
//double fft_trigg(double index) {
|
||||
// return (double)triggFFT((int)index);
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_mode(double index, double mode) {
|
||||
// return (double)modeFFT((int)index, (FFT_MODE)((int)mode));
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_stat(double index) {
|
||||
// return (double)statFFT((int)index);
|
||||
//}
|
||||
|
||||
// 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 = "ecmcPlugin_Motion",
|
||||
// Description
|
||||
.desc = "Motion plugin for commissioning of ecmc motion axes.",
|
||||
// Option description
|
||||
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
|
||||
" "ECMC_PLUGIN_AXIS_OPTION_CMD"<axis id> : Sets default source axis id.\n"
|
||||
" "ECMC_PLUGIN_BUFFER_SIZE_OPTION_CMD"<size> : Data points to collect, default = 4096.\n"
|
||||
" "ECMC_PLUGIN_RATE_OPTION_CMD"<rate hz> : Sampling rate in Hz"
|
||||
" "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Sampling rate in Hz"
|
||||
,
|
||||
// Plugin version
|
||||
.version = ECMC_EXAMPLE_PLUGIN_VERSION,
|
||||
// Optional construct func, called once at load. NULL if not definded.
|
||||
.constructFnc = motionConstruct,
|
||||
// Optional destruct func, called once at unload. NULL if not definded.
|
||||
.destructFnc = motionDestruct,
|
||||
// Optional func that will be called each rt cycle. NULL if not definded.
|
||||
.realtimeFnc = motionRealtime,
|
||||
// Optional func that will be called once just before enter realtime mode
|
||||
.realtimeEnterFnc = motionEnterRT,
|
||||
// Optional func that will be called once just before exit realtime mode
|
||||
.realtimeExitFnc = motionExitRT,
|
||||
// PLC funcs
|
||||
// .funcs[0] =
|
||||
// { /*----fft_clear----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_clear",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_clear(index) : Clear/reset fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_clear,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[1] =
|
||||
// { /*----fft_enable----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_enable",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_enable(index, enable) : Set enable for fft[index].",
|
||||
// /**
|
||||
// * 7 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 = fft_enable,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[2] =
|
||||
// { /*----fft_trigg----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_trigg",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_trigg,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[3] =
|
||||
// { /*----fft_mode----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_mode",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].",
|
||||
// /**
|
||||
// * 7 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 = fft_mode,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[4] =
|
||||
// { /*----fft_stat----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_stat",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_stat,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
.funcs[0] = {0}, // last element set all to zero..
|
||||
// PLC consts
|
||||
/* CONTINIOUS MODE = 1 */
|
||||
// .consts[0] = {
|
||||
// .constName = "fft_CONT",
|
||||
// .constDesc = "FFT Mode: Continious",
|
||||
// .constValue = CONT
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[1] = {
|
||||
// .constName = "fft_TRIGG",
|
||||
// .constDesc = "FFT Mode :Triggered",
|
||||
// .constValue = TRIGG
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[2] = {
|
||||
// .constName = "fft_NO_STAT",
|
||||
// .constDesc = "FFT Status: Invalid state",
|
||||
// .constValue = NO_STAT,
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[3] = {
|
||||
// .constName = "fft_IDLE",
|
||||
// .constDesc = "FFT Status: Idle state (waiting for trigger)",
|
||||
// .constValue = IDLE
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[4] = {
|
||||
// .constName = "fft_ACQ",
|
||||
// .constDesc = "FFT Status: Acquiring data",
|
||||
// .constValue = ACQ
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[5] = {
|
||||
// .constName = "fft_CALC",
|
||||
// .constDesc = "FFT Status: Calculating result",
|
||||
// .constValue = CALC
|
||||
// },
|
||||
.consts[0] = {0}, // last element set all to zero..
|
||||
};
|
||||
|
||||
ecmc_plugin_register(pluginDataDef);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // ifdef __cplusplus
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,168 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlg.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
#ifndef ECMC_MOTION_PLG_H_
|
||||
#define ECMC_MOTION_PLG_H_
|
||||
|
||||
#include <stdexcept>
|
||||
#include "ecmcDataItem.h"
|
||||
#include "ecmcAsynPortDriver.h"
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
#include "inttypes.h"
|
||||
#include <string>
|
||||
#include "dbBase.h"
|
||||
#include "ecmcAxisBase.h"
|
||||
#include "ecmcDataBuffer.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsEvent.h"
|
||||
|
||||
#define ECMC_PLUGIN_MOTION_ERROR_AXIS_OUT_OF_RANGE 1
|
||||
|
||||
typedef enum TRIGG_MODE{
|
||||
NO_MODE = 0,
|
||||
CONT = 1,
|
||||
TRIGG = 2,
|
||||
} TRIGG_MODE;
|
||||
|
||||
class ecmcMotionPlg : public asynPortDriver {
|
||||
public:
|
||||
|
||||
/** ecmc Motion Plg class
|
||||
* This object can throw:
|
||||
* - bad_alloc
|
||||
* - invalid_argument
|
||||
* - runtime_error
|
||||
* - out_of_range
|
||||
*/
|
||||
ecmcMotionPlg(int objIndex, // index of this object
|
||||
char* configStr,
|
||||
char* portName);
|
||||
~ecmcMotionPlg();
|
||||
|
||||
// Add data to buffer (called from "external" callback)
|
||||
void dataUpdatedCallback(uint8_t* data,
|
||||
size_t size,
|
||||
ecmcEcDataType dt);
|
||||
// Call just before realtime because then all data sources should be available
|
||||
void connectToDataSource();
|
||||
void doWriteWorker(); // low prio worker thread
|
||||
void setEnable(int enable);
|
||||
void clearBuffers();
|
||||
void triggMotionObject();
|
||||
void executeMotionObject();
|
||||
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
|
||||
virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
|
||||
size_t nElements, size_t *nIn);
|
||||
virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value);
|
||||
|
||||
|
||||
private:
|
||||
void parseConfigStr(char *configStr);
|
||||
void addDataToBuffer(double data);
|
||||
void initAsyn();
|
||||
static int dataTypeSupported(ecmcEcDataType dt);
|
||||
int setAxis(int axisId);
|
||||
int setMode(TRIGG_MODE mode);
|
||||
int setTrigg(int trigg);
|
||||
void writeBuffers();
|
||||
void switchBuffers();
|
||||
|
||||
|
||||
epicsMutexId axisMutex_;
|
||||
|
||||
double* xAxisArray_; // FFT x axis with freqs
|
||||
size_t elementsInBuffer_;
|
||||
double ecmcSampleRateHz_;
|
||||
int dataSourceLinked_; // To avoid link several times
|
||||
int command_;
|
||||
int status_;
|
||||
// ecmc callback handle for use when deregister at unload
|
||||
int callbackHandle_;
|
||||
int destructs_;
|
||||
int objectId_; // Unique object id
|
||||
int triggOnce_;
|
||||
int cycleCounter_;
|
||||
int ignoreCycles_;
|
||||
|
||||
// Config options
|
||||
int cfgDbgMode_; // Config: allow dbg printouts
|
||||
size_t cfgArraySize_; // Config: Data set size
|
||||
int cfgEnable_; // Config: Enable data acq./calc.
|
||||
double cfgSampleRateHz_; // Config: Sample rate (defaults to ecmc rate)
|
||||
double cfgDataSampleRateHz_;// Config: Sample for data
|
||||
int cfgAxisIndex_; // Config: Enable data acq./calc.
|
||||
TRIGG_MODE cfgMode_; // Config: Mode continous or triggered.
|
||||
|
||||
// Asyn
|
||||
int asynEnableId_; // Enable/disable acq./calcs
|
||||
int asynYActPosArrayId_;
|
||||
int asynYSetPosArrayId_;
|
||||
int asynYDiffPosArrayId_;
|
||||
int asynXAxisArrayId_;
|
||||
int asynTriggId_; // Trigg new measurement
|
||||
int asynAxisId_; // motion axis id
|
||||
int asynSRateId_; // Sample rate
|
||||
int asynElementsInBufferId_; // Current buffer index
|
||||
int asynBufferSizeId_; // Current buffer index
|
||||
int asynCommandId_;
|
||||
int asynStatusId_;
|
||||
int asynModeId_;
|
||||
|
||||
ecmcAxisBase *axis_;
|
||||
// Thread related
|
||||
//epicsEvent doCalcEvent_;
|
||||
|
||||
|
||||
// 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 void printComplexArray(std::complex<double>* fftBuff,
|
||||
size_t elements,
|
||||
int objId);
|
||||
static std::string to_string(int value);
|
||||
|
||||
ecmcDataBuffer<epicsFloat64> *actPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *setPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *diffPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *xPosBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *enableBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *enabledBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *busyBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *executeBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *trajSourceBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *encSourceBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *atTargetBuffer_;
|
||||
ecmcDataBuffer<epicsInt32> *errorIdBuffer_;
|
||||
ecmcDataBuffer<epicsInt32> *statusWdBuffer_;
|
||||
|
||||
bool bTriggInProgress_;
|
||||
double xdt_;
|
||||
double xTime_;
|
||||
epicsEvent doWriteEvent_;
|
||||
int writeBusy_;
|
||||
timespec writePauseTime_;
|
||||
};
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_H_ */
|
||||
@@ -0,0 +1,39 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgDefs.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
* Credits to https://github.com/sgreg/dynamic-loading
|
||||
*
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef ECMC_MOTION_PLG_DEFS_H_
|
||||
#define ECMC_MOTION_PLG_DEFS_H_
|
||||
|
||||
#define ECMC_PLUGIN_ASYN_PREFIX "plugin.motion"
|
||||
|
||||
// Options
|
||||
#define ECMC_PLUGIN_DBG_PRINT_OPTION_CMD "DBG_PRINT="
|
||||
#define ECMC_PLUGIN_AXIS_OPTION_CMD "AXIS="
|
||||
#define ECMC_PLUGIN_BUFFER_SIZE_OPTION_CMD "BUFFER_SIZE="
|
||||
#define ECMC_PLUGIN_RATE_OPTION_CMD "RATE="
|
||||
#define ECMC_PLUGIN_ENABLE_OPTION_CMD "ENABLE="
|
||||
#define ECMC_PLUGIN_MODE_OPTION_CMD "MODE="
|
||||
|
||||
// CONT, TRIGG
|
||||
#define ECMC_PLUGIN_MODE_CONT_OPTION "CONT"
|
||||
#define ECMC_PLUGIN_MODE_TRIGG_OPTION "TRIGG"
|
||||
|
||||
|
||||
/** Just one error code in "c" part of plugin
|
||||
(error handled with exceptions i c++ part) */
|
||||
#define ECMC_PLUGIN_MOTION_ERROR_CODE 1
|
||||
|
||||
// Default size (must be n²)
|
||||
#define ECMC_PLUGIN_DEFAULT_ARRAY_SIZE 4096
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_DEFS_H_ */
|
||||
@@ -0,0 +1,126 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgWrap.cpp
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* 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 "ecmcMotionPlgWrap.h"
|
||||
#include "ecmcMotionPlg.h"
|
||||
|
||||
#define ECMC_PLUGIN_MAX_PORTNAME_CHARS 64
|
||||
#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.MOTION"
|
||||
|
||||
static std::vector<ecmcMotionPlg*> motionObjs;
|
||||
static int motionObjCounter = 0;
|
||||
static char portNameBuffer[ECMC_PLUGIN_MAX_PORTNAME_CHARS];
|
||||
|
||||
int createMotionObj(char* configStr) {
|
||||
|
||||
// create new ecmcMotionPlg object
|
||||
ecmcMotionPlg* motionObj = NULL;
|
||||
|
||||
// create asynport name for new object ()
|
||||
memset(portNameBuffer, 0, ECMC_PLUGIN_MAX_PORTNAME_CHARS);
|
||||
snprintf (portNameBuffer, ECMC_PLUGIN_MAX_PORTNAME_CHARS,
|
||||
ECMC_PLUGIN_PORTNAME_PREFIX "_%d", motionObjCounter);
|
||||
try {
|
||||
motionObj = new ecmcMotionPlg(motionObjCounter, configStr, portNameBuffer);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
if(motionObj) {
|
||||
delete motionObj;
|
||||
}
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
|
||||
motionObjs.push_back(motionObj);
|
||||
motionObjCounter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void deleteAllMotionObjs() {
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
delete (*pMotionObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int linkDataTomotionObjs() {
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
try {
|
||||
(*pMotionObj)->connectToDataSource();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enableMotionObj(int objIndex, int enable) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->setEnable(enable);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clearMotionObj(int objIndex) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->clearBuffers();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int triggMotionObj(int objIndex) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->triggMotionObject();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int executeMotionObjs() {
|
||||
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
try {
|
||||
(*pMotionObj)->executeMotionObject();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgWrap.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
#ifndef ECMC_MOTION_PLG_WRAP_H_
|
||||
#define ECMC_MOTION_PLG_WRAP_H_
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif // ifdef __cplusplus
|
||||
|
||||
/** \brief Create new Motion object
|
||||
*
|
||||
* The plugin supports creation of multiple Motion objects\n
|
||||
* (if loaded several times).\n
|
||||
* The different fft are adressed by fftindex (in other functions below).\n
|
||||
* The first loaded fft get index 0 and then increases for each load.\n
|
||||
* This function call will create the custom asynparameters dedicated for this plugin.\
|
||||
* The configuration string needs to define a data source by:\n
|
||||
* "SOURCE=<data source>;"\n
|
||||
* Example:\n
|
||||
* "SOURCE=ec0.s1.AI_1";\n
|
||||
* \param[in] configStr Configuration string.\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int createMotionObj(char *configStr);
|
||||
|
||||
/** \brief Enable/disable Motion object
|
||||
*
|
||||
* Enable/disable Motion object. If disabled no data will be acquired\n
|
||||
* and no calculations will be made.\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
* \param[in] enable enable/disable (1/0).\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int enableMotionObj(int objIndex, int enable);
|
||||
|
||||
/** \brief Clear FFT object\n
|
||||
*
|
||||
* Clears buffers. After this command the acquistion can start from scratch.\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int clearMotionObj(int objIndex);
|
||||
|
||||
/** \brief Set mode of FFT object
|
||||
*
|
||||
* The FFT object can measure in two differnt modes:\n
|
||||
* CONT(1) : Continious measurement (Acq data, calc, then Acq data ..)\n
|
||||
* TRIGG(2): Measurements are triggered from plc or over asyn and is only done once (untill next trigger)\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
* \param[in] mode Mode CONT(1) or TRIGG(2)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
//int modeMotionObj(int objIndex, FFT_MODE mode);
|
||||
|
||||
/** \brief Trigger FFT object\n
|
||||
*
|
||||
* If in triggered mode a new measurment cycle is initiated (fft will be cleared first).\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int triggMotionObj(int objIndex);
|
||||
|
||||
|
||||
/** \brief execute FFT object\n
|
||||
*
|
||||
* If in triggered mode a new measurment cycle is initiated (fft will be cleared first).\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int executeMotionObjs();
|
||||
|
||||
/** \brief Link data to _all_ fft objects
|
||||
*
|
||||
* This tells the FFT lib to connect to ecmc to find it's data source.\n
|
||||
* This function should be called just before entering realtime since then all\n
|
||||
* data sources in ecmc will be definded (plc sources are compiled just before runtime\n
|
||||
* so are only fist accesible now).\n
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int linkDataTomotionObjs();
|
||||
|
||||
/** \brief Deletes all created fft objects\n
|
||||
*
|
||||
* Should be called when destructs.\n
|
||||
*/
|
||||
|
||||
void deleteAllMotionObjs();
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // ifdef __cplusplus
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_WRAP_H_ */
|
||||
Reference in New Issue
Block a user