commit 557bbb0eaec026465de3b4f916f2d8585ca79623 Author: chrin Date: Tue Sep 19 11:58:36 2017 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1318aa7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +*.bak +SL6-x86_64 +felix-cache diff --git a/MakefileWin/Makefile b/MakefileWin/Makefile new file mode 100644 index 0000000..3f3018e --- /dev/null +++ b/MakefileWin/Makefile @@ -0,0 +1,59 @@ +MATLAB_ROOT=C:\Program Files\MATLAB\R2016b_x64 + +MEXE=mexw64 +empty:= + +s? = $(subst $(empty) ,?,$1) +?s = $(subst ?, ,$1) + +notdirx = $(call ?s,$(notdir $(call s?,$1))) +MATLAB_VERSION= $(call notdirx, $(MATLAB_ROOT)) +$(info ****************) +$(info $(MATLAB_VERSION)) +$(info ****************) + + +INCLUDES = -IC:\CAFE\cafe-1.0.0-beta-3\cpp\include -IC:\local\boost_1_63_0 \ +-IC:\local\boost_1_63_0\boost -IC:\epics\base-3.14.12.5\include -IC:\epics\base-3.14.12.5\include\os\WIN32 \ +-I"$(MATLAB_ROOT)"\extern\include \ +-Ic:\Qt\qt-4.8.6-x64-msvc2010\include -Ic:\Qt\qt-4.8.6-x64-msvc2010\include\QtCore -Ic:\Qt\qt-4.8.6-msvc2010\include\QtXml + +CXX=cl +CXXFLAGS = /W4 /EHsc +OUTPUT_OPTION = /o $@ + +LIB_CAFE=C:\CAFE\cafe-1.0.0-beta-3\cpp\lib\cafe\cafe.lib + +LIB_BOOST =C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-1_63.lib + +LIB_BOOST2=C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_thread-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_system-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-s-1_63.lib + + +LIB_QT=C:\Qt\Qt-4.8.6-x64-msvc2010\lib\QtCore4.lib C:\Qt\qt-4.8.6-x64-msvc2010\lib\QtXml4.lib + +LIB_EPICS=C:\epics\base-3.14.12.5\lib\windows-x64\Com.lib C:\epics\base-3.14.12.5\lib\windows-x64\ca.lib + +LIB_MATLAB=-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmat.lib \ +-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmex.lib \ +-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmx.lib + +OBJ_DIR=$(MATLAB_VERSION) + + +$(OBJ_DIR)\mocha.$(MEXE): mocha.cpp $(OBJ_DIR)\macchinettaSwitch.obj + "$(MATLAB_ROOT)"\bin\win64\mex -v COMPFLAGS="$(COMPFLAGS) -Wall" mocha.cpp \ + $(OBJ_DIR)/macchinettaSwitch.obj -DDB_TEXT_GLBLSOURCE -DMSCC -DWIN32 -DWIN64 -largeArrayDims \ + $(INCLUDES) $(LIB_MATLAB) $(LIB_EPICS) $(LIB_CAFE) $(LIB_BOOST) $(LIB_BOOST2) $(LIB_QT) \ + -outdir $(OBJ_DIR) -output mocha.$(MEXE) + +$(OBJ_DIR)\macchinettaSwitch.obj: macchinettaSwitch.cpp macchinettaHelper.h \ + macchinetta.h containerMochaccino.h + "$(MATLAB_ROOT)"\bin\win64\mex -largeArrayDims \ + -c macchinettaSwitch.cpp $(INCLUDES) -outdir $(OBJ_DIR) + +clean: + del $(OBJ_DIR)\macchinettaSwitch.obj $(OBJ_DIR)\mocha.$(MEXE) + diff --git a/MakefileWin/Makefile_noqt b/MakefileWin/Makefile_noqt new file mode 100644 index 0000000..46f2d14 --- /dev/null +++ b/MakefileWin/Makefile_noqt @@ -0,0 +1,63 @@ +# +# Note LIB_CAFE=C:\CAFE\cafe-1.0.0-beta-3\cpp\lib\cafe-noqt\cafe.lib +# +MATLAB_ROOT=C:\Program Files\MATLAB\R2016b_x64 + +MEXE=mexw64 +empty:= + +s? = $(subst $(empty) ,?,$1) +?s = $(subst ?, ,$1) + +notdirx = $(call ?s,$(notdir $(call s?,$1))) +MATLAB_VERSION= $(call notdirx, $(MATLAB_ROOT)) +$(info ****************) +$(info $(MATLAB_VERSION)) +$(info ****************) + + +INCLUDES = -IC:\CAFE\cafe-1.0.0-beta-3\cpp\include -IC:\local\boost_1_63_0 \ +-IC:\local\boost_1_63_0\boost -IC:\epics\base-3.14.12.5\include -IC:\epics\base-3.14.12.5\include\os\WIN32 \ +-I"$(MATLAB_ROOT)"\extern\include +#-Ic:\Qt\qt-4.8.6-x64-msvc2010\include -Ic:\Qt\qt-4.8.6-x64-msvc2010\include\QtCore -Ic:\Qt\qt-4.8.6-msvc2010\include\QtXml + +CXX=cl +CXXFLAGS = /W4 /EHsc +OUTPUT_OPTION = /o $@ + + +LIB_CAFE=C:\CAFE\cafe-1.0.0-beta-3\cpp\lib\cafe-noqt\cafe.lib + +LIB_BOOST =C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-1_63.lib + +LIB_BOOST2=C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_thread-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_system-vc100-mt-s-1_63.lib \ +C:\local\boost_1_63_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-s-1_63.lib + + +LIB_QT=C:\Qt\Qt-4.8.6-x64-msvc2010\lib\QtCore4.lib C:\Qt\qt-4.8.6-x64-msvc2010\lib\QtXml4.lib + +LIB_EPICS=C:\epics\base-3.14.12.5\lib\windows-x64\Com.lib C:\epics\base-3.14.12.5\lib\windows-x64\ca.lib + +LIB_MATLAB=-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmat.lib \ +-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmex.lib \ +-I"$(MATLAB_ROOT)"\extern\lib\win64\microsoft\libmx.lib + +OBJ_DIR=$(MATLAB_VERSION) + + +$(OBJ_DIR)\mocha.$(MEXE): mocha.cpp $(OBJ_DIR)\macchinettaSwitch.obj + "$(MATLAB_ROOT)"\bin\win64\mex -v COMPFLAGS="$(COMPFLAGS) -Wall" mocha.cpp \ + $(OBJ_DIR)/macchinettaSwitch.obj -DDB_TEXT_GLBLSOURCE -DMSCC -DWIN32 -DWIN64 -largeArrayDims \ + $(INCLUDES) $(LIB_MATLAB) $(LIB_EPICS) $(LIB_CAFE) $(LIB_BOOST) $(LIB_BOOST2) \ + -outdir $(OBJ_DIR) -output mocha.$(MEXE) + +$(OBJ_DIR)\macchinettaSwitch.obj: macchinettaSwitch.cpp macchinettaHelper.h \ + macchinetta.h containerMochaccino.h + "$(MATLAB_ROOT)"\bin\win64\mex -largeArrayDims \ + -c macchinettaSwitch.cpp $(INCLUDES) -outdir $(OBJ_DIR) + +clean: + del $(OBJ_DIR)\macchinettaSwitch.obj $(OBJ_DIR)\mocha.$(MEXE) + diff --git a/MakefileWin/mex_C++_win64.xml b/MakefileWin/mex_C++_win64.xml new file mode 100644 index 0000000..2f98f99 --- /dev/null +++ b/MakefileWin/mex_C++_win64.xml @@ -0,0 +1,146 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README b/README new file mode 100644 index 0000000..dcf1c46 --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +USE makefile_rel_2014_manual for release versio + + +## -------------------------------------------------------------------------- +## makefile +## + + +make: installs mocha mex file and associated shared object file locally +into $OBJ_DIR=${EPICS_HOST_ARCH}/$(MATLAB_VERSION) + + +make install: installs mocha mex file and associated shared object file +into INSTALL_PATH?=$(INSTALL_MOCHA_LIBDIR) where: +INSTALL_MOCHA_LIBDIR= $(CAFE_BASE)/mocha/$(MOCHA_VERSION)/lib/${EPICS_HOST_ARCH}/$(MATLAB_VERSION) + + +make clean: +rm $(OBJ_DIR)/*.o $(OBJ_DIR)/*.so $(OBJ_DIR)/*.$(MEXE) + +## -------------------------------------------------------------------------- diff --git a/containerMochaccino.h b/containerMochaccino.h new file mode 100644 index 0000000..1e32aac --- /dev/null +++ b/containerMochaccino.h @@ -0,0 +1,60 @@ + + + +struct mochaccino +{ +long id; +std::string name; + + mochaccino(long _id, std::string _name):id(_id),name(_name){}; + + friend std::ostream& operator<<(std::ostream& os, const mochaccino& m) + { + //os<, BOOST_MULTI_INDEX_MEMBER(mochaccino, std::string , name)>, + ordered_non_unique< + tag, BOOST_MULTI_INDEX_MEMBER(mochaccino, long, id )> > + > mochaccino_set; + + +template +void print_out_by( + const MultiIndexContainer& s, + Tag* =0 +) +{ + +// obtain a reference to the index tagged by Tag + + const typename boost::multi_index::index::type& i= + get(s); + + typedef typename MultiIndexContainer::value_type value_type; + +// dump the elements of the index to cout + std::cout << "--------------" << std::endl; + std::cout << " METHODS LIST " << std::endl; + std::cout << "--------------" << std::endl; + std::copy(i.begin(),i.end(),std::ostream_iterator(std::cout)); + std::cout << "--------------------" << std::endl; +} + +typedef mochaccino_set::index::type mochaccino_set_by_id; +typedef mochaccino_set::index::type mochaccino_set_by_name; + + + + + diff --git a/example.m b/example.m new file mode 120000 index 0000000..2d6dd2b --- /dev/null +++ b/example.m @@ -0,0 +1 @@ +exampleNew.m \ No newline at end of file diff --git a/exampleNew.m b/exampleNew.m new file mode 100644 index 0000000..c94a81d --- /dev/null +++ b/exampleNew.m @@ -0,0 +1,1055 @@ +%function example() +%mocha +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Jan Chrin, Paul Scherrer Institut +% March 2017 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (1) Establishing connections to EPICS Process Variables (PVs) +% (2) Simple single channel operations (and the PVData Object) +% (3) Understanding the Status Error Code / MATLAB Exceptions +% (4) Waveforms and Arrays +% (5) Handling Enumerated Types +% (6) Multiple scalar operations, i.e., operations on several PVs with scalar values +% (7) Multiple cell array ('compound') operations, i.e., on several PVS with scalar/vector values +% (8) Multiple Struct operations on several PVS returning PVData Objects plus Multiple Sets for Scalars/Vectors +% (9) Asynchronous interactions and retrieving data from Cache +% (10) Synchronous group operations, also with externally defined groups +% (11) Monitors, either with or without user supplied callbacks (in essence, matlab scripts) +% (12) Control system parameters, i.e., operating limits, engineerimg units +% (13) Retrieve channel medadata, e.g., data type, native no. elements, connection state, read/write access, etc. +% (14) Setting timeouts for set/get operations +% (15) Setting synchronous group timeouts for set/get operations +% (16) Special Methods, e.g., setAndGet, setAndMatch +% (17:END) Gracefully terminate CAFE +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% the mocha release is accompanied with the long established mca scripts +% which have been accordingly 'mocha-fied', +% i.e., the 'mocha' interface is used from within the mca scripts +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Test channels +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% To run this test script, first create 5 soft channels of the given class. +% pv(1:2) are scalar numerics, pv(3) is a wf, pv(4) is a mbbo record (enum), +% pv(5) is a dbr_string_t, pv(6) does not exist +pv={'ARIDI-BPM-01LE:X-AVG','ARIDI-BPM-01LE:Y-AVG','ARIDI-BPM-01LE:WF-INT-2','ARIDI-BPM-01LE:SET-ENABLE','ARIDI-BPM-01LE:SET-ENABLE.DESC','PV-JOKE'}; + +% +% MATLAB's Run and Advance utility will run each of these 17 sections at the user's prompt. + +% To create an executable: +% uncomment function example in first line and run the mcc compiler +% mcc -m example +% ./run_example.sh $MATLAB_DIR + + +% The following monitorAction.m is included in the movcha release for test purposes. +% Otherwise please copy and place it in your local directory from where matlab +% will be started. This file can optionally be used as a callback function for monitors. + +%monitorAction.m +%{ +function varargout = monitorAction(varargin) +disp('monitorAction called for:'); +pvName=mocha('getPVFromHandle', varargin{1}); +disp(pvName); +X=['Handle =', num2str(varargin{1})]; +disp(X); + +%[varargout{1} varargout{2}] = mocha ('getCache', varargin{1}); +[var1,var2]=mocha ('getCache', varargin{1}); +[s,t]=mocha('getStatus', varargin{1}); +%X=['Value=', num2str(varargout{1}), ' Status=', num2str(s), ' [',t(1), ' ', t(2),']']; +X=['Value =', num2str(var1)]; +Y=['Status=', num2str(s)]; +disp(X) +disp(Y) +disp([t(1),t(2)]) +%} + + + +%%%% +mocha('test'); %test if mocha MEX-file is accessible +mocha('version'); %lists mocha/cafe version +%mocha('show'); %lists all available mocha methods +%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (1) Establishing connections to EPICS Process Variables (PVs) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Explicitly opening channels is good practice even if only optional +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (1) Establishing connections to EPICS Process Variables (PVs) '); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + +%returns an array of handles (object references) +hpv=mocha('open',pv); + +%When executing the 'open' message as above, the default behaviour +%is for each 'open' to wait for a fixed amount of time, given by: +openTime = mocha ('getOpenWaitTime'); %currently 0.4s +%The 'open' wait time can, however, be configured by the user as follows: +mocha ('setOpenWaitTime', 0.2); %set to 0.2s +mocha ('setOpenWaitTime'); %reset to default (0.4s) +%The above shoud be set before the mocha 'open' method is executed + + +%If opening numerous channels, however, better to do this with a single message. +%This is done as shown here: +mocha('openPrepare'); +hpv=mocha('open',pv); +% and more mocha 'open' messages would follow here... +% Finally send the messages and wait for 0.2s for connections to complete +mocha('openNowAndWait', 0.2) + +%There are a number of ways to extract information on the created handles +%print all handles whether connected or not +mocha('printHandles'); + +%Array of handles and matching PVnames +[handles, pvs] = mocha ('getHandles'); +[handles, pvs] = mocha ('getConnectedHandles'); +[handles, pvs] = mocha ('getDisconnectedHandles'); +%Array of handles, matching PVnames and connection states +[handles, pvs, states] = mocha ('getHandleStates'); + +%print information on disconnected channels +if (~mocha('allConnected')) + mocha('printDisconnectedHandles'); + %or + [handles, pvs] = mocha ('getDisconnectedHandles'); + for n =1 : length(handles) + X=['Handle=', num2str(handles(n)), 'PV=',pvs(n)]; + disp(X); + end +end + +%To check on the connection state of a single channel +logicValue=mocha('isConnected', pv(1)); %by pvName +logicValue=mocha('isConnected', hpv(1)); %byHandle + + +%Handle and PV Mapping +%Retrieve handle for a given PV +handle = mocha ('getHandleFromPV', pv(1)); +pvName = mocha ('getPVFromHandle', hpv(1)); + +%% +%or run the MATLAB script (which also shows latest values) +disp('If val is NaN then a harmless warning will appear from struct2table'); +%Warning: Out of range or non-integer values truncated during +%conversion to character + +pvtable + + +%Channels may be closed when the application no longer needs them +%mocha ('close', pv(1)); %close given channel +%mocha ('close', pv); %close given channels +%Close all chanels and release all ca resources before exiting MATLAN +%mocha ('close'); + +%END (1) Establishing connections to EPICS Process Variables (PVs) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(2) Simple single channel operations (and the PVData Object) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (2) Simple single channel operations '); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%Now perform some get/set operations + +%Mocha operations will accept either a pv name or the pv handle +%(as returned from the mocha 'open' method) as the 2nd input argument + +%GET value +%by pvName; value (scalar or vector) returned in native data type +[value, status]= mocha ('get', pv(1)); +%by Handle; value (scalar or vector) returned in native data type +[value, status]= mocha ('get', hpv(1)); + +%by pvName; value (scalar or vector) returned as a MATLAB double +[value, status]= mocha ('get', pv(1), 'uint8'); +%by pvName; value (scalar or vector) returned as a MATLAB uint8 type +[value, status]= mocha ('get', pv(1), 'double'); + +%SET +%value (scalar or vector) can be in any MATLAB data type +[status] = mocha('set', pv(1), value); + +%Single channel operations that return data, alarms and timestamps +%pvData struct returned; pvData.val has the native data type +pvData = mocha ('getPV', pv(1)); +%pvData struct returned; pvData.val has the double data type +disp('Displaying pvdata struct'); +pvData = mocha ('getPV', pv(1), 'double') + +pvData.val; +pvData.status; % int32 +pvData.alarmStatus; %int16 +pvData.alarmSeverity; %int16 +pvData.ts; %[year, month, day, hour, min, sec, nsec] + + +%Other ways to retrieve alarms and timestamps from cache following a 'get' + ts=mocha('getTimestamp', pv(1)); +[ets]=mocha('getETS', pv(1)) % [secPastEpoch, nsec] + +[alarmStatSev] = mocha ('getAlarm', pv(1)); %[alarmStatus, alarmSeverity] +[alarmStatSev] = mocha ('getAlarmAsString', pv(1)) %[alarmStatus, alarmSeverity] + +%The string equivalenty of an integer alarmStatus/Severity +%may be gotten at any time as follows; +alarmStatus_str = mocha('alarmStatusAsString', pvData.alarmStatus); +alarmSeverity_str = mocha('alarmSeverityAsString', pvData.alarmSeverity); + +%Alarm conditions and alarm severities can be listed as follows: +disp('Listing all possible alarm condition value/name pairs') +[strVal, intVal] = mocha('alarmStatusList'); +for n = 1:length(intVal) + [intVal(n), strVal(n)] +end +disp('Listing all possible alarm severity value/name pairs') +[strVal, intVal] = mocha('alarmSeverityList'); +for n = 1:length(intVal) + [intVal(n), strVal(n)] +end + + +%An extended (x) struct holding supplementary data may also be retrieved: +disp('Displaying extended pvdata struct'); +pvStruct = mocha ('getStruct', pv(1)) +pvStruct.handle; %uint32 +pvStruct.pv; %char +pvStruct.val; +pvStruct.status; %int32 +pvStruct.status_str; %char +pvStruct.alarmStatus; %int16 +pvStruct.alarmStatus_str; %char +pvStruct.alarmSeverity; %int16 +pvStruct.alarmSeverity_str; %char +pvStruct.ts; %[year, month, day, hour, min, sec, nsec] +pvStruct.epicsTS; %[secPastEpoch, nsec] + +%END (2) Simple single channel operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(3) Understanding the Status Error Code / MATLAB Exceptions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (3) Understanding the Status Error Code / MATLAB Exceptions'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +[value, status]= mocha ('get', pv(1)); + pvData = mocha ('getPV', pv(1)); + status = pvData.status; + +%A Status Code of 1 represents a normal completion +%Status Codes <=480 are generated by the native ca library +%Status Codes >=600 are generated by the underlying CAFE library + +%A status code is paired to an enumerated name +statusAsString=mocha ('statusAsString', status); +%The following returns the enumerated name +%preceded with severity (SUCCESS, INFO, WARNING, ERROR) +statusText = mocha ('statusAsText', status); +%Further information concerning the code +statusInfo = mocha ('statusInfo', status); + +%Another way to retrieve the full status information w.r.t. the previous +%operation on a given handle is +[status, statusArray] = mocha ('getStatus', pv(1)) +%status is the integer status code +%statusArray[1] returns same data as statusText above +%statusArray[2] returns same data as statusInfo above + +%Status code/name pairs can be listed as follows: +disp('Listing all possible status code value/name pairs') +[strVal, intVal] = mocha('statusList'); + +%Alarm conditions and alarm severities can be listed as follows: +%disp('Listing all possible alarm condition value/name pairs') +[strVal, intVal] = mocha('alarmStatusList'); +for n = 1:length(intVal) + [intVal(n), strVal(n)]; %not printed to window +end + +%Rather than have to check on the status codes, CAFE MATLAB exceptions can be +%enabled (mocha default is to have exceptions dis-enabled) + +mocha ('withExceptions', true) %enables MATLAB exceptions for single channel operations + +try + [val, status] = mocha ('get', pv(6)) %pv(6) is dis-connected as channel does not exist +catch ME + ME + %A MATLAB exception, MException, comprises the 'identifier' and 'message' properties + if strfind(ME.identifier,'CAFE_WARN') + warning(ME.message); + elseif strfind(ME.identifier, 'CAFE_INFO') + disp(ME.message); + elseif strfind(ME.identifer,'CAFE_ERROR') + error(ME.message); + else + disp(ME.message); + end +end + +mocha ('withExceptions', false) %dis-enable MATLAB exceptions for single channel operations + +%END (3) Simple single channel operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(4) Waveforms and Arrays +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (4) Waveforms and Arrays'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + +[value, status] = mocha ('get', pv(3)); %Returns all elements of the wf +[pvdata] = mocha ('getPV', pv(3)); %Returns all elements of the wf in pvdata.val + +%The default behaviour is for all elements of the wf to be read out and +%presented. However, this number together with an offset can be configured +%by the user + +nelemWF = mocha('setNelem', pv(3), 20); +offsetWF= mocha('setOffset',pv(3), 12); + +%nelemWF = mocha('setNelem', pv(3)); %sets to native value +%offsetWF= mocha('setOffset',pv(3), 0); %but remember to set offset to 0 too! + +%The subsequent method then returns an array (value) of length 20, +%containing data from the 13th until the 32nd element of the waveform. +[value, status] = mocha ('get', pv(3), 'double') + +%END (4) Waveforms and Arrays +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(5) Handling Enumerated Data Types +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (5) Handling Enumerated Data Types'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%Consider pv(4) which is an mbbo record with enumerated value/names +%0/off 1/on 2/{transient state} +%with current value 1, i.e., 'on' + +%Default behaviour is to present the value as a string: +[value, status] = mocha ('get', pv(4)); +%Hence above method will return a value of 'on' +X=[pv(4), 'has value', value]; +disp(X); +%Any MATLAB numberic data type, such as 'int8', 'single' could also be specified +[value, status] = mocha ('get', pv(4), 'uint8'); +%Hence above method would return a value of 1 +X=[pv(4), 'has value', num2str(value)]; +disp(X); + +%For set, the input value can be any valid numeric or string; +%It will be internally converted to an unsigned short before being sent to the IOC. +[status] = mocha ('set', pv(4), 0); % will send the value 0, i.e. 'off' +[status] = mocha ('set', pv(4), 'off'); % will send the value 0, being the value euivalent of the enumerated name +[status] = mocha ('set', pv(4), '0'); %will send an unsigned short value of 0 +[status] = mocha ('set', pv(4), 'anything'); %will complain that this is not a valid enumerated name +[status] = mocha ('set', pv(4), '0anything'); %will convert this to an unsigned short value of 0 + +%END (5) Handling Enumerated Data Types +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(6) Multiple Scalar Operations, i.e., operations on several PVs with scalar values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (6) Multiple Scalar Operations, i.e., operations on several PVs with scalar values'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%GET: +%Messages are collected and transmitted with one single method invocation +%If Handle/PV points to a WF, only the 1st element of the WF is returned. +%If a data type for the retrieved data is not specified, then the native type +%of the first handle/pv is selected, here (pv(1)) + + +pvInput=[pv(1:3),pv(6)]; +[val, isAllOK, s] = mocha ('getScalarArray', pvInput, 'double'); +% Alternatively +% [val, isAllOK, s] = mocha ('get', pvInput, 'double'); +% may be called; +% mocha('getScalarArray') will then be called internally +[val, isAllOK, s] = mocha ('get', pvInput, 'double') +if isAllOK ~= 1 + for n=1:length(s) + if s(n) ~= 1 + [codes,ctext]=mocha('getStatus', pvInput(n)); + X=['GET: Error in Elem:', num2str(n), pvInput(n), ':']; + Y=[num2str(codes), ctext(1)]; + disp(X); disp(Y); + end + end +end + + +%SET: +val(1)=val(1)+0.001; +[isAllOK, s] = mocha ('setScalarArray', pvInput, val); +% Alternatively +% [isAllOK, s] = mocha ('set', pvInput, val); +% may be called; +% mocha('setScalarArray') will then be called internally + + +[isAllOK, s] = mocha ('set', pvInput, val); + +if isAllOK ~= 1 + for n=1:length(s) + if s(n) ~= 1 + [codes,ctext]=mocha('getStatus', pvInput(n)); + X=['SET: Error in Elem.:', num2str(n), pvInput(n), ':']; + Y=[num2str(codes), ctext(1)]; + disp(X); disp(Y); + end + end +end + +%END (6) Multiple Scalar Operations, i.e., operations on several PVs with scalar values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(7) Multiple cell array ('compound') operations, i.e., on several PVS with scalar/vector values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (7) Multiple cell array ("compound") operations, i.e., on several PVS with scalar/vector values'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + +%GET +%Note the use of the handles; one could equally use the PV array, pv +[val, isAllOK, s] = mocha ('getCellArray', hpv); +%returns a cell array, wherein the elements are of native data type and can be of any size + +%SET +val{1}=1.111; +val{2}=2.222; +val{3}=(1:256); %wf +val{4}='on'; %mbbo +[isAllOK, s] = mocha ('set', hpv, val{:}); + +%Here, the data type of all returned values is defined to be a string +[val, isAllOK, s] = mocha ('getCellArray', hpv, 'string') + +%END (7) Multiple Scalar Operations, i.e., operations on several PVs with scalar values +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(8) Multiple Struct operations on several PVS returning PVData Objects plus Multiple Sets for Scalars/Vectors +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section (8) Multiple Struct operations on several PVS returning PVData Objects plus Multiple Sets for Scalars/Vectors'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%GET +%returns a sequence of pvData structs +[pvData, isAllOK] = mocha ('getPVArray', pv) +disp('Display all pvData.val values and statuses:'); +%pvData(i) corresponds to the data returned by pv(i) +{pvData.val} +[pvData.status] +%pvData(1:6).ts %timestamps +%[pvData(1:6).alarmStatus] +%[pvData.alarmSeverity] + +%Note: the following method is equivelent to the above +%as it will call getPVArray internally +[pvData, isAllOK] = mocha ('getPV', pv); + + +%returns a sequence of extended (x) pvData structs +[pvStruct, isAllOK] = mocha ('getStructArray', pv) +%pvStruct(i) corresponds to the data returned by pv(i) +disp('Display all pvStruct as arrays:'); +[pvStruct.handle] +{pvStruct.pv} +{pvStruct.val} +[pvStruct.status] +{pvStruct.status_str} +[pvStruct.alarmStatus] +[pvStruct.alarmStatus_str] +[pvStruct.alarmSeverity] +{pvStruct.alarmSeverity_str} +pvStruct.ts +pvStruct.epicsTS +[pvStruct.alarmSeverity] +{pvStruct.alarmSeverity_str} +%pvStruct(1:6).ts %timestamps +%[pvStruct(1:6).alarmStatus] + +%Note: the following method is equivelent to the above +%as it will call getStructArray internally +[pvStruct, isAllOK] = mocha ('getStruct', pv); + + +disp('Alternatively part data (values, statuses only) could also be retrieved with getCellArray:'); +[val, isAllOK, s] = mocha ('getCellArray', hpv) + +%SET +pvData(1).val =0.2345; +pvData(2).val =2.6789; +pvData(3).val =(256:512); +pvData(4).val = 'off'; +[isAllOK, s] = mocha ('set', hpv, pvData(1:6).val); +%Check values were set +[val, isAllOK, s] = mocha ('getCellArray', hpv) +disp('Recall we had previously set an offset for wf of value:'); +offset=mocha('getOffset',hpv(3)) +disp('Setting new offset/nelem for wf has value:'); +offset=mocha('setOffset',hpv(3),0) +%nelem =mocha('setNelem',hpv(3), mocha('getnelemnative',hpv(3)) ) +nelem =mocha('setNelem',hpv(3),10); +disp('Note that setNelem and setOffset are for readback of waveform only'); +%SET +%Another way to set +dd{1} = 3.33; +dd{2} = uint8(4); +dd{3} = [1,2,3,4,5,6,7,8,9,10,11,12,2.6,2.7,2.8,2.9,3.0,3.1,3.2,3.3]; %(2:257); % +dd{4} = 'off'; +dd{5} = 'Enable or Dis-enable BPM'; +dd{6} = 0; +[isAllOK,s] = mocha ('setMany', pv(1:5), dd{1:5}); +%or this will call setMany +dd{4} = 'on'; +[isAllOK,s] = mocha ('set', pv(1:5), dd{1:5}); +%Check values were set +[pvData, isAllOK] = mocha ('getPVArray', hpv(1:5)); +{pvData.val} +pvData(3).val +%END (8) Multiple Struct operations on several PVS returning PVData Objects plus Multiple Sets for Scalars/Vectors +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(9) Asynchronous interactions and retrieving data from Cache +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(9) Asynchronous interactions and retrieving data from Cache'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%GET +%Messages are aggregated until the user decides when to send the messages +%Note that there is no variable for the return data! This will be retrieved +%later through the getCache method + [s] = mocha ('getAsyn', pv(1)); +[isAllOK,s] = mocha ('getAsyn', pv(2:5)); +%Now send the messages +mocha('sendNow'); %optional; otherwise 'getCache' will do the send +%or mocha('caFlush'); + +%getCache methods are used to retrieve the data; +%methods will wait until any outstanding callback is complete or a timeout is reached +[val, s] = mocha('getCache', pv(1), 'double'); + pvData = mocha('getCache', pv(2)); +%get several pvs in one call +[val, isAllOK, s] = mocha('getScalarArrayCache', pv, 'string'); +%or getCache will call getScalarArrayCache +[val, isAllOK, s] = mocha('getCache', pv, 'string') +[val, isAllOK, s] = mocha('getCellArrayCache', pv) +[pvData, isAllOK] = mocha('getPVArrayCache', pv) +%return extended pvStruct +[pvStruct, isAllOK] = mocha('getStructArrayCache', pv) +%SET +%Set messages are by default asynchronous and non-blocking. +%The user may configure any given handle such that the messages are blocking, +%meaning a subsequent set method will wait until the server has reported back to the client: +%BLOCKING: +mocha('setPutWait', pv); %policy changed to blocking for all handles pv(1:6) +status = mocha ('set', pv(1), 0.1); %blocks, status may return a timeout error +%NON_BLOCKING - this is the default +mocha('setPutNoWait', pv); %policy changed to non-blocking for all handles pv(1:6) +status = mocha ('set', pv(1), 0.2); %blocks, status will never return a timeout error +%Want to be sure the value got written? +disp('Executing setAndGet; Return val should equal input value, i.e., 0.3'); +[val, status]= mocha('setAndGet', pv(1), 0.3) %val will be 0.3 on success. +%The above method initiates a set followed immediately by a get. +%The user should be aware that in the event of other applications writing +%to the same epics channel, the possibility exists that this external write +%may occur between the set and subsequent get in the above method. +%The data type of the returned value matches that of the input value. + +%AGGREGATING ASYNCHRONOUS SET OPERATIONS - Can be ignored as user case is expected to be uncommon +%If required set methods can also be aggregated before being sent asynchronously over the network +dd{1} = double(3.3); +dd{2} = uint8(4); +dd{3} = [11,12,13,14,15,6,7,8,9,10,11,12,2.6,2.7,2.8,2.9,3.0,3.1,3.2,3.3]; %(2:257); % +dd{4} = 'off'; +dd{5} = 'Enable or Dis-enable BPM'; +dd{6} = 0; + +mocha('setPutPrepare', pv(1:6)); +s = mocha ('set', pv(1), dd{1}); +s = mocha ('set', pv(2), dd{2}); +s = mocha ('set', pv(3), dd{3}); +s = mocha ('set', pv(4:5), dd{4:5}); +s = mocha ('set', pv(6), dd{6}); +mocha('sendNow'); + +%Note that a subsequent set on the same given channel +%will trigger a 'send' to IOC transaction on the pending set +mocha('setPutPrepare', pv(1:6)); +s = mocha ('set', pv(1), dd{1}); +s = mocha ('set', pv(1), 0.2); %will first trigger a send of the previous 'set' +[val,s]=mocha('get', pv(1)) %a get method will also initiate a send of all previous messages + +%Reset Policy - Remember to reset the policy, e.g., to asynchronous, blocking +mocha('setPutWait', pv); +%or +%Reset Policy - Remember to reset the (default) policy, e.g., to asynchronous, non-blocking, non-aggregating +mocha('setPutNoWait', pv); + +%END (9) Asynchronous interactions and retrieving data from Cache +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(10) Synchronous Group Operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(10) Synchronous Group Operations'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +% +%Uses the ca_sg functionality which guarantees a set of ca requests have completed, or a timeout is reached +%First define a group; here a simple group of two BPMs +s = mocha('defineGroup', 'gBPM', pv(1:2)); +%First define a group; here a collection of non-related pvs +s = mocha('defineGroup', 'gSnapshot', pv(1:5)); +%Open a group; optional, otherwise first get/set method will establish the connections +gHandle1 = mocha('openGroup', 'gBPM'); +gHandle2 = mocha('openGroup', 'gSnapshot'); + +%A synchronous group can be regarded as a logical software unity; +%*** A pv within a group will have its own, separate handle *** +%as revealed from within the following command +mocha('printHandles'); +%or +[hArray, pvArray]=mocha('getHandles'); +%For example, three ca virual circuits have thus been created for pv(1) +%as this pv exists in its own right, within group 'gBPM' and within group 'gSnapshot' +%Likewise two ca virtual circuits have been created for the waveform in pv(3) +%The various handles for the given pv may be configured independently +%e.g. In the following we will set the nelem for pv(3) (hpv(3)) to 6 +% and the the nelem for pv(3) within the group 'gSnapshot' to 12 +newNelem=mocha('setNelem', pv(3), 6); %corresponds to handle for pv(3) +%set nelements for handle withing group for pv(3) to 12 +handlesWithinGroup=mocha('getHandlesWithinGroup', gHandle2); +newNelem=mocha('setNelem', handlesWithinGroup(3), 12); %handlesWithinGroup(3) corresponds to pv(3) in group 'gSnapshot' +disp('pv(3) should have been read with 6 elements:') +[val,s]=mocha('get', pv(3)); +val +disp('pv(3) should have been read with 12 elements:') +[val,s]=mocha('get', handlesWithinGroup(3)); +val + + +[pvData1, isAllOK] = mocha('getPVGroup', 'gBPM'); %2nd argument could equally have been the group handle, i.e., gHandle1 +[pvData2, isAllOK] = mocha('getPVGroup', gHandle2); %2nd argument could equally have been the group name, i.e., 'gSnapshot' + +%To retrieve extended PVData; +[pvStruct, isAllOK] = mocha('getStructGroup', 'gBPM'); + +%pvData is an array of returned s +pvData2.val +pvData2.status; % int32 +pvData2.alarmStatus; %int16 +pvData2.alarmSeverity; %int16 +pvData2.ts; %[year, month, day, hour, min, sec, nsec] + + +mocha('get',handlesWithinGroup(3)) + +pvData2(3).val=(1:256); +[isAllOK,s]=mocha('setGroup', gHandle2, pvData2.val); +%reset to 256 +mocha('setNelem', handlesWithinGroup(3), 256) +mocha('get',handlesWithinGroup(3)) + + +%Configuring groups through XML - See documentation/talk for XML format +%Here the test.xml contains a group consistimng of 2 BPMs +mocha('loadXMLGroups', 'test.xml'); + +%List Groups and group Members +disp('listGroups:'); +[groups] = mocha('listGroups') +disp('Show members of group gSnapshot:'); +[members]= mocha('listGroupMembers', 'gSnapshot') +disp('Show members of group gTest (as loaded from test.xml):'); +[members]= mocha('listGroupMembers', 'gTest') +%This will only CLOSE and remove groups that have already been OPENED! +%%for i =1:length(groups) +%%mocha('closeGroup', groups{i}) +%%end + +%END (10) Synchronous Group Operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%(11) Monitors, either with or without user supplied callbacks (in essence, matlab scripts) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(11) Monitors, either with or without user supplied callbacks (in essence, matlab scripts'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%Simple Monitors +monitorID = mocha ('monitor', pv(1)); +[monitorIDArray, isAllOK, statusArray] = mocha ('monitor', pv(1:6)); %start monitors for several pvs/handles +%Once the monitor is started, data may be retrieved via one of the cache methods + +[val,s] = mocha('getCache', pv(1)); %Scalar or vector returned in native data type +[val,s] = mocha('getCache', pv(1), 'double'); %Scalar or vector returned as a MATLAB double +[val,s] = mocha('getCache', pv(1), 'uint8'); %Scalar or vector returned as a MATLAB uint8 + + +[pvData] = mocha('getPVCache', pv(1)) %PVData Object returned with pvData.val in native data type +[pvData] = mocha('getPVCache', pv(1), 'single'); %PVData Object returned with pvData.val as a MATLAB float +[pvData] = mocha('getPVCache', pv(1), 'int32'); %PVData Object returned as a MATLAB int32 + +[pvStruct] = mocha('getStructCache', pv(1)) %Extended (x) mocha closepvData + +s = mocha('monitorStop', pv(1), monitorID); %Stop monitor for pv/handle with given monitorID +s = mocha('monitorStop', pv(1)); %Stop all monitors for this pv/handle +s = mocha('monitorStop', pv(1:6)); %Stop all monitors for these pvs/handles +s = mocha('monitorStop'); %Stop all monitors for all pvs/handles + + +%Monitors with Actions, i,e, callback of MATLAB script + +%Need to give the numeric value of the handle as input argument to monitorAction +monAction=['monitorAction(', num2str(hpv(1)), ')'] ; +%The above reads monAction = 'monitorAction(1)' +%Here monitorAction(1) refers to a Matlab Script monitorAction.m +%that takes a single input argument, which is the handle of the monitored channel + +monitorID= mocha('monitor',hpv(1),monAction); + +%Mulitple monitors with actions: +%monAction2=['monitorAction(', num2str(hpv(2)), ')'] ; +%[monitorID] = mocha('monitor', hpv(1:2), monAction, monAction2); + +%The monitorAction.m script will typically retrieve data from Cache as follows: +%[val,status]=mocha ('getCache', varargin{1}); + +mocha('monitorFlushEvent', pv(1)); %will execute the MATLAB script monitorAction.m if new data has arrived +mocha('monitorFlushEvent'); %will execute all 'actions' for all 'handles' that have received new data + +%The above command is used in conjunction with MATLAB timer (as for MCA's mcamontimer.m) +obj.t = timer('TimerFcn', 'mocha(''monitorFlushEvent'')', 'Period', 2.0, 'ExecutionMode', 'fixedSpacing'); +%Else if double quotes cannot be used in the above; here's a way around the problem: +%obj.t = timer('TimerFcn', 'mocha(402)', 'Period', 2.0, 'ExecutionMode', 'fixedSpacing'); +start(obj.t); +disp ('Callback for monitors for 5 seconds') +for n=1:5 + mocha('set', pv(1), n); %See the script be executed + pause(1); +end +stop(obj.t); + +%END Monitors, either with or without user supplied callbacks (in essence, matlab scripts) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (12) Control system parameters, i.e. operating limits, engineerimg units +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(12) Control system parameters, i.e. operating limits, engineerimg units'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +[ctrlData] = mocha('getCtrl', hpv(1)); +%Usually it is sufficient to use the getCtrlCache method +[ctrlData] = mocha('getCtrlCache', hpv(1)); +ctrlData +% This is what an output may look like for an ao/ai record +%{ + handle: 1 + pv: 'ARIDI-BPM-01LE:X-AVG' + val: 3.2000 + status: 1 + alarmStatus: 0 + alarmSeverity: 0 + precision: 6 + units: 'mm' + noEnumStrings: 0 + enumStrings: {1�0 cell} + upperDisplayLimit: 2 + lowerDisplayLimit: -2 + upperAlarmLimit: NaN + lowerAlarmLimit: NaN + upperWarningLimit: NaN + lowerWarningLimit: NaN + upperControlLimit: 2 + lowerControlLimit: -2 +%} +[ctrlData] = mocha('getCtrlCache', hpv(4)); +ctrlData +% This is what an output may look like for an mbbo/i record +%{ + handle: 2 + pv: 'ARIDI-BPM-01LE:SET-ENABLE' + val: 'off' + status: 1 + alarmStatus: 0 + alarmSeverity: 0 + precision: 0 + units: '' + noEnumStrings: 3 + enumStrings: {'off' 'on' 'monitor'} + upperDisplayLimit: 0 + lowerDisplayLimit: 0 + upperAlarmLimit: 0 + lowerAlarmLimit: 0 + upperWarningLimit: 0 + lowerWarningLimit: 0 + upperControlLimit: 0 + lowerControlLimit: 0 +%} + +% +%END (12) Control system parameters, i.e. operating limits, engineerimg units +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (13) Retrieve channel medadata, e.g., data type, native no. elements, connection state, read/write access, etc. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(13) Retrieve channel medadata, e.g., data type, native no. elements, connection state, read/write access, etc. '); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + +iStruct=mocha('getInfo', pv(1)); +iStruct +% This is what an output may look like: +% The members connectFlag, accessRead, and accessWrite are all of MATLAB data type, logical +%{ + handle: 1 + pv: 'ARIDI-BPM-01LE:X-AVG' + channelID: '0x7f46fc879ae0' + connectFlag: 1 + hostName: 'psi-softioc-2.psi.ch:45408' + dataType: 'DBR_DOUBLE' + className: 'ai' + accessRead: 1 + accessWrite: 1 + nelem: 1 + connectionState: 'CA_OP_CONN_UP' +%} + +% +%END (13) Retrieve channel medadata, e.g., data type, native no. elements, connection state, read/write access, etc. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (14) Setting timeouts for set/get operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(14) Setting timeouts for set/get operations'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +%Timeouts in CAFE are self-regulating and are regulated by +%the following parameters in defines.h in the CAFE livrary +%const bool DEFAULT_SELF_GOVERNING_TIMEOUT = true; +%const unsigned short DEFAULT_PEND_IO_NO_TRIES = 2; +%const double DEFAULT_PEND_IO_INCREMENT_TIME = 2.0; + +%Self governing timeouts may be turned off/on for all handles, +%or on a per handle basis + +%Make true (default) for handle hpv(1) +mocha('setselfgoverningtimeout', pv(1), true); + +%Make true for all handles +mocha('setselfgoverningtimeout', true); + + +%Timeouts can be set separately for blocking SET/GET operations +%either globally or on a per handle basis +[t] = mocha('getTimeout', pv(1)); +%t(1) is timeout for a blocking put operation +%t(2) is timeout for a blocking get operation + +%the minimum timeout is returned from among all handles +[t] = mocha('getTimeout'); +%t(1) is minimum put timeout from among all handles +%t(2) is minimum get timeout from among all handles + +%Timeouts can be set in a number of ways, for all handles +%or on a per handle basis + +%set both put and get timeouts for handle hpv(1) to 10.0 seconds +status=mocha('setTimeout', pv(1), 10.0); + +%set both put and get timeouts for all handles to 10.0 seconds +status=mocha('setTimeout', 10.0); + +%set put timeout for handle hpv(1) to 5.0 seconds +status=mocha('setTimeoutPut', pv(1), 5.0); + +%set put timeouts for all handles to 5.0 seconds +status=mocha('setTimeoutPut', 5.0); + +%set get timeout for handle hpv(1) to 10.0 seconds +status=mocha('setTimeoutGet', pv(1), 10.0); + +%set put timeouts for all handles to 10.0 seconds +status=mocha('setTimeoutGet', 10.0); + +% +%END (14) Setting timeouts for set/get operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (15) Setting synchronous group timeouts for set/get operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(15) Setting synchronous group timeouts for set/get operations'); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + +%Self governing timeouts may be turned off/on for all group handles, +%or on a per group handle basis + +%Make true (default) for handle hpv(1) +mocha('setSGselfgoverningtimeout', gHandle1, true); + +%Make true for all handles +mocha('setSGselfgoverningtimeout', true); + + +%Timeouts can be set separately for blocking SET/GET operations +%either globally or on a per grop handle basis +[t] = mocha('getSGTimeout',gHandle1); +%t(1) is timeout for a group put operation +%t(2) is timeout for a grop get operation + +%the minimum timeout is returned from among all handles +[t] = mocha('getSGTimeout'); +%t(1) is minimum put timeout from among all group handles +%t(2) is minimum get timeout from among all group handles + +%Timeouts can be set in a number of ways, for all gourp handles +%or on a per grop handle basis + +%set both put and get timeouts for group handle, gHandle1, to 10.0 seconds +status=mocha('setSGTimeout', gHandle1, 10.0); + +%set both put and get timeouts for all group handles to 10.0 seconds +status=mocha('setSGTimeout', 10.0); + +%set put timeout for group handle, gHandle1, to 5.0 seconds +status=mocha('setSGTimeoutPut', gHandle1, 5.0); + +%set put timeouts for all group handles to 5.0 seconds +status=mocha('setSGTimeoutPut', 5.0); + +%set get timeout for group handle, gHandle1, to 10.0 seconds +status=mocha('setTimeoutGet', gHandle1, 10.0); + +%set put timeouts for all group handles to 10.0 seconds +status=mocha('setSGTimeoutGet', 10.0); + +% +%END (15) Setting synchronous group timeouts for set/get operations +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (16) Special Methods, e.g., setAndGet +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(16) Special Methods, e.g., setAndGet, setAndMatch '); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + + +%%Several specialized methods exist within the CAFE library, +%%such as setAndMatch which can set a number of PVs to a given value +%%and then examines a given collection of readback PVS. +%%Method verifies whether or not the set/readback values agree within +%%the given tolerance and timeout. Useful for, e.g., ID Gap Scans, +%%Other specialized methods can be exposed to mocha on request + +% \brief Set Channels followed by a corresponding readback of Channels +% Method verifies whether or not the set/readback values agree within +% the given tolerance and timeout. ICAFE_NORMAL is returned as soon as +% a match is reached else ECAFE_TIMEOUT_SET_AND_MATCH if timeout. +% \param 1 input: 'setAndMatch' +% \param 2 input: array of handles/pvs to set +% \param 3 input: array of values to set +% \param 4 input: array of handles/ov of readback channel +% \param 5 input: tolerance (+-) margin +% \param 6 input: timeout value; maximum time allowed for agreement to occur +% \param 7 input: printFlag bool, set to true for diagnostics +% \return ECA_NORMAL if all OK else first ECAFE error encountered, else +% ECAFE_TIMEOUT_SET_AND_MATCH if timeout + +% For the purpose of this example, the readbnack channels are the same as +% the input channels thus ensuring that a match is found +status=mocha ('setAndMatch', pv(1:2), [1.1,2.2], pv(1:2), 0.01, 5.0, true); + +%%Another simple method is the setAndGet Method +%%Set a PV and immediately retrieve its value + +%The method (previously presente in (9) above, initiates a set and is +%followed immediately by a get. +%The user should be aware that in the event of other applications writing +%to the same epics channel, the possibility exists that this external write +%may occur between the set and subsequent get within the 'setAndGet'. + +setValue=0.4; +[getValue, status] = mocha ('setAndGet', pv(1), setValue) +%The data type of the returned value matches that of the input value. + +% +%END (16) Special Methods, e.g., setAndGet +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% (17) Gracefully terminate CAFE +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); +disp('Section(17) Gracefully terminate CAFE '); +disp('%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'); + + +%Stops all monitors (if any) +%Closes all channels +%Releases all CA resources +mocha ('close'); + +% +%END (17) Gracefully terminate CAFE +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + diff --git a/macchinetta.h b/macchinetta.h new file mode 100644 index 0000000..3bf6fd4 --- /dev/null +++ b/macchinetta.h @@ -0,0 +1,10 @@ +/* Header for the wrapper. + Contains the function signature of (wrapper) machinettaFunction such that we can use this header + in the MEX-file to call the function in the (wrapper) machinetta library. +*/ +#include "mex.h" + + +#define MACCHINETTA_API extern + +MACCHINETTA_API void macchinettaFunction(int nlhs,mxArray *[],int nrhs, const mxArray *prhs[]); diff --git a/macchinettaHelper.h b/macchinettaHelper.h new file mode 100644 index 0000000..8e71a58 --- /dev/null +++ b/macchinettaHelper.h @@ -0,0 +1,2052 @@ +#include +#include "macchinetta.h" +#include "containerMochaccino.h" + +namespace NS_MOCHA { + +using boost::multi_index_container; +using namespace boost::multi_index; + + +const unsigned short METHOD_NAME_MAX_SIZE=80; +const unsigned short PVNAME_MAX_SIZE=80; + +const unsigned short MONITOR_ACTION_MAX_SIZE=255; +const unsigned short ME_MESSAGE_MAX_SIZE=255; + +CAFE cafe; +CAFEGlobalAlarmCondition cgac; +CAFEGlobalAlarmSeverity cgas; + + +bool isCAInitialized=false; +bool collectionsLoaded=false; +bool groupsLoaded=false; + +bool reportError=false; + +bool withExceptions=false; + +size_t neWithinAllDataCells=0; + +size_t neWithinAllCells=0; +size_t iWithinAllCells=0; +dbr_string_t * inputStringCell; +pv_string_t * inputPVStringCell; + +//Declarations +mxArray *mData; +mxArray *xData; +mxArray *yData; +mxArray *zData; + +mxLogical *logicalData; + + +int32_T * longStatus; +int64_T * longlongStatus; +int16_T * shortAlarmStatus; +int16_T * shortAlarmSeverity; + +epicsTimeStamp ets1; +uint32_T * d4; +uint32_T * d9; +uint32_T * fHandle; + +uint8_T * ucharArray; +uint16_T * ushortArray; +uint32_T * ulongArray; +uint64_T * ulonglongArray; +int8_T * charArray; +int16_T * shortArray; +int32_T * longArray; +int64_T * longlongArray; +float * floatArray; +double * doubleArray; + +bool * inputBool; +int8_T * inputChar; +float * inputFloat; +int16_T * inputShort; +double * inputDouble; +int32_T * inputLong; +int64_T * inputLongLong; + +uint8_T * inputUChar; +uint16_T * inputUShort; +uint32_T * inputULong; +uint64_T * inputULongLong; + +uint32_T * handleULong; +uint64_T * handleULongLong; + +uint32_T * handleULongReadback; + +dbr_string_t * stringArray; + + +//Ctrl +uint16_T * precision; +uint16_T * noEnumStrings; +double * udl; +double * ldl; +double * ual; +double * lal; +double * uwl; +double * lwl; +double * ucl; +double * lcl; + +int32_T status=ECA_NORMAL;; + +int32_T pvLength; +int32_T messLength; +int32_T MELength; + + +char acceleratorBase[PVNAME_MAX_SIZE]; + +char groupName[PVNAME_MAX_SIZE]; // +char pv[PVNAME_MAX_SIZE]; // +char mess[METHOD_NAME_MAX_SIZE]; // open get set close +char monAction[MONITOR_ACTION_MAX_SIZE]; // open get set close +char MEmess[METHOD_NAME_MAX_SIZE]; // open get set close + +mwSignedIndex nelem; + +double * dd; + +uint32_T handle=0; +uint32_T ghandle=0; + +uint32_T monitorID=0; + +int16_T nfieldsInfo=11; +int16_T nfieldsME=5; +int16_T nfields=5; +int16_T nfieldsExtra=11; +int16_T nfieldsCtrl=21; + +const char * fnamesInfo[11] ={"handle","pv","channelID","connectFlag","hostName","dataType", +"className","accessRead", "accessWrite","nelem","connectionState"}; + + +const char * fnamesME[5] ={"pv","handle","status","statusText","statusInfo"}; +const char * fnames[5] ={"val","status","alarmStatus","alarmSeverity","ts"}; +const char * fnamesExtra[11] ={"handle","pv","val","status","status_str","alarmStatus","alarmStatus_str", + "alarmSeverity","alarmSeverity_str","ts","epicsTS"}; +const char * fnamesCtrl[21]={"handle","pv","val","status","status_str","alarmStatus","alarmStatus_str", + "alarmSeverity","alarmSeverity_str", + "precision","units","noEnumStrings","enumStrings", + "upperDisplayLimit","lowerDisplayLimit","upperAlarmLimit", "lowerAlarmLimit", + "upperWarningLimit","lowerWarningLimit","upperControlLimit","lowerControlLimit"}; + +mxArray *fout0; mxArray *fout1; mxArray *fout2; mxArray *fout3; mxArray *fout4; +mxArray *fout5; mxArray *fout6; mxArray *fout7; mxArray *fout8; mxArray *fout9; +mxArray *fout10; mxArray *fout11; mxArray *fout12; mxArray *fout13; mxArray *fout14; +mxArray *fout15; mxArray *fout16; mxArray *fout17; mxArray *fout18; +mxArray *fout1a; mxArray *fout2a; mxArray *fout3a; + +unsigned int nc=0,nr=0,nn=0; + +mochaccino_set ms; +mochaccino_set mdt; + +enum mdtIndex {MOCHA_NATIVE=0, MOCHA_CHAR, MOCHA_UCHAR, MOCHA_SHORT, MOCHA_USHORT, + MOCHA_INT, MOCHA_UINT, MOCHA_LONG, MOCHA_ULONG, + MOCHA_FLOAT, MOCHA_DOUBLE, MOCHA_STRING}; +//map Strings to Integers + +enum mochaIndex {SHOW=1, OPEN, OPEN_ARRAY, OPEN_WAIT, GET_OPEN_WAIT_TIME, + OPEN_WAIT_WITH_TIME,OPEN_WAIT_TIME_TO_DEFAULT, + OPEN_NOWAIT, OPEN_NOW, OPEN_NOW_AND_WAIT, OPEN_GROUP, + CLOSE, CLOSE_ARRAY, CLOSE_GROUP, CA_POLL, MEX_UNLOCK, MOCHA_VERSION, + WITH_EXCEPTIONS, HAVE_EXCEPTIONS, SEND_NOW, + GET=100, GET_INT8, GET_INT16, GET_INT32, GET_INT64, GET_UINT8, + GET_UINT16, GET_UINT32, GET_UINT64, GET_FLOAT, GET_DOUBLE, + GET_STRING, GET_CACHE, GET_ASYN, GET_SCALAR_ARRAY, + GET_SCALAR_ARRAY_CACHE, GET_ARRAY_ASYN, + GET_STRUCT_ARRAY, GET_STRUCT_ARRAY_CACHE, + GET_STRUCT_EXTENDED_ARRAY, GET_STRUCT_EXTENDED_ARRAY_CACHE, + GET_CELL_ARRAY, GET_CELL_ARRAY_CACHE, + GET_WF_AS_STRING, GET_WF_AS_STRING_CACHE, + GET_GROUP, GET_GROUP_CACHE, GET_GROUP_EXTENDED, GET_GROUP_EXTENDED_CACHE, + GET_STRUCT, GET_STRUCT_CACHE, GET_STRUCT_EXTENDED, GET_STRUCT_EXTENDED_CACHE, + GET_CTRL_STRUCT, GET_CTRL_CACHE, GET_ME_STRUCT, GET_CHANNEL_INFO, + FETCH_INDEX_OF_GROUP_MEMBER, FETCH_INDEX_OF_COLLECTION_MEMBER, + GET_STATUS=200, GET_STATUS_TEXT, GET_STATUS_INFO, IS_STATUS_TIMEOUT, + GET_ALARM, GET_ALARM_AS_STRING, + STATUS_AS_STRING, ALARM_STATUS_AS_STRING, ALARM_SEVERITY_AS_STRING, + STATUS_LIST, ALARM_STATUS_LIST, ALARM_SEVERITY_LIST, + GET_TIMESTAMP, GET_EPICS_TIMESTAMP, GET_PULSEID_FROM_TIMESTAMP, + GET_PULSEID_FROM_TIMESTAMP_GROUP, + GET_READ_ACCESS, GET_WRITE_ACCESS, + INIT_GET_SYNC_WITH_CALLBACK_DEFAULT,INIT_GET_SYNC_WITHOUT_CALLBACK, + SET=300, SET_AND_GET, SET_AND_MATCH, SET_SCALAR_ARRAY, SET_STRUCT_ARRAY, SET_GROUP, SET_PUT_PREPARE, + SET_PUT_WAIT, SET_PUT_NOWAIT, + GET_TIMEOUT, SET_TIMEOUT, SET_TIMEOUT_DEFAULT, + SET_TIMEOUT_PUT, SET_TIMEOUT_GET, SET_SELF_GOVERNING_TIMEOUT, + GET_SG_TIMEOUT, SET_SG_TIMEOUT, SET_SG_TIMEOUT_DEFAULT, + SET_SG_TIMEOUT_PUT, SET_SG_TIMEOUT_GET, SET_SG_SELF_GOVERNING_TIMEOUT, + SET_NELEM, SET_NELEM_CACHE, SET_OFFSET, + GET_NELEM_CLIENT, GET_NELEM_NATIVE, GET_NELEM_REQUEST, + GET_NELEM, GET_NELEM_CACHE, GET_OFFSET, + MONITOR=400, MONITOR_STOP, MONITOR_FLUSH_EVENT, + GET_MONITOR_HANDLES, GET_MONITOR_HANDLES_AND_ACTIONS, + IS_CONNECTED=500, ALL_CONNECTED, + PRINT_STATUS=600, PRINT_MONITORS, PRINT_HANDLE, PRINT_HANDLES, + PRINT_DISCONNECTED_HANDLES,GET_HANDLES,GET_HANDLE_STATES, + GET_HANDLES_WITHIN_GROUP, + GET_DISCONNECTED_HANDLES, GET_CONNECTED_HANDLES, + HANDLE_FROM_PV, PV_FROM_HANDLE, LIST_COLLECTIONS, LIST_COLLECTION_MEMBERS, + LIST_GROUPS, LIST_GROUP_MEMBERS, DEFINE_GROUP, + LOAD_XML_COLLECTIONS=900, LOAD_XML_GROUPS, LOAD_SF_GROUPS, GET_CHANNEL_LIST, + TEST=999 }; + +void msInsert() { + + ms.insert(mochaccino(SHOW, "show")); + ms.insert(mochaccino(OPEN, "open")); + ms.insert(mochaccino(OPEN_ARRAY, "openarray")); + ms.insert(mochaccino(CLOSE_ARRAY, "closearray")); + ms.insert(mochaccino(OPEN_WAIT, "openwait")); + ms.insert(mochaccino(GET_OPEN_WAIT_TIME, "getopenwaittime")); + ms.insert(mochaccino(OPEN_NOWAIT, "opennowait")); + ms.insert(mochaccino(OPEN_NOWAIT, "openprepare")); + ms.insert(mochaccino(OPEN_NOW, "opennow")); + ms.insert(mochaccino(OPEN_NOW_AND_WAIT, "opennowandwait")); + ms.insert(mochaccino(OPEN_WAIT_WITH_TIME, "setopenwaittime")); + ms.insert(mochaccino(OPEN_WAIT_TIME_TO_DEFAULT, "setopenwaittimetodefault")); + + ms.insert(mochaccino(OPEN_GROUP, "opengroup")); + ms.insert(mochaccino(CLOSE, "close")); + + ms.insert(mochaccino(CLOSE_GROUP, "closegroup")); + + ms.insert(mochaccino(CA_POLL, "capoll")); + ms.insert(mochaccino(MEX_UNLOCK, "mexunlock")); + ms.insert(mochaccino(MOCHA_VERSION, "version")); + + ms.insert(mochaccino(WITH_EXCEPTIONS, "withexceptions")); + ms.insert(mochaccino(WITH_EXCEPTIONS, "setexceptions")); + ms.insert(mochaccino(HAVE_EXCEPTIONS, "haveexceptions")); + ms.insert(mochaccino(SEND_NOW, "sendnow")); + ms.insert(mochaccino(SEND_NOW, "caflush")); + ms.insert(mochaccino(GET_ASYN, "getasyn")); + ms.insert(mochaccino(GET_ME_STRUCT, "getmestruct")); + + ms.insert(mochaccino(GET_WF_AS_STRING, "getcharasstring")); + ms.insert(mochaccino(GET_WF_AS_STRING_CACHE, "getcharasstringcache")); + ms.insert(mochaccino(GET_WF_AS_STRING, "getwfasstring")); + ms.insert(mochaccino(GET_WF_AS_STRING_CACHE, "getwfasstringcache")); + + ms.insert(mochaccino(GET_SCALAR_ARRAY, "getscalararray")); + ms.insert(mochaccino(GET_SCALAR_ARRAY_CACHE,"getscalararraycache")); + + ms.insert(mochaccino(GET_CELL_ARRAY, "getcellarray")); + ms.insert(mochaccino(GET_CELL_ARRAY_CACHE, "getcellarraycache")); + + ms.insert(mochaccino(GET_ARRAY_ASYN, "getarrayasyn")); + + //ms.insert(mochaccino(GET_STRUCT_ARRAY, "getstructarray")); + //ms.insert(mochaccino(GET_STRUCT_ARRAY_CACHE,"getstructarraycache")); + ms.insert(mochaccino(GET_STRUCT_ARRAY, "getpvarray")); + ms.insert(mochaccino(GET_STRUCT_ARRAY_CACHE,"getpvarraycache")); + + + ms.insert(mochaccino(GET_STRUCT_EXTENDED_ARRAY, "getstructarray")); + ms.insert(mochaccino(GET_STRUCT_EXTENDED_ARRAY_CACHE,"getstructarraycache")); + //ms.insert(mochaccino(GET_STRUCT_EXTENDED_ARRAY, "getpvxarray")); + //ms.insert(mochaccino(GET_STRUCT_EXTENDED_ARRAY_CACHE,"getpvxarraycache")); + + ms.insert(mochaccino(INIT_GET_SYNC_WITH_CALLBACK_DEFAULT, "usesyncgetwithdefaultcallback")); + ms.insert(mochaccino(INIT_GET_SYNC_WITHOUT_CALLBACK, "usesyncgetwithoutcallback")); + + ms.insert(mochaccino(GET, "get")); + ms.insert(mochaccino(GET_CACHE, "getcache")); + ms.insert(mochaccino(GET_UINT8, "getuint8")); + ms.insert(mochaccino(GET_UINT16, "getuint16")); + ms.insert(mochaccino(GET_UINT32, "getuint32")); + ms.insert(mochaccino(GET_UINT64, "getuint64")); + ms.insert(mochaccino(GET_INT8, "getint8")); + ms.insert(mochaccino(GET_INT16, "getint16")); + ms.insert(mochaccino(GET_INT32, "getint32")); + ms.insert(mochaccino(GET_INT64, "getint64")); + ms.insert(mochaccino(GET_FLOAT, "getfloat")); + ms.insert(mochaccino(GET_FLOAT, "getsingle")); + ms.insert(mochaccino(GET_DOUBLE, "getdouble")); + ms.insert(mochaccino(GET_STRING, "getstring")); + + //ms.insert(mochaccino(GET_STRUCT, "getstruct")); + //ms.insert(mochaccino(GET_STRUCT_CACHE, "getstructcache")); + ms.insert(mochaccino(GET_STRUCT, "getpv")); + ms.insert(mochaccino(GET_STRUCT_CACHE, "getpvcache")); + + ms.insert(mochaccino(GET_STRUCT_EXTENDED, "getstruct")); + ms.insert(mochaccino(GET_STRUCT_EXTENDED_CACHE, "getstructcache")); + //ms.insert(mochaccino(GET_STRUCT_EXTENDED, "getpvx")); + //ms.insert(mochaccino(GET_STRUCT_EXTENDED_CACHE, "getpvxcache")); + + ms.insert(mochaccino(GET_GROUP, "getgroup")); + ms.insert(mochaccino(GET_GROUP_CACHE, "getgroupcache")); + ms.insert(mochaccino(GET_GROUP, "getpvgroup")); + ms.insert(mochaccino(GET_GROUP_CACHE, "getpvgroupcache")); + ms.insert(mochaccino(GET_GROUP_EXTENDED, "getstructgroup")); + ms.insert(mochaccino(GET_GROUP_EXTENDED_CACHE, "getstructgroupcache")); + + ms.insert(mochaccino(GET_CTRL_STRUCT, "getctrl")); + ms.insert(mochaccino(GET_CTRL_CACHE, "getctrlcache")); + + ms.insert(mochaccino(FETCH_INDEX_OF_GROUP_MEMBER, "idxgrpmem")); + ms.insert(mochaccino(FETCH_INDEX_OF_COLLECTION_MEMBER, "idxcolmem")); + ms.insert(mochaccino(LIST_GROUPS, "listgroups")); + ms.insert(mochaccino(LIST_GROUP_MEMBERS, "listgroupmembers")); + ms.insert(mochaccino(LIST_COLLECTIONS, "listcollections")); + ms.insert(mochaccino(LIST_COLLECTION_MEMBERS, "listcollectionmembers")); + ms.insert(mochaccino(STATUS_AS_STRING, "statusasstring")); + ms.insert(mochaccino(ALARM_STATUS_AS_STRING, "alarmstatusasstring")); + ms.insert(mochaccino(ALARM_SEVERITY_AS_STRING, "alarmseverityasstring")); + + ms.insert(mochaccino(STATUS_LIST, "statuslist")); + ms.insert(mochaccino(ALARM_STATUS_LIST, "alarmstatuslist")); + ms.insert(mochaccino(ALARM_SEVERITY_LIST, "alarmseveritylist")); + + ms.insert(mochaccino(GET_STATUS, "getstatus")); + ms.insert(mochaccino(GET_STATUS_TEXT, "statusastext")); + ms.insert(mochaccino(GET_STATUS_INFO, "statusinfo")); + ms.insert(mochaccino(IS_STATUS_TIMEOUT, "istimeout")); + ms.insert(mochaccino(GET_ALARM, "getalarm")); + ms.insert(mochaccino(GET_ALARM_AS_STRING, "getalarmasstring")); + ms.insert(mochaccino(GET_TIMESTAMP, "gettimestamp")); + ms.insert(mochaccino(GET_EPICS_TIMESTAMP, "getepicstimestamp")); + ms.insert(mochaccino(GET_EPICS_TIMESTAMP, "getets")); + ms.insert(mochaccino(GET_PULSEID_FROM_TIMESTAMP, "getpulseidfromts")); + ms.insert(mochaccino(GET_PULSEID_FROM_TIMESTAMP_GROUP,"getgrouppulseidfromts")); + + ms.insert(mochaccino(GET_READ_ACCESS, "getreadaccess")); + ms.insert(mochaccino(GET_WRITE_ACCESS, "getwriteaccess")); + ms.insert(mochaccino(GET_CHANNEL_INFO, "getchannelinfo")); + ms.insert(mochaccino(GET_CHANNEL_INFO, "getinfo")); + + ms.insert(mochaccino(SET, "set")); + ms.insert(mochaccino(SET_AND_GET, "setandget")); + ms.insert(mochaccino(SET_AND_MATCH, "setandmatch")); + ms.insert(mochaccino(SET_SCALAR_ARRAY, "setscalararray")); + ms.insert(mochaccino(SET_STRUCT_ARRAY, "setstructarray")); + ms.insert(mochaccino(SET_STRUCT_ARRAY, "setpvarray")); + ms.insert(mochaccino(SET_STRUCT_ARRAY, "setmany")); + + + ms.insert(mochaccino(SET_GROUP, "setgroup")); + ms.insert(mochaccino(SET_PUT_PREPARE, "setputprepare")); + ms.insert(mochaccino(SET_PUT_WAIT, "setputwait")); + ms.insert(mochaccino(SET_PUT_NOWAIT, "setputnowait")); + ms.insert(mochaccino(SET_PUT_NOWAIT, "setputdefault")); + + ms.insert(mochaccino(GET_TIMEOUT, "gettimeout")); + ms.insert(mochaccino(SET_TIMEOUT, "settimeout")); + ms.insert(mochaccino(SET_TIMEOUT_PUT, "settimeoutput")); + ms.insert(mochaccino(SET_TIMEOUT_GET, "settimeoutget")); + ms.insert(mochaccino(SET_TIMEOUT_DEFAULT,"settimeoutdefault")); + ms.insert(mochaccino(SET_SELF_GOVERNING_TIMEOUT,"setselfgoverningtimeout")); + + ms.insert(mochaccino(GET_SG_TIMEOUT, "getsgtimeout")); + ms.insert(mochaccino(SET_SG_TIMEOUT, "setsgtimeout")); + ms.insert(mochaccino(SET_SG_TIMEOUT_PUT, "setsgtimeoutput")); + ms.insert(mochaccino(SET_SG_TIMEOUT_GET, "setsgtimeoutget")); + ms.insert(mochaccino(SET_SG_TIMEOUT_DEFAULT,"setsgtimeoutdefault")); + ms.insert(mochaccino(SET_SG_SELF_GOVERNING_TIMEOUT,"setsgselfgoverningtimeout")); + + ms.insert(mochaccino(SET_NELEM, "setnelem")); + ms.insert(mochaccino(SET_NELEM_CACHE,"setnelemcache")); + + ms.insert(mochaccino(SET_OFFSET, "setoffset")); + ms.insert(mochaccino(GET_NELEM_CLIENT, "getnelemclient")); + ms.insert(mochaccino(GET_NELEM_NATIVE, "getnelemnative")); + ms.insert(mochaccino(GET_NELEM_REQUEST, "getnelemrequest")); + ms.insert(mochaccino(GET_NELEM, "getnelem")); + ms.insert(mochaccino(GET_NELEM_CACHE,"getnelemcache")); + + ms.insert(mochaccino(GET_OFFSET, "getoffset")); + + ms.insert(mochaccino(MONITOR, "monitor")); + ms.insert(mochaccino(MONITOR_STOP, "monitorstop")); + ms.insert(mochaccino(MONITOR_FLUSH_EVENT, "monitorflushevent")); + + ms.insert(mochaccino(GET_MONITOR_HANDLES, "getmonitorhandles")); + ms.insert(mochaccino(GET_MONITOR_HANDLES_AND_ACTIONS, "getmonitorhandlesandactions")); + + ms.insert(mochaccino(IS_CONNECTED, "isconnected")); + ms.insert(mochaccino(ALL_CONNECTED, "allconnected")); + + ms.insert(mochaccino(PRINT_STATUS, "printstatus")); + ms.insert(mochaccino(PRINT_DISCONNECTED_HANDLES,"printdisconnectedhandles")); + ms.insert(mochaccino(GET_HANDLES, "gethandles")); + ms.insert(mochaccino(GET_HANDLE_STATES, "gethandlestates")); + ms.insert(mochaccino(GET_HANDLES_WITHIN_GROUP, "gethandleswithingroup")); + + ms.insert(mochaccino(GET_CONNECTED_HANDLES, "getconnectedhandles")); + ms.insert(mochaccino(GET_DISCONNECTED_HANDLES, "getdisconnectedhandles")); + ms.insert(mochaccino(PRINT_MONITORS, "printmonitors")); + ms.insert(mochaccino(PRINT_HANDLE, "printhandle")); + ms.insert(mochaccino(PRINT_HANDLES, "printhandles")); + ms.insert(mochaccino(HANDLE_FROM_PV, "gethandlefrompv")); + ms.insert(mochaccino(PV_FROM_HANDLE, "getpvfromhandle")); + ms.insert(mochaccino(DEFINE_GROUP, "definegroup")); + + ms.insert(mochaccino(LOAD_XML_COLLECTIONS,"loadxmlcollections")); + ms.insert(mochaccino(LOAD_XML_GROUPS, "loadxmlgroups")); + ms.insert(mochaccino(LOAD_SF_GROUPS, "loadsfgroups")); + ms.insert(mochaccino(GET_CHANNEL_LIST, "getchannellist")); + ms.insert(mochaccino(TEST, "test")); +} + +void mdtInsert() { + mdt.insert(mochaccino(MOCHA_NATIVE, "native")); + mdt.insert(mochaccino(MOCHA_CHAR, "int8")); + mdt.insert(mochaccino(MOCHA_UCHAR, "uint8")); + mdt.insert(mochaccino(MOCHA_SHORT, "int16")); + mdt.insert(mochaccino(MOCHA_USHORT, "uint16")); + mdt.insert(mochaccino(MOCHA_INT, "int32")); + mdt.insert(mochaccino(MOCHA_UINT, "uint32")); + mdt.insert(mochaccino(MOCHA_LONG, "int64")); + mdt.insert(mochaccino(MOCHA_ULONG, "uint64")); + mdt.insert(mochaccino(MOCHA_FLOAT, "single")); + mdt.insert(mochaccino(MOCHA_FLOAT, "float")); + mdt.insert(mochaccino(MOCHA_DOUBLE, "double")); + mdt.insert(mochaccino(MOCHA_STRING, "char")); + mdt.insert(mochaccino(MOCHA_STRING, "string")); +} + +void printStatus(int status ) { + string s = cafe.getCafeStatus().csi.message(status); + string c = cafe.getCafeStatus().csc.message(status); + mexPrintf("%s\n",c.c_str()); + mexPrintf("%s\n",s.c_str()); +} + + +string prepareExceptionID(int status ) { + string exID="CAFE_"; exID.append(cafe.getCafeStatus().severity(status)); + exID.append(":"); exID.append(cafe.getCafeStatus().msgID(status)); + return exID; +} + + +string prepareExceptionText(unsigned int handle, int status ) { + string exText="PV="; + exText.append(cafe.getPVFromHandle(handle)); + exText.append(" Handle="); + exText.append(static_cast( &(ostringstream() << handle) )->str()); + exText.append(" statusCode="); + exText.append(static_cast( &(ostringstream() << status) )->str()); + exText.append(" statusText="); exText.append(cafe.getCafeStatus().msgID(status)); + exText.append(" statusInfo="); exText.append(cafe.getCafeStatus().info(status)); + return exText; +} + + + +void fillMEStruct(string sME) { + + + fout1 = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData (fout1); + + fout2 = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData (fout2); + + fout0 = mxCreateCellMatrix(1,1); + fout3 = mxCreateCellMatrix(1,1); + fout4 = mxCreateCellMatrix(1,1); + + std::string str2 =""; + std::string str =""; + + std::size_t found = sME.find("PV="); + + if (found != string::npos) { + str2 = sME.substr(found+3); + found = str2.find(" "); + str = str2.substr(0,found); + mexPrintf("PV %s\n", str.c_str()); + mxSetCell (fout0, 0, mxCreateString( str.c_str())); + } + + + found= sME.find("Handle="); + if (found!= string::npos) { + str2 = sME.substr(found+7); + found = str2.find(" "); + str = str2.substr(0,found); + //mexPrintf("handle %d\n", std::atoi(str.c_str())); + ulongArray[0]= std::atoi(str.c_str()); + } + + found= sME.find("statusCode="); + if (found!= string::npos) { + + str2 = sME.substr(found+11); + found = str2.find(" "); + str = str2.substr(0,found); + //mexPrintf("status %d\n", std::atoi(str.c_str())); + longStatus[0]= std::atoi(str.c_str()); + } + + + found= sME.find("statusText="); + if (found!= string::npos) { + str2 = sME.substr(found+11); + found = str2.find(" "); + str = str2.substr(0,found); + //mexPrintf("statusText %s\n", str.c_str()); + mxSetCell (fout3, 0, mxCreateString(str.c_str())); + } + + found= sME.find("statusInfo="); + if (found!= string::npos) { + str2 = sME.substr(found+11); + //mexPrintf("statusInfo %s\n", str2.c_str()); + mxSetCell (fout4, 0, mxCreateString(str2.c_str())); + } + + return; + +} + + + +bool isValidClass(const mxArray * inputClass) { + // Refuse these input mx classes; + + mxClassID mxid =mxGetClassID( inputClass); + + switch(mxid) { + case mxUNKNOWN_CLASS: + mexPrintf("Undetermined class: %s \n",mxGetClassName( inputClass) ); + return false; + break; + case mxSTRUCT_CLASS: + case mxFUNCTION_CLASS: + mexPrintf("The requested class is not yet supported: %s \n",mxGetClassName( inputClass) ); + return false; + break; + case mxVOID_CLASS: + mexPrintf("This requested class is reserved: %s \n",mxGetClassName( inputClass) ); + return false; + break; + } + + return true; +} + +unsigned int getMdtIndexFromCafeDataType(CAFE_DATATYPE cdt){ + unsigned int mdtIndex; + + switch ( cdt) + { + case CAFE_DOUBLE: + mdtIndex=MOCHA_DOUBLE; + break; + case CAFE_FLOAT: + mdtIndex=MOCHA_FLOAT; + break; + case CAFE_SHORT: + mdtIndex=MOCHA_SHORT; + break; + case CAFE_ENUM: + mdtIndex=MOCHA_USHORT; + break; + case CAFE_CHAR: + mdtIndex=MOCHA_UCHAR; + break; + case CAFE_LONG: + mdtIndex=MOCHA_INT; + break; + case CAFE_STRING: + mdtIndex=MOCHA_STRING; + break; + default: //If not connected for instance + mdtIndex=MOCHA_DOUBLE; + break; + } + return mdtIndex; +} + +unsigned int getMdtIndex(const mxArray * l){ + + char messStruct[METHOD_NAME_MAX_SIZE]; + mxArray * mDataStruct; + + unsigned int mdtIndex=MOCHA_NATIVE; + + mochaccino_set_by_name & name_mdt_index = mdt.get (); + mochaccino_set_by_name::iterator it_name_mdt; + + short messLengthStruct = METHOD_NAME_MAX_SIZE+1; + //message + mDataStruct = (mxArray *) l; + mxGetString(mDataStruct, messStruct, messLengthStruct); + + //Not allowed! + //mxFree(mxGetData(mDataStruct)); // Added line to avoid memory leak + //mxDestroyArray(mDataStruct); + + //remove leadingTrailing Blanks + const char * _messStruct=messStruct; + cafe.getHandleHelper().removeLeadingAndTrailingSpaces(_messStruct,messStruct); + + //tolowercase + std::string messString = messStruct; + + if(messString.size()==0) {return mdtIndex;} + + std::transform(messString.begin(), messString.end(), messString.begin(), ::tolower); + strcpy(messStruct,messString.c_str()); + + //Is Valid Data Type?? + it_name_mdt = name_mdt_index.find(messStruct); + + if (it_name_mdt != name_mdt_index.end()) { + mdtIndex=(*it_name_mdt).id; + //mexPrintf("MESSAGE INDEX: %d %s ", mdtIndex, messStruct); + } + else { + mexPrintf("WARNING: Unknown data type: %s\n", messStruct); + mexPrintf("WARNING: Possible data types are listed. \n"); + mexPrintf("WARNING: Using native type if known else double\n"); + print_out_by(mdt); + } + + return mdtIndex; +} + + + +void scanCell(const mxArray * thisCell) +{ + + size_t thisNeWithinObject = mxGetNumberOfElements (thisCell); + for (mwIndex i=0; i openArray(vector vstr) { + + + vector vuint32; + vuint32.reserve(vstr.size()); + + std::fill(vuint32.begin(), vuint32.end(), 0); + + try { + cafe.open(vstr, vuint32); + } + catch(CAFEException_open &e) { + + mexPrintf("---------------\n"); + //cout << e.what() << endl; + mexPrintf("%s\n", e.what() ); + mexPrintf("---------------\n"); + + cafe.printCAFEException_pv(e.pvEx); + printStatus(e.pvEx.statusCode); + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + catch(exception &e) { + + mexPrintf("---------------\n"); + mexPrintf("%s\n", e.what() ); + mexPrintf("---------------\n"); + + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + return vuint32; +} + + + +unsigned int open(char _pv[PVNAME_MAX_SIZE]) { + + uint32_T _handle=0; + + try { + cafe.open(_pv, (unsigned int&) _handle); + } + catch(CAFEException_open &e) { + + mexPrintf("---------------\n"); + cout << e.what() << endl; + mexPrintf("---------------\n"); + + cafe.printCAFEException_pv(e.pvEx); + printStatus(e.pvEx.statusCode); + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + catch(exception &e) { + + mexPrintf("---------------\n"); + cout << e.what() << endl; + mexPrintf("---------------\n"); + + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + return _handle; +} + + +unsigned int groupOpen(char _pv[PVNAME_MAX_SIZE]) { + uint32_T _ghandle=0; + + try { + status=cafe.groupOpen((const char *) _pv, (unsigned int &) _ghandle); + } + catch(CAFEException_groupOpen &e) { + mexPrintf("---------------\n"); + cout << e.what() << endl; + mexPrintf("---------------\n"); + NS_MOCHA::printStatus(e.groupEx.statusCode); + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + catch(exception &e) { + mexPrintf("---------------\n"); + cout << e.what() << endl; + mexPrintf("---------------\n"); + mexPrintf("EXITING MATLAB\n"); + exit(1); + } + return _ghandle; +} + + + +unsigned int checkForHandleNoOpen(const mxArray * inputValue) { + + unsigned int _handle=0; + + if (mxIsNumeric(inputValue) ) { + _handle = (uint32_T) mxGetScalar(inputValue); + } + + else if (mxIsChar(inputValue) ) { + + //message pvname + xData = (mxArray *) inputValue; + + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(xData, pv, pvLength); + + _handle=cafe.getHandleHelper().getHandleFromPV(pv); + if (_handle==0) { + mexPrintf("PV=%s has not yet been opened by user!\n", pv ); + } + + } + else if (mxIsCell(inputValue) ) { + + mxArray * newCell = mxGetCell(inputValue,0); + + if (mxIsNumeric(newCell) ) { + _handle = (uint32_T) mxGetScalar(newCell); + } + + else if (mxIsChar(newCell) ) { + + //message pvname + xData = (mxArray *) newCell; + + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(xData, pv, pvLength); + + _handle=cafe.getHandleHelper().getHandleFromPV(pv); + if (_handle==0) { + mexPrintf("PV=%s has not yet been opened by user!\n", pv ); + } + } + + } + else { + mexPrintf("Error in checkForHandleNoOpen:\n"); + mexPrintf("Handle does not have a numeric value \n"); + mexPrintf("or PV name does not have a char value \n" ); + } + return _handle; +} + + + +unsigned int checkForHandle(const mxArray * inputValue) { + + unsigned int _handle=0; + + if (mxIsNumeric(inputValue) ) { + _handle = (uint32_T) mxGetScalar(inputValue); + + } + + else if (mxIsChar(inputValue) ) { + + //message pvname + xData = (mxArray *) inputValue; + + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(xData, pv, pvLength); + + _handle=cafe.getHandleHelper().getHandleFromPV(pv); + + if (_handle==0) { + _handle=open(pv); + } + } + else if (mxIsCell(inputValue) ) { + + mxArray * newCell = mxGetCell(inputValue,0); + + if (mxIsNumeric(newCell) ) { + _handle = (uint32_T) mxGetScalar(newCell); + } + + else if (mxIsChar(newCell) ) { + + //message pvname + xData = (mxArray *) newCell; + + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(xData, pv, pvLength); + + _handle=cafe.getHandleHelper().getHandleFromPV(pv); + + if (_handle==0) { + _handle=open(pv); + } + } + } + else { + mexPrintf("Error in checkForHandle:\n"); + mexPrintf("Handle does not have a numeric value \n"); + mexPrintf("or PV name does not have a char value \n"); + return _handle; + } + if (_handle==0) { + mexPrintf("Handle in input argument not given! \n"); + } + return _handle; +} + + +uint32_T * scanNumericForHandle (const mxArray * inputValue) { + + uint32_T * inputULong; + + if (mxIsNumeric(inputValue) ) { + + size_t numberOfHandles=mxGetNumberOfElements (inputValue); + mxArray * foutE = mxCreateNumericMatrix(1,numberOfHandles,mxUINT32_CLASS, mxREAL); + inputULong = (uint32_T *) mxGetData (foutE); + + mxClassID mxid =mxGetClassID(inputValue); + + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr ( inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputDouble[i]; + } + break; + case mxSINGLE_CLASS: + inputFloat = (float *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputFloat[i]; + } + break; + case mxLOGICAL_CLASS: + inputBool = (bool *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputBool[i]; + } + break; + case mxINT8_CLASS: + inputChar = (int8_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputChar[i]; + } + break; + case mxUINT8_CLASS: + inputUChar = (uint8_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputUChar[i]; + } + break; + case mxINT16_CLASS: + inputShort = (int16_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputShort[i]; + } + break; + case mxUINT16_CLASS: + inputUShort = (uint16_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputUShort[i]; + } + break; + case mxINT32_CLASS: + inputLong = (int32_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputLong[i]; + } + break; + case mxUINT32_CLASS: + inputULong = (uint32_T *) mxGetData (inputValue); + //for (size_t i=0; i< numberOfHandles; ++i) { + // inputULongLong[i] = (uint64_T) inputULong[i]; + //} + break; + case mxINT64_CLASS: + inputLongLong = (int64_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputLongLong[i]; + } + break; + case mxUINT64_CLASS: + inputULongLong = (uint64_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputULongLong[i]; + } + break; + // Series of Strings go in a CELL + } + } + else { + mexPrintf("scanNumericForHandle was not given a numeric for input!"); + mxArray * foutE = mxCreateNumericMatrix(1,1,mxUINT32_CLASS, mxREAL); + inputULong = (uint32_T *) mxGetData (foutE); + inputULong[0] = 0; + } + return inputULong; +} + +uint32_T * checkHandleArray(const mxArray * inputValue, bool openIfNoHandle) { + + uint32_T * inputULong; + mxArray * foutE; + size_t numberOfHandles=0; + + if (mxIsNumeric(inputValue) ) { + + numberOfHandles=mxGetNumberOfElements (inputValue); + + foutE = mxCreateNumericMatrix(1,std::max((int)numberOfHandles,1),mxUINT32_CLASS, mxREAL); + inputULong= (uint32_T *) mxGetData (foutE); + + mxClassID mxid =mxGetClassID(inputValue); + + //mexPrintf("Class ID %d\n", mxid ); + //mexPrintf(mxGetClassName(inputValue)); + + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr ( inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputDouble[i]; + } + break; + case mxSINGLE_CLASS: + inputFloat = (float *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputFloat[i]; + } + break; + case mxLOGICAL_CLASS: + inputBool = (bool *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputBool[i]; + } + break; + case mxINT8_CLASS: + inputChar = (int8_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputChar[i]; + } + break; + case mxUINT8_CLASS: + inputUChar = (uint8_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputUChar[i]; + } + break; + case mxINT16_CLASS: + inputShort = (int16_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputShort[i]; + } + break; + case mxUINT16_CLASS: + inputUShort = (uint16_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputUShort[i]; + } + break; + case mxINT32_CLASS: + inputLong = (int32_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputLong[i]; + } + break; + case mxUINT32_CLASS: + inputULong = (uint32_T *) mxGetData (inputValue); + + break; + case mxINT64_CLASS: + inputLongLong = (int64_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputLongLong[i]; + } + break; + case mxUINT64_CLASS: + inputULongLong = (uint64_T *) mxGetData (inputValue); + for (size_t i=0; i< numberOfHandles; ++i) { + inputULong[i] = (uint32_T) inputULongLong[i]; + } + break; + // Series of Strings go in a CELL + } + + //for (size_t i=0; i::quiet_NaN()); + + //foutE = mxCreateDoubleMatrix(1,1,mxREAL); + //doubleArray = (double *) mxGetPr ( plhs[0]); + //doubleArray[0]=numeric_limits::signaling_NaN(); + break; + case MOCHA_FLOAT: + foutE = mxCreateNumericMatrix(1,1,mxSINGLE_CLASS, mxREAL); + floatArray = (float *) mxGetData (foutE); + floatArray[0]=numeric_limits::quiet_NaN(); + break; + case MOCHA_INT: + foutE = mxCreateNumericMatrix(1,1,mxINT32_CLASS, mxREAL); + longArray = (int32_T *) mxGetData (foutE); + longArray[0]=numeric_limits::quiet_NaN(); + break; + case MOCHA_SHORT: + foutE = mxCreateNumericMatrix(1,1,mxINT16_CLASS, mxREAL); + shortArray = (int16_T *) mxGetData (foutE); + shortArray[0]=numeric_limits::quiet_NaN(); + break; + case MOCHA_USHORT: + foutE = mxCreateNumericMatrix(1,1,mxUINT16_CLASS, mxREAL); + ushortArray = (uint16_T *) mxGetData (foutE); + ushortArray[0]=numeric_limits::quiet_NaN(); + break; + case MOCHA_UCHAR: + foutE = mxCreateNumericMatrix(1,1,mxUINT8_CLASS, mxREAL); + ucharArray = (uint8_T *) mxGetData (foutE); + ucharArray[0]=numeric_limits::quiet_NaN(); + break; + case MOCHA_STRING: + foutE = mxCreateCellMatrix(1,1); + mxSetCell (foutE, 0, mxCreateString( numeric_limits::quiet_NaN() )); + break; + case MOCHA_CHAR: + foutE = mxCreateNumericMatrix(1,1,mxINT8_CLASS, mxREAL); + charArray = (int8_T *) mxGetData (foutE); + charArray[0]= numeric_limits::quiet_NaN(); + break; + case MOCHA_UINT: + foutE = mxCreateNumericMatrix(1,1,mxUINT32_CLASS, mxREAL); + ulongArray = (uint32_T *) mxGetData (foutE); + ulongArray[0]= numeric_limits::quiet_NaN(); + break; + case MOCHA_LONG: + foutE = mxCreateNumericMatrix(1,1,mxINT64_CLASS, mxREAL); + longlongArray = (int64_T *) mxGetData (foutE); + longlongArray[0]= numeric_limits::quiet_NaN(); + break; + case MOCHA_ULONG: + foutE = mxCreateNumericMatrix(1,1,mxUINT64_CLASS, mxREAL); + ulonglongArray = (uint64_T *) mxGetData (foutE); + ulonglongArray[0]= numeric_limits::quiet_NaN(); + break; + default: + foutE = mxCreateDoubleScalar(numeric_limits::quiet_NaN()); + break; + } + +return foutE; +} + + +void fillPVCell(unsigned int mdtIndex, PVDataHolder dh) { + + nelem= dh.getNelem(); + + switch ( mdtIndex) + { + case MOCHA_DOUBLE: + fout0 = mxCreateDoubleMatrix(1,nelem,mxREAL); + doubleArray = (double *) mxGetPr (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { doubleArray[i]=dh.getAsDouble(i);} + break; + + case MOCHA_FLOAT: + fout0 = mxCreateNumericMatrix(1,nelem,mxSINGLE_CLASS, mxREAL); + floatArray = (float *) mxGetData (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { floatArray[i]=dh.getAsFloat(i);} + break; + + case MOCHA_INT: + fout0 = mxCreateNumericMatrix(1,nelem,mxINT32_CLASS, mxREAL); + longArray = (int32_T *) mxGetData (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { longArray[i]=dh.getAsLong(i); } + break; + + case MOCHA_SHORT: + fout0 = mxCreateNumericMatrix(1,nelem,mxINT16_CLASS, mxREAL); + shortArray = (int16_T *) mxGetData (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { shortArray[i]=dh.getAsShort(i); } + break; + + case MOCHA_USHORT: + fout0 = mxCreateNumericMatrix(1,nelem,mxUINT16_CLASS, mxREAL); + ushortArray = (uint16_T *) mxGetData (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { ushortArray[i]=(unsigned short) dh.getAsEnum(i);} + break; + + case MOCHA_UCHAR: + fout0 = mxCreateNumericMatrix(1,nelem,mxUINT8_CLASS, mxREAL); + ucharArray = (uint8_T *) mxGetData (fout0); + for (mwSignedIndex i=0; i< nelem; ++i) { ucharArray[i]= (unsigned short) dh.getAsChar(i); } + break; + + case MOCHA_STRING: + { + //cells are best + + + if (nelem==1) { + fout0=mxCreateString(dh.getAsString(0).c_str() ); + } + else { + fout0 = mxCreateCellMatrix(1,nelem); + for (mwSignedIndex i=0; i +//#include +//#endif + + +extern void _main(); +using namespace NS_MOCHA; + +void macchinettaFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + + if (nrhs <1) { + mexPrintf("Input argument not entered. \n"); + mexPrintf("The command: mocha \'show\' will display the methods available. \n"); + return; + } + + if (mxIsCell(prhs[0])) { + mexPrintf("mocha message argument (1st input arg) must be a char and not a cell. \n"); + return; + } + + int32_T mochaIndex=-1; + + if ( mxIsNumeric(prhs[0]) && !mxIsChar(prhs[0]) ) { + mochaIndex= (int) mxGetScalar( prhs[0] ); + if (mochaIndex !=MONITOR_FLUSH_EVENT) { + mexPrintf("We prefer not to expose the numerical index value directly. \n"); + mexPrintf("Please use the method name (MATLAB char) as input to the first argument. \n"); + mexPrintf("The command: mocha \'show\' will display the methods available. \n"); + + mexPrintf("1st input argument Class Name: %s\n", mxGetClassName(prhs[0])); + mexPrintf("1st input argument Class ID: %d\n", mxGetClassID(prhs[0])); + mexPrintf("1st input argument to mocha must be of type char/mxCHAR_CLASS\n"); + + return; + } + } + + + /* + if (strcmp (mxGetClassName(prhs[0]),"string") ==0 ) { + + mxChar * mess2 = static_cast(mxGetData(prhs[0])); + + mData = (mxArray *) mess2; + messLength = METHOD_NAME_MAX_SIZE+1; + + if ( mxGetString(mData, mess, messLength) == 1) { + mexPrintf ("mxGetString has failed; input is not of mxChar type\n"); + } + + + + mexPrintf ("mocha does not support string/mxSTRING_CLASS as input\n"); + mexPrintf ("Please use char/mxCHAR_CLASS as data type for input\n"); + return; + } + else { + */ + //message + + //Trick to handle mocha(402) input from monitor Action + + messLength = METHOD_NAME_MAX_SIZE+1; + if (mxIsChar(prhs[0]) ) { + mData = (mxArray *) prhs[0]; + mxGetString(mData, mess, messLength); + } + else if (mochaIndex ==MONITOR_FLUSH_EVENT){ + strcpy(mess,"monitorflushevent"); + } + + + + char messOriginal[METHOD_NAME_MAX_SIZE+1]; + strcpy(messOriginal,mess); + + + //mexPrintf("message mess:%s\n", mess); + //mexPrintf("message orig:%s\n", messOriginal); + + + + //remove leadingTrailing Blanks + const char * _mess=mess; + cafe.getHandleHelper().removeLeadingAndTrailingSpaces(_mess,mess); + + std::string messString = mess; + + std::transform(messString.begin(), messString.end(), messString.begin(), ::tolower); + strcpy(mess,messString.c_str()); + + + if(!isCAInitialized && strcmp(mess,"monitorflushevent")!=0 && strcmp(mess,"close")!=0) { + NS_MOCHA::msInsert(); + NS_MOCHA::mdtInsert(); + + // print_out_by(ms); + } + else if (!isCAInitialized && strcmp(mess,"close")==0) { + mexPrintf("The CAFEteria was never opened! \n"); + return; + } + + if(!isCAInitialized && strcmp(mess,"close")!=0){ + + + if (!mexIsLocked()) { + mexLock(); + } + + //Remove PyCafe component should cafe have been compiled with pyCafe + //This flag controls import_PyCafe for when PyCafe_api.h is used + //If PyCafe.h is not used then you must link to non-Py cafe C++ librarry + + + //if ( cafe.setPyCafe(true) ) { + // mexPrintf("Py_Initialize \n"); + // Py_Initialize(); + //} + + #ifdef HAVE_PYTHON_H + //cafe.setPyCafe(true); + //dlopen("libpython2.6.so", RTLD_GLOBAL|RTLD_LAZY); + //dlopen("libpython3.5m.so", RTLD_GLOBAL|RTLD_LAZY); + mexPrintf("HAVE_PYTHON_H \n"); + //Py_Initialize(); + //mexPrintf("Py_Initialize from MATLAB \n"); + #endif + + cafe.init(); + + //#ifdef HAVE_PYTHON_H + // cafe.loadSFGroups("VA"); + //#endif + + isCAInitialized=true; + + if (strcmp(mess,"monitorflushevent")==0 ) { + mexPrintf("The CAFEteria is now open due to an outstanding monitorFlushEvent action (probably from a timer) \n"); + } + else { + mexPrintf("The CAFEteria is now open \n"); + } + } + + + mochaccino_set_by_name & name_index = ms.get (); + mochaccino_set_by_name::iterator it_name; + + + //mexPrintf("message %s\n", mess); + //mexPrintf("message %s\n", messString.c_str()); + + it_name = name_index.find(mess); + + if ( (it_name) != name_index.end() ) { + mochaIndex=(*it_name).id; + } + + int32_T mdtIndex=MOCHA_NATIVE; + int32_T mochaIndexOriginal=mochaIndex; + + bool cacheFlag=false; + bool sgTimeoutFlag=false; + bool extendedPV=false; + + size_t numberOfHandlesGetAsyn=0; + size_t nh=0; + size_t nv=0; + + //Wrapper methods + switch(mochaIndex) { + case GET_INT8: + mochaIndex=GET; + mdtIndex=MOCHA_CHAR; + break; + case GET_INT16: + mochaIndex=GET; + mdtIndex=MOCHA_SHORT; + break; + case GET_INT32: + mochaIndex=GET; + mdtIndex=MOCHA_INT; + break; + case GET_INT64: + mochaIndex=GET; + mdtIndex=MOCHA_LONG; + break; + case GET_UINT8: + mochaIndex=GET; + mdtIndex=MOCHA_UCHAR; + break; + case GET_UINT16: + mochaIndex=GET; + mdtIndex=MOCHA_USHORT; + break; + case GET_UINT32: + mochaIndex=GET; + mdtIndex=MOCHA_UINT; + break; + case GET_UINT64: + mochaIndex=GET; + mdtIndex=MOCHA_ULONG; + break; + case GET_FLOAT: + mochaIndex=GET; + mdtIndex=MOCHA_FLOAT; + break; + case GET_DOUBLE: + mochaIndex=GET; + mdtIndex=MOCHA_DOUBLE; + break; + case GET_STRING: + mochaIndex=GET; + mdtIndex=MOCHA_STRING; + break; + case GET_CELL_ARRAY_CACHE: + mochaIndex=GET_CELL_ARRAY; + cacheFlag=true; + break; + case GET_SCALAR_ARRAY_CACHE: + mochaIndex=GET_SCALAR_ARRAY; + cacheFlag=true; + break; + case GET_STRUCT_ARRAY_CACHE: + mochaIndex=GET_STRUCT_ARRAY; + cacheFlag=true; + break; + case GET_STRUCT_CACHE: + mochaIndex=GET_STRUCT; + cacheFlag=true; + break; + case GET_GROUP_CACHE: + mochaIndex=GET_GROUP; + cacheFlag=true; + break; + + + case GET_STRUCT_EXTENDED: + mochaIndex=GET_STRUCT; + extendedPV=true; + break; + + case GET_STRUCT_EXTENDED_ARRAY: + mochaIndex=GET_STRUCT_ARRAY; + extendedPV=true; + break; + + case GET_GROUP_EXTENDED: + mochaIndex=GET_GROUP; + extendedPV=true; + break; + + case GET_STRUCT_EXTENDED_ARRAY_CACHE: + mochaIndex=GET_STRUCT_ARRAY; + cacheFlag=true; + extendedPV=true; + break; + case GET_STRUCT_EXTENDED_CACHE: + mochaIndex=GET_STRUCT; + cacheFlag=true; + extendedPV=true; + break; + case GET_GROUP_EXTENDED_CACHE: + mochaIndex=GET_GROUP; + cacheFlag=true; + extendedPV=true; + break; + + case GET_WF_AS_STRING_CACHE: + mochaIndex=GET_WF_AS_STRING; + cacheFlag=true; + break; + + case GET_CACHE: + mochaIndex=GET; + cacheFlag=true; + break; + case GET_CTRL_CACHE: + mochaIndex=GET_CTRL_STRUCT; + cacheFlag=true; + break; + case GET_NELEM_CACHE: + mochaIndex=GET_NELEM_REQUEST; + cacheFlag=true; + break; + case GET_ASYN: + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle/pv \n", nrhs); + return; + } + if (mxIsChar(prhs[1]) ) { + numberOfHandlesGetAsyn=1; + } + else { + numberOfHandlesGetAsyn=mxGetNumberOfElements (prhs[1]); + } + if (numberOfHandlesGetAsyn >1) { + mochaIndex=GET_ARRAY_ASYN; + } + break; + + case SET: + + + if (nrhs<3) { + mexPrintf("Invalid Number of argument %d. Input: 'set', handle/pv, data \n", nrhs); + return; + } + + + if (mxIsChar(prhs[1])) { + nh=1; + } + else{ + nh=mxGetNumberOfElements (prhs[1]); + } + if (mxIsChar(prhs[2])) { + nv=1; + } + else{ + nv=mxGetNumberOfElements (prhs[2]); + } + + ///mexPrintf("nh=%d, nvalues=%d, nargin=%d\n", nh,nv, nrhs); + if (nh>1 && nh==nv && nrhs==3) { + mochaIndex=SET_SCALAR_ARRAY; + //mexPrintf("SET_SCALAR_ARRAY\n"); + } + else if (nh>1 && nh==(nrhs-2)) { + mochaIndex=SET_STRUCT_ARRAY; + //mexPrintf("SET_STRUCT_ARRAY\n"); + } + else if (nh>1) { + mochaIndex=SET_STRUCT_ARRAY; + mexPrintf("Inbalance between number of handles and input data\n"); + //mexPrintf("SET_STRUCT_ARRAY\n"); + } + + break; + + case SET_NELEM_CACHE: + mochaIndex=SET_NELEM; + cacheFlag=true; + break; + + case OPEN: + if (nrhs>1) { + if( mxIsCell(prhs[1]) ) { + mochaIndex=OPEN_ARRAY; + } + } + break; + + case CLOSE: + if (nrhs>1) { + if( mxGetNumberOfElements (prhs[1]) >1 ) { + mochaIndex=CLOSE_ARRAY; + } + } + break; + + case OPEN_WAIT_WITH_TIME: + if (nrhs<2) { + mochaIndex=OPEN_WAIT_TIME_TO_DEFAULT; + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_CHANNEL_CREATION); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + } + break; + + default: + break; + } + + + //Test again for GET + //Wrapper methods + switch(mochaIndex) { + case GET: + + if (mxIsChar(prhs[1])) { + nh=1; + } + else{ + + nh=mxGetNumberOfElements (prhs[1]); + + } + + ///mexPrintf("nh=%d, nargin=%d\n", nh, nrhs); + if (nrhs>3) { + mexPrintf("Usage: get [pv] (optional)\n"); + return; + } + if (nh>1) { + mochaIndex=GET_SCALAR_ARRAY; + //mexPrintf("GET_SCALAR_ARRAY\n"); + if(nrhs==3 &&mxIsChar(prhs[nrhs-1])) { + mdtIndex=NS_MOCHA::getMdtIndex(prhs[nrhs-1]); + } + //else { + //mexPrintf("3rd input argument giving the must be a string\n"); + //} + + //mexPrintf("GET_SCALAR_ARRAY\n"); + } + break; + + case GET_STRUCT: + if (mxIsChar(prhs[1])) { + nh=1; + } + else{ + nh=mxGetNumberOfElements (prhs[1]); + } + + ///mexPrintf("nh=%d, nargin=%d\n", nh, nrhs); + if (nrhs>3) { + mexPrintf("Usage: get [pv] (optional)\n"); + return; + } + if (nh>1) { + mochaIndex=GET_STRUCT_ARRAY; + //mexPrintf("GET_STRUCT_ARRAY\n"); + if(nrhs==3 &&mxIsChar(prhs[nrhs-1])) { + mdtIndex=NS_MOCHA::getMdtIndex(prhs[nrhs-1]); + } + //else { + //mexPrintf("3rd input argument giving the must be a string\n"); + //} + } + + break; + } + + // The Big Switch + switch (mochaIndex) { + + case TEST: + mexPrintf("mocha mex file is active\n"); + break; + + case MOCHA_VERSION: + plhs[0]=mxCreateString((char *) "mocha-1.3.0-final-1 : September 2017"); + break; + + case SHOW: + //print_out_by(ms); + for (it_name=name_index.begin(); it_name != name_index.end(); ++it_name) { + mexPrintf("%s\n", ((*it_name).name).c_str()); + } + break; + + case CA_POLL: + cafe._ca_poll(); + break; + + case MEX_UNLOCK: + + if (!mexIsLocked()) { + mexUnlock(); + } + break; + + case SET_PUT_PREPARE: + { + + + if (nrhs<2) { + mexPrintf("Invalid Number of argument(s) %d. Input: setPutPrepare, handle(s) or handleArray \n", nrhs); + return; + } + + + size_t numberOfHandles=0; + + + for (size_t j=1; j dhV; + vector pvV; + cafe.getHandleHelper().getHandles(dhV,pvV); + numberOfHandles=dhV.size(); + + for (size_t i=0; i< numberOfHandles; ++i) { + + status=cafe.getPolicy().getChannelRequestPolicyPut(dhV[i], polput); + if (status==ECAFE_INVALID_HANDLE) { + mexPrintf("SET_PUT_WAIT: Invalid handle no = %d \n", dhV[i]); + continue; + } + + //mexPrintf("no wait for handle no = %d\n", handleULong[i]); + //mexPrintf("wait for handle no = %d\n", handleULong[i]); + polput.setMethodKind(WITH_CALLBACK_DEFAULT); + polput.setWaitKind(WAIT); + polput.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_MESSAGE); + cafe.getPolicy().setChannelRequestPolicyPut(dhV[i], polput); + } + + break; + } + + + for (size_t j=1; j dhV; + vector pvV; + cafe.getHandleHelper().getHandles(dhV,pvV); + numberOfHandles=dhV.size(); + + for (size_t i=0; i< numberOfHandles; ++i) { + + status=cafe.getPolicy().getChannelRequestPolicyPut(dhV[i], polput); + if (status==ECAFE_INVALID_HANDLE) { + mexPrintf("SET_PUT_NOWAIT: Invalid handle no = %d \n", dhV[i]); + continue; + } + + //mexPrintf("no wait for handle no = %d\n", handleULong[i]); + //mexPrintf("wait for handle no = %d\n", handleULong[i]); + polput.setMethodKind(WITH_CALLBACK_DEFAULT); + polput.setWaitKind(NO_WAIT); + polput.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_MESSAGE); + cafe.getPolicy().setChannelRequestPolicyPut(dhV[i], polput); + } + + break; + } + + + for (size_t j=1; j dhV; + vector pvV; + cafe.getHandleHelper().getHandles(dhV,pvV); + unsigned int numberOfHandles=dhV.size(); + + if (numberOfHandles==0) {return;} + + ChannelRequestPolicy polget; + polget.setPolicy(FLUSH_AFTER_EACH_MESSAGE, WAIT, WITHOUT_CALLBACK); + + for (size_t i=0; i< numberOfHandles; ++i) { + cafe.getPolicy().setChannelRequestPolicyGet(dhV[i], polget); + } + + break; + } + case INIT_GET_SYNC_WITH_CALLBACK_DEFAULT: + { + cafe.channelRequestPolicyMasterGet.setPolicy(FLUSH_AFTER_EACH_MESSAGE, WAIT, WITH_CALLBACK_DEFAULT); + + vector dhV; + vector pvV; + cafe.getHandleHelper().getHandles(dhV,pvV); + unsigned int numberOfHandles=dhV.size(); + + if (numberOfHandles==0) {return;} + + ChannelRequestPolicy polget; + polget.setPolicy(FLUSH_AFTER_EACH_MESSAGE, WAIT, WITH_CALLBACK_DEFAULT); + + for (size_t i=0; i< numberOfHandles; ++i) { + cafe.getPolicy().setChannelRequestPolicyGet(dhV[i], polget); + } + + break; + } + + case OPEN_NOWAIT: + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_DESIGNATED_TO_CLIENT); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + + break; + + case OPEN_WAIT: + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_CHANNEL_CREATION); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + break; + + + case OPEN_NOW: + cafe.channelOpenPolicy.flushSendBufferNow(); + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_CHANNEL_CREATION); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + + break; + + + case OPEN_WAIT_WITH_TIME: + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, timeout \n", nrhs); + return; + } + + if (nrhs>1) { + if (!mxIsNumeric(prhs[1]) ) { + mexPrintf("Timeout does not have a numeric value \n"); + return; + } + cafe.channelOpenPolicy.setTimeout(mxGetScalar(prhs[1])); + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_AFTER_EACH_CHANNEL_CREATION); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + } + break; + + + case OPEN_WAIT_TIME_TO_DEFAULT: + if (nrhs>1) { + mexPrintf("Ignoring number of arguments %d\n", nrhs); + mexPrintf("This method resets open wait time to default value\n"); + } + + + plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + doubleArray[0]= cafe.channelOpenPolicy.setTimeoutToDefault(); + + + break; + + + case OPEN_NOW_AND_WAIT: + + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, timeout \n", nrhs); + return; + } + + if (nrhs>1) { + if (!mxIsNumeric(prhs[1]) ) { + mexPrintf("Timeout does not have a numeric value \n"); + return; + } + + //Get Timeput + double tPrevious=cafe.channelOpenPolicy.getTimeout(); + cafe.channelOpenPolicy.setTimeout(mxGetScalar(prhs[1])); + cafe.channelOpenPolicy.flushSendBufferNow(); + //reset + cafe.channelOpenPolicy.setWhenToFlushSendBuffer(FLUSH_NOW); + cafe.channelOpenPolicy.setFlushSendBufferKind(WITH_PEND_EVENT); + + //Set to previous + //cafe.channelOpenPolicy.setTimeoutToDefault(); + cafe.channelOpenPolicy.setTimeout(tPrevious); + + } + break; + + + case GET_OPEN_WAIT_TIME: + if (nrhs>1) { + mexPrintf("Ignoring number of arguments %d\n", nrhs); + mexPrintf("This method returns the current open wait time value\n"); + } + + plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + doubleArray[0]= cafe.channelOpenPolicy.getTimeout(); + break; + + case WITH_EXCEPTIONS: + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, bool \n", nrhs); + return; + } + + if( !mxIsLogical(prhs[1]) ) { + mexPrintf("2nd input argument must be of Matlab type Logical, i.e.true/false \n" ); + return; + } + + + //withExceptions = mxGetLogicals (prhs[1]); + withExceptions = mxIsLogicalScalarTrue (prhs[1]); + + break; + + + case HAVE_EXCEPTIONS: + + plhs[0] = mxCreateNumericMatrix(1,1,mxLOGICAL_CLASS,mxREAL); + logicalData = (mxLogical *) mxGetData (plhs[0]); + logicalData[0]=withExceptions; + + break; + + case SEND_NOW: + ca_flush_io(); + break; + + + case OPEN_ARRAY: + { + + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message Array, pv Output: handle Array \n", nrhs); + return; + } + + if( !mxIsCell(prhs[1]) ) { + mexPrintf("Process Variable names must be in a cell. \n" ); + return; + } + + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + if(numberOfHandles==0) { + mexPrintf("ERROR: MISSING INPUT \n"); + return; + } + + vector vstr; + vstr.reserve(numberOfHandles); + + for (size_t i=0; i< numberOfHandles; ++i) { + + mxArray * newCell = mxGetCell(prhs[1],i); + + if (mxIsChar(newCell) ) { + + //message pvname + xData = (mxArray *) newCell; + + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(xData, pv, pvLength); + vstr.push_back(pv); + } + else { + + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData (plhs[0]); + ulongArray[0]=0; + mexPrintf("ERROR READING INPUT, ELEMENT %d of %d IS NOT A mxCHAR \n", i, numberOfHandles); + return; + } + } + + + + vector vuint32=NS_MOCHA::openArray(vstr); + + + plhs[0] = mxCreateNumericMatrix(1,vuint32.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData (plhs[0]); + for (size_t i=0; i::signaling_NaN(); + + groupStatus[0]=ECAFE_UNKNOWN_GROUP; + + return; + } + + mdtIndex=MOCHA_NATIVE; + + if (nrhs>2) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument must be a char \n"); + return; + } + mdtIndex=getMdtIndex(prhs[2]); + } + + + int32_T mdtIndexOriginal=mdtIndex; + + PVGroup pvgroup; + + status=cafe.groupAttach(ghandle, pvgroup); + + PVDataHolder * du; + unsigned int NPV=0; + bool isGroupTimeout=false; + + if (status!=ECAFE_UNKNOWN_GROUP && status != ECAFE_EMPTY_GROUP) { + + + if (cacheFlag) { + status=cafe.groupGetCache(ghandle, pvgroup); + } + else { + status=cafe.groupGet(ghandle, pvgroup); + } + + + // statusGroup != ICAFE_SUCCESS when one or more channels accesses fail + if ( pvgroup.getStatusGroup() != ICAFE_SUCCESS ) { + for (mwSignedIndex i=0; i dhV = cafe.getHandlesFromWithinGroupV(ghandle); + du = new PVDataHolder[dhV.size()]; + if (cacheFlag) { + status=cafe.getPVArray(dhV, du); + } + else { + //status=cafe.getPVArrayCache(dhV, du); + status=cafe.getCachePVArray(dhV, du); + } + NPV=dhV.size(); + isGroupTimeout=true; + + } + } + else { + + mexPrintf("status/handle %d / %d \n", status, ghandle); + mexPrintf("Returning NaN in place of struct \n"); + + NS_MOCHA::printStatus(status); + + doubleArray[0]=numeric_limits::signaling_NaN(); + + groupStatus[0]=status; + + return; + } + + + groupStatus[0]=status; + + if (extendedPV) { + plhs[0]=mxCreateStructMatrix(1,NPV, nfieldsExtra, fnamesExtra); + } + else { + plhs[0]=mxCreateStructMatrix(1,NPV, nfields, fnames); + } + + + + for (mwSignedIndex j=0; j 2) { + mexPrintf("Ignoring all input arguments after the 2nd \n"); + mexPrintf("Method is mocha ('getAsyn', \n"); + } + + handle=checkForHandle(prhs[1]); + if(handle==0) { + mexPrintf("Handle does not exist!\n"); + return;} + + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + + status=cafe.get(handle); + longStatus[0]=status; + + if (status!=ICAFE_NORMAL) { + //NS_MOCHA::printStatus(status); + cafe.printStatus(handle,status); + + } + + break; + } + + + case GET_ARRAY_ASYN: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle/pv \n", nrhs); + return; + } + size_t numberOfHandles=0; + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + } + else { + numberOfHandles=mxGetNumberOfElements (prhs[1]); + } + + handleULong = checkHandleArray(prhs[1],true); + + if (handleULong==NULL) { + mexPrintf("GET_ARRAY_SYNC: Ignoring NULL value in input \n"); + mexPrintf("Number of arguments should be %d. with Input: message, handle/pv \n", nrhs); + return; + } + + plhs[1] = mxCreateNumericMatrix(1,numberOfHandles,mxINT32_CLASS, mxREAL); + longArray = (int32_T *) mxGetData (plhs[1]); + + status=cafe.get( (unsigned int *) handleULong, numberOfHandles, + (int *) longArray); + + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS, mxREAL); + longStatus = (int32_T *) mxGetData (plhs[0]); + longStatus[0]=(int32_T) status; + + break; + } + + + case GET_CTRL_STRUCT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle/pv, matlab type (optional)\n", nrhs); + return; + } + + + if (mxIsChar(prhs[1])) { + nh=1; + } + else{ + nh=mxGetNumberOfElements (prhs[1]); + } + if (nh >1) { + mexPrintf("Method limited to one handle/pv only. Reporting on first given"); + } + + handle=checkForHandle(prhs[1]); + if(handle==0) { + mexPrintf("Handle does not exist!\n"); + return;} + + mdtIndex=MOCHA_NATIVE; + + if (nrhs>2) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument must be a char \n"); + return; + } + mdtIndex=getMdtIndex(prhs[2]); + } + + fout1 = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData (fout1); + fout2 = mxCreateNumericMatrix(1,1,mxINT16_CLASS,mxREAL); + shortAlarmStatus = (int16_T *) mxGetData (fout2); + fout3 = mxCreateNumericMatrix(1,1,mxINT16_CLASS,mxREAL); + shortAlarmSeverity = (int16_T *) mxGetData (fout3); + fout4 = mxCreateNumericMatrix(1,1, mxUINT16_CLASS,mxREAL); + precision = (uint16_T *) mxGetData(fout4); + + fout6 = mxCreateNumericMatrix(1,1, mxUINT16_CLASS,mxREAL); + noEnumStrings = (uint16_T *) mxGetData(fout6); + fout8 = mxCreateDoubleMatrix(1,1,mxREAL); + udl = (double *) mxGetPr (fout8); + fout9 = mxCreateDoubleMatrix(1,1,mxREAL); + ldl = (double *) mxGetPr (fout9); + fout10 = mxCreateDoubleMatrix(1,1,mxREAL); + ual = (double *) mxGetPr (fout10); + fout11 = mxCreateDoubleMatrix(1,1,mxREAL); + lal = (double *) mxGetPr (fout11); + fout12 = mxCreateDoubleMatrix(1,1,mxREAL); + uwl = (double *) mxGetPr (fout12); + fout13 = mxCreateDoubleMatrix(1,1,mxREAL); + lwl = (double *) mxGetPr (fout13); + fout14 = mxCreateDoubleMatrix(1,1,mxREAL); + ucl = (double *) mxGetPr (fout14); + fout15 = mxCreateDoubleMatrix(1,1,mxREAL); + lcl = (double *) mxGetPr (fout15); + + + fout16=mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + fHandle = (uint32_T *) mxGetData(fout16); + fHandle[0]=handle; + string s = cafe.getPVFromHandle(handle); + fout17 =mxCreateString( s.c_str() ); + + + + nelem=cafe.getHandleHelper().getNelemRequestCtrl(handle); + + // mexPrintf("nelemRequested %d", nelem); + PVCtrlHolder du; + du.setNelem(nelem); + //du.setNelem(2); + // mexPrintf("nelem %d ", du.getNelem()); + + if (cacheFlag) { + status=cafe.getCtrlCache(handle,du); + } + else { + status=cafe.getCtrl(handle,du); + } + + reportError=false; + + plhs[0]=mxCreateStructMatrix(1, 1, nfieldsCtrl, fnamesCtrl); + + //Match INPUT to CAFE DATATYPE + if (mdtIndex==MOCHA_NATIVE) { + mdtIndex=getMdtIndexFromCafeDataType(du.getDataType()); + if (cafe.getHandleHelper().isEnum(handle)) { + mdtIndex=MOCHA_STRING; + } + } + + fillCtrlStruct(mdtIndex, du); + + if (status==ICAFE_NORMAL) { + fout5 = mxCreateString((char *) du.getUnits()); + ////fillCtrlStruct(mdtIndex, du); + } //if + else { + reportError=true; + } + // Use shared_ptr since cafe-1.0 + //delete [] du.val; + + if (reportError) { + fout0=getValueIfError(mdtIndex); + //longStatus[0] = (int32_T) status; + //shortAlarmStatus[0] = (int16_T) 0; + //shortAlarmSeverity[0] = (int16_T) 0; + fout5 = mxCreateString((const char *) ""); + precision[0]=0; + noEnumStrings[0]=0; + fout7 = mxCreateCellMatrix(1,1); + for (mwSignedIndex i=0; i <1; ++i) + mxSetCell (fout7, i, mxCreateString((const char *) "" ) ); + udl[0]=0; + ldl[0]=0; + ual[0]=0; + lal[0]=0; + uwl[0]=0; + lwl[0]=0; + ucl[0]=0; + lcl[0]=0; + //cafe.printStatus(handle,status); + } + + mxSetFieldByNumber(plhs[0], 0, 0, fout16); //handle + mxSetFieldByNumber(plhs[0], 0, 1, fout17); //pv + mxSetFieldByNumber(plhs[0], 0, 2, fout0); + mxSetFieldByNumber(plhs[0], 0, 3, fout1); + mxSetFieldByNumber(plhs[0], 0, 4, fout1a); + mxSetFieldByNumber(plhs[0], 0, 5, fout2); + mxSetFieldByNumber(plhs[0], 0, 6, fout2a); + mxSetFieldByNumber(plhs[0], 0, 7, fout3); + mxSetFieldByNumber(plhs[0], 0, 8, fout3a); + + mxSetFieldByNumber(plhs[0], 0, 9, fout4); + mxSetFieldByNumber(plhs[0], 0, 10, fout5); + mxSetFieldByNumber(plhs[0], 0, 11, fout6); + mxSetFieldByNumber(plhs[0], 0, 12, fout7); + mxSetFieldByNumber(plhs[0], 0, 13, fout8); + mxSetFieldByNumber(plhs[0], 0, 14, fout9); + mxSetFieldByNumber(plhs[0], 0, 15, fout10); + mxSetFieldByNumber(plhs[0], 0, 16, fout11); + mxSetFieldByNumber(plhs[0], 0, 17, fout12); + mxSetFieldByNumber(plhs[0], 0, 18, fout13); + mxSetFieldByNumber(plhs[0], 0, 19, fout14); + mxSetFieldByNumber(plhs[0], 0, 20, fout15); + break; + } + + case GET_STRUCT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle/pv, matlab type (optional) \n", nrhs); + return; + } + + handle=checkForHandle(prhs[1]); + if(handle==0) { + mexPrintf("Handle does not exist!\n"); + return;} + + mdtIndex=MOCHA_NATIVE; + + if (nrhs>2) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument must be a char \n"); + return; + } + mdtIndex=getMdtIndex(prhs[2]); + } + + reportError=false; + + uint32_T * d4; + nelem = cafe.getHandleHelper().getNelemClient(handle); //change NelemRequest to NelemClient + + // OUTPUT + + if (extendedPV) { + plhs[0]=mxCreateStructMatrix(1, 1, nfieldsExtra, fnamesExtra); + } + else { + plhs[0]=mxCreateStructMatrix(1, 1, nfields, fnames); + } + /* + fout1 = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData (fout1); + + fout2 = mxCreateNumericMatrix(1,1,mxINT16_CLASS,mxREAL); + shortAlarmStatus = (int16_T *) mxGetData (fout2); + + fout3 = mxCreateNumericMatrix(1,1,mxINT16_CLASS,mxREAL); + shortAlarmSeverity = (int16_T *) mxGetData (fout3); + + fout4 = mxCreateNumericMatrix(1,7,mxUINT32_CLASS,mxREAL); + d4 = (uint32_T *) mxGetData(fout4); + + + + + fout9 = mxCreateNumericMatrix(1,2,mxUINT32_CLASS,mxREAL); + d9 = (uint32_T *) mxGetData(fout9); + */ + + PVDataHolder du; + + epicsTimeStamp ets1; + ets1.secPastEpoch=0; + ets1.nsec=0; + + unsigned int nelemPrevious=1; + bool nelemCacheChangeFlag=false; + + if(cacheFlag) { + nelem = cafe.getHandleHelper().getNelemToRetrieveFromCache(handle); + if (nelem > cafe.getHandleHelper().getNelemRequest(handle) ) { + nelemPrevious=nelem; + nelem = min( (unsigned int) nelem, cafe.getHandleHelper().getNelemRequest(handle)); + cafe.getHandleHelper().setNelemToRetrieveFromCache(handle,nelem); + nelemCacheChangeFlag=true; + } + } + + du.setNelem(nelem); + + if (cacheFlag) { + status=cafe.getCache(handle,du); + } + else { + status=cafe.get(handle,du); + } + + //Match INPUT to CAFE DATATYPE + if (mdtIndex==MOCHA_NATIVE) { + mdtIndex=getMdtIndexFromCafeDataType(du.getDataType()); + if (cafe.getHandleHelper().isEnum(handle)) { + mdtIndex=MOCHA_STRING; + } + } + + fillPVStruct(mdtIndex, du); + + if (extendedPV) { + fillPVStructExtra(handle, du); + } + + if (status!=ICAFE_NORMAL) { + reportError=true; + } + + + if(nelemCacheChangeFlag) { + cafe.getHandleHelper().setNelemToRetrieveFromCache(handle,nelemPrevious); + } + + // Use shared_ptr since cafe-1.0 + // delete [] du.val; + + if (reportError) { + + fout0=getValueIfError(mdtIndex); + //longStatus[0] = (int32_T) status; + //shortAlarmStatus[0] = (int16_T) 0; + //shortAlarmSeverity[0] = (int16_T) 0; + + //cafe.printStatus(handle,status); + } + + + if (extendedPV) { + mxSetFieldByNumber(plhs[0], 0, 0, fout10); + mxSetFieldByNumber(plhs[0], 0, 1, fout5); + mxSetFieldByNumber(plhs[0], 0, 2, fout0); + mxSetFieldByNumber(plhs[0], 0, 3, fout1); + mxSetFieldByNumber(plhs[0], 0, 4, fout6); + mxSetFieldByNumber(plhs[0], 0, 5, fout2); + mxSetFieldByNumber(plhs[0], 0, 6, fout7); + mxSetFieldByNumber(plhs[0], 0, 7, fout3); + mxSetFieldByNumber(plhs[0], 0, 8, fout8); + mxSetFieldByNumber(plhs[0], 0, 9, fout4); + mxSetFieldByNumber(plhs[0], 0,10, fout9); + } + else { + mxSetFieldByNumber(plhs[0], 0, 0, fout0); + mxSetFieldByNumber(plhs[0], 0, 1, fout1); + mxSetFieldByNumber(plhs[0], 0, 2, fout2); + mxSetFieldByNumber(plhs[0], 0, 3, fout3); + mxSetFieldByNumber(plhs[0], 0, 4, fout4); + } + + if (status!=ICAFE_NORMAL) { + if (withExceptions) { + mexErrMsgIdAndTxt(prepareExceptionID(status).c_str(), prepareExceptionText(handle,status).c_str()); + } + } + + break; + } + + case GET_SCALAR_ARRAY: + { + + if (nrhs<2) { + if(cacheFlag) { + mexPrintf("Invalid Number of argument %d. Input: 'getScalarArrayCache', handleArray \n", nrhs); + } + else { + mexPrintf("Invalid Number of argument %d. Input: 'getScalarArray', handleArray \n", nrhs); + } + return; + } + + if (nrhs>2 && (mochaIndex==mochaIndexOriginal || cacheFlag) ) { + //ischar? + if (!mxIsChar(prhs[nrhs-1]) ) { + mexPrintf("Last input argument must be a char \n"); + return; + } + mdtIndex=NS_MOCHA::getMdtIndex(prhs[nrhs-1]); + } + + + int32_T mdtIndexOriginal=mdtIndex; + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + neWithinAllCells=0; // filled by checkHandleArray + + //What is dataType? + handleULong = checkHandleArray(prhs[1],true);//(uint64_T *) mxGetData ( prhs[1]); + + + if (handleULong==NULL) { + mexPrintf("GET_SCALAR_ARRAY: Ignoring NULL value in input\n"); + mexPrintf("Input Invalid. Should be: 'getStructArray(Cache)', handleArray \n"); + return; + } + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + //mexPrintf("char numberOfHandles %d",numberOfHandles); + } + else if (mxIsCell(prhs[1]) ) { + numberOfHandles=neWithinAllCells; + //mexPrintf(" cell numberOfHandles %d",numberOfHandles); + } + + + //for (size_t i=0; i1) { + nelem=1; // First element only + } + pvd[i].setNelem(nelem); + + //Is this really needed? + if(cacheFlag) { + cafe.getHandleHelper().setNelemToRetrieveFromCache((unsigned int) handleULong[i],nelem); + } + } + + if(cacheFlag) { + status=cafe.getCache( (unsigned int *) handleULong, numberOfHandles, + pvd); + } + else { + + status=cafe.get( (unsigned int *) handleULong, numberOfHandles, + pvd); + + } + + + int32_T * groupStatus; + + //overall groupStatus + plhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + groupStatus = (int32_T *) mxGetData (plhs[1]); + groupStatus[0]=status; + + plhs[2] = mxCreateNumericMatrix(1,numberOfHandles,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData (plhs[2]); + + //plhs[0] = mxCreateDoubleMatrix (1,numberOfHandles,mxREAL); + //doubleArray = (double *) mxGetPr (plhs[0]); + + //If no datatype is given, assume datatype of first element! + if (mdtIndexOriginal==MOCHA_NATIVE){ + mdtIndex=NS_MOCHA::getMdtIndexFromCafeDataType(pvd[0].getDataType()); + if (cafe.getHandleHelper().isEnum(handleULong[0])) { //check this for handleULong[0] + mdtIndex=MOCHA_STRING; + } + } + + + + switch (mdtIndex) + { + case MOCHA_DOUBLE: + plhs[0] = mxCreateDoubleMatrix(1,numberOfHandles,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_FLOAT: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxSINGLE_CLASS, mxREAL); + floatArray = (float *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_INT: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxINT32_CLASS, mxREAL); + longArray = (int32_T *) mxGetData (plhs[0] ); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_SHORT: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxINT16_CLASS, mxREAL); + shortArray = (int16_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_USHORT: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxUINT16_CLASS, mxREAL); + ushortArray = (uint16_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_UCHAR: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxUINT8_CLASS, mxREAL); + ucharArray = (uint8_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + + case MOCHA_STRING: + { + plhs[0] = mxCreateCellMatrix(1,numberOfHandles); + for (mwSignedIndex j=0; j ::quiet_NaN() )); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + } + // Non DBR_TYPES + case MOCHA_CHAR: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxINT8_CLASS, mxREAL); + charArray = (int8_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + case MOCHA_UINT: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxUINT32_CLASS, mxREAL); + ulongArray = (uint32_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + case MOCHA_LONG: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxINT64_CLASS, mxREAL); + longlongArray = (int64_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + case MOCHA_ULONG: + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxUINT64_CLASS, mxREAL); + ulonglongArray = (uint64_T *) mxGetData (plhs[0]); + for (mwSignedIndex j=0; j ::quiet_NaN(); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + default: + { + plhs[0] = mxCreateCellMatrix(1,numberOfHandles); + for (mwSignedIndex j=0; j ::quiet_NaN())); + } + longStatus[j]=pvd[j].getStatus(); + } + break; + } + } //switch + + // for (mwSignedIndex j=0; j 2 && (mochaIndex==mochaIndexOriginal || cacheFlag) ) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument (data type) must be a char \n"); + return; + } + mdtIndex=NS_MOCHA::getMdtIndex(prhs[2]); + } + + int32_T mdtIndexOriginal=mdtIndex; + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + + neWithinAllCells=0; // filled by checkHandleArray + + //What is dataType? + handleULong = checkHandleArray(prhs[1],true);//(uint64_T *) mxGetData ( prhs[1]); + + if (handleULong==NULL) { + mexPrintf("GET_STRUCT_ARRAY: Ignoring NULL value in input \n"); + mexPrintf("Input Invalid. Should be: 'getStructArray', handleArray \n"); + return; + } + + + if(handleULong[0]==0) { + mexPrintf("Input Invalid. Should be: 'getStructArray', handleArray \n"); + return; + } + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + } + else if (mxIsCell(prhs[1]) ) { + numberOfHandles=neWithinAllCells; + //mexPrintf(" cell numberOfHandles %d",numberOfHandles); + } + + + + PVDataHolder * pvd = new PVDataHolder[numberOfHandles]; + + for (size_t i=0; i2 && (mochaIndex==mochaIndexOriginal || cacheFlag) ) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument (data type) must be a char \n"); + return; + } + mdtIndex=NS_MOCHA::getMdtIndex(prhs[2]); + } + + int32_T mdtIndexOriginal=mdtIndex; + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + neWithinAllCells=0; // filled by checkHandleArray + + //What is dataType? + handleULong = checkHandleArray(prhs[1],true);//(uint64_T *) mxGetData ( prhs[1]); + + if (handleULong==NULL) { + mexPrintf("GET_CELL_ARRAY: Ignoring NULL value in input \n"); + mexPrintf("Input Invalid. Should be: 'getCellArray', handleArray \n"); + return; + } + + + if(handleULong[0]==0) { + mexPrintf("Input Invalid. Should be: 'getCellArray', handleArray \n"); + return; + } + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + } + else if (mxIsCell(prhs[1]) ) { + numberOfHandles=neWithinAllCells; + //mexPrintf(" cell numberOfHandles %d",numberOfHandles); + } + + + PVDataHolder * pvd = new PVDataHolder[numberOfHandles]; + + for (size_t i=0; i2 && (mochaIndex==mochaIndexOriginal || cacheFlag) ) { + //ischar? + if (!mxIsChar(prhs[2]) ) { + mexPrintf("3rd input argument must be a char \n"); + return; + } + mdtIndex=NS_MOCHA::getMdtIndex(prhs[2]); + + } + if (mdtIndex==MOCHA_NATIVE){ + + + + status=cafe.getHandleHelper().getDataTypeRequest(handle, rdt); + + + if (status!=ICAFE_NORMAL) { + mexPrintf("Error for handle input= %d \n", (uint32_T) mxGetScalar(prhs[1]) ); + NS_MOCHA::printStatus(status); + longStatus[0]=status; + plhs[0]=getValueIfError(mdtIndex); + return; + } + + CAFE_DATATYPE cdt = (CAFE_DATATYPE) rdt; + + + + mdtIndex=getMdtIndexFromCafeDataType(cdt); + + + + if (cafe.getHandleHelper().isEnum(handle)) { + + mdtIndex=MOCHA_STRING; + } + } + + nelem = cafe.getHandleHelper().getNelemClient(handle); //Change Request to Client + + + + if (cafe.getHandleHelper().getOffset(handle) > 0 ) { + + nelem = min( cafe.getHandleHelper().getNelemClient(handle), + (cafe.getHandleHelper().getNelemNative(handle)-cafe.getHandleHelper().getOffset(handle)) ); + + } + + if(nelem<1) { + nelem=1; // This is to build output matrix + } + + + unsigned int nelemPrevious=1; + bool nelemCacheChangeFlag=false; + + if(cacheFlag) { + + nelem = cafe.getHandleHelper().getNelemToRetrieveFromCache(handle) ; + + //mexPrintf("get Cache: nelem = %d \n", nelem); + + + if ( (cafe.getHandleHelper().getOffsetLast(handle) > 0) || + (cafe.getHandleHelper().getNelemToRetrieveFromCache(handle) > cafe.getHandleHelper().getNelemRequest(handle))){ + + + //if (nelem > cafe.getHandleHelper().getNelemRequest(handle) ) { + nelemPrevious=cafe.getHandleHelper().getNelemToRetrieveFromCache(handle); + nelem = min( (unsigned int) nelem, cafe.getHandleHelper().getNelemRequest(handle)-cafe.getHandleHelper().getOffsetLast(handle)); + + //mexPrintf("nelem to ret from Cache %d \n",cafe.getHandleHelper().getNelemToRetrieveFromCache(handle)); + //mexPrintf("nelem to ret from Cache %d \n",nelem); + //cafe.getHandleHelper().setNelemToRetrieveFromCache(handle,nelem+cafe.getHandleHelper().getOffsetLast(handle)); + cafe.getHandleHelper().setNelemToRetrieveFromCache(handle,nelem); + nelemCacheChangeFlag=true; + } + + } + + switch (mdtIndex) + { + case MOCHA_DOUBLE: + plhs[0] = mxCreateDoubleMatrix(1,nelem,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + if(cacheFlag) { status=cafe.getCache(handle,doubleArray);} + else {status=cafe.get(handle,doubleArray);} + break; + + case MOCHA_FLOAT: + plhs[0] = mxCreateNumericMatrix(1,nelem,mxSINGLE_CLASS, mxREAL); + floatArray = (float *) mxGetData (plhs[0]); + if(cacheFlag) { mexPrintf("here"); status=cafe.getCache(handle,floatArray); mexPrintf("status %d", status);} + else {status=cafe.get(handle,floatArray);} + break; + + case MOCHA_INT: + plhs[0] = mxCreateNumericMatrix(1,nelem,mxINT32_CLASS, mxREAL); + longArray = (int32_T *) mxGetData (plhs[0] ); + if(cacheFlag) { status=cafe.getCache(handle,longArray);} + else {status=cafe.get(handle,longArray);} + break; + + case MOCHA_SHORT: + plhs[0] = mxCreateNumericMatrix(1,nelem,mxINT16_CLASS, mxREAL); + shortArray = (int16_T *) mxGetData (plhs[0]); + if(cacheFlag) { status=cafe.getCache(handle,shortArray);} + else {status=cafe.get(handle,shortArray);} + break; + + case MOCHA_USHORT: + plhs[0] = mxCreateNumericMatrix(1,nelem,mxUINT16_CLASS, mxREAL); + ushortArray = (uint16_T *) mxGetData (plhs[0]); + if(cacheFlag) { status=cafe.getCache(handle,ushortArray);} + else {status=cafe.get(handle,ushortArray);} + break; + + case MOCHA_UCHAR: + plhs[0] = mxCreateNumericMatrix(1,nelem,mxUINT8_CLASS, mxREAL); + ucharArray = (uint8_T *) mxGetData (plhs[0]); + if(cacheFlag) { status=cafe.getCache(handle,ucharArray);} + else {status=cafe.get(handle,ucharArray);} + break; + + case MOCHA_STRING: + { + dbr_string_t * stringArrayc = new dbr_string_t[nelem]; + + if(cacheFlag) { status=cafe.getCache(handle,stringArrayc);} + else {status=cafe.get(handle,stringArrayc);} + + //char *test[40]; + //test[0]="test"; + //test[1]="again"; + //mxChar *pr; + //char *ptr_to_seed_data; + //int c; + + + if (status==ICAFE_NORMAL) { + + if (nelem==1) { + plhs[0]=mxCreateString( stringArrayc[0] ); + } + else { + plhs[0] = mxCreateCellMatrix(1,nelem); + for (mwSignedIndex i=0; i 1) { + mexPrintf("Method returns enumerated value/name pairs of alarm conditions \n"); + } + + vector vecS; vector vecI; + cgac.getStates(vecI, vecS); + + plhs[1] = mxCreateNumericMatrix(1,vecI.size(), mxINT32_CLASS,mxREAL); + longArray= (int32_T *) mxGetData(plhs[1]); + + //return string list + plhs[0] = mxCreateCellMatrix(1,vecS.size()); + + for (mwSignedIndex i=0; i1) { + mexPrintf("Method returns enumerated value/name pairs of alarm severities \n"); + } + + vector vecS; vector vecI; + cgas.getStates(vecI, vecS); + + plhs[1] = mxCreateNumericMatrix(1,vecI.size(), mxINT32_CLASS,mxREAL); + longArray= (int32_T *) mxGetData(plhs[1]); + + //return string list + plhs[0] = mxCreateCellMatrix(1,vecS.size()); + + for (mwSignedIndex i=0; i1) { + mexPrintf("Method returns enumerated value/name pairs of status codes \n"); + } + + vector vecS; vector vecI; + cafe.getCafeStatus().csc.getStates(vecI, vecS); + + plhs[1] = mxCreateNumericMatrix(1,vecI.size(), mxINT32_CLASS,mxREAL); + longArray= (int32_T *) mxGetData(plhs[1]); + + //return string list + plhs[0] = mxCreateCellMatrix(1,vecS.size()); + + for (mwSignedIndex i=0; i vi; + + status=cafe.groupAttach(ghandle, pvg); + + if (status!=ECAFE_UNKNOWN_GROUP && status != ECAFE_EMPTY_GROUP) { + + status=cafe.groupGetCache(ghandle, pvg); + + vi=cafe.getPulseIDFromTS(pvg); + + } + + plhs[0] = mxCreateNumericMatrix(1,vi.size(), mxUINT32_CLASS,mxREAL); + ulongArray= (uint32_T *) mxGetData(plhs[0]); + + for (mwSignedIndex i=0; i::signaling_NaN(); + + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + } + + + break; + } + + case SET_STRUCT_ARRAY: + { + if (nrhs<3) { + mexPrintf("Invalid Number of argument %d. Input: 'setStructArray', handle/pv array, data array \n", nrhs); + return; + } + + + //What is dataType? + handleULong = checkHandleArray(prhs[1],true); + + if (handleULong==NULL) { + mexPrintf("SET_STRUCT_ARRAY: Ignoring NULL value in input\n"); + mexPrintf("Input Invalid. Should be: 'setStructArray', handle/pv array, data array \n"); + return; + } + + + if(handleULong[0]==0) { + mexPrintf("Input Invalid. Should be: 'setStructArray', handle/pv array, data array \n"); + return; + } + + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + size_t nDataInputs=nrhs-2; + + //Examine data input + //Break up a cell or an array + //Check no of data inputs + //nelem=nrhs-2; + + /* + if (nhrs=3} { + //neWithinAllDataCells=0; + + + if (mxIsCell(prhs[k])) { + + nDataInputs=getObjectsFromDataCell(prhs[k]); + + mexPrintf("Running No of Elements in Cell = %d \n", nDataInputs); + + } + //else { + // nDataInputs=nDataInputs+1; + //} + } + */ + + + //if (numberOfHandles != nrhs-2) { + if (numberOfHandles != nDataInputs) { + mexPrintf("Input Invalid. Data Array Length %d does not equal No of handles %d! \n", nrhs-2,numberOfHandles); + //mexPrintf("Input Invalid. Data Array Length %d does not equal No of handles %d! \n", nDataInputs,numberOfHandles); + return; + } + + PVDataHolder * du; + + //du = new PVDataHolder[nrhs-2]; + du = new PVDataHolder[nDataInputs]; + + mwSignedIndex j=0; + + for (mwSignedIndex k=2; k3) { + mexPrintf("Ignoring arguments after the 3rd from the %d entered. \nInput: 'setScalarArray', handle/pv array, data array \n", nrhs); + } + + //What is dataType? + handleULong = checkHandleArray(prhs[1],true); + + if (handleULong==NULL) { + mexPrintf("SET_SCALAR_ARRAY: Ignoring NULL value in input \n"); + mexPrintf("Input Invalid. Should be: 'setScalarArray', handle/pv array, data array \n"); + return; + } + + + if(handleULong[0]==0) { + mexPrintf("Input Invalid. Should be: 'setScalarArray', handle/pv array, data array \n"); + return; + } + + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + nelem=mxGetNumberOfElements (prhs[2]); + + if(nelem==0) { + mexPrintf("Empty Data Array in Input \n"); + return; + } + + if (numberOfHandles != nelem) { + mexPrintf("Input Invalid. Data Array Length %d does not equal No of handles %d! \n", nelem,numberOfHandles); + return; + } + + + neWithinAllCells=0; + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + } + else if (mxIsCell(prhs[1]) ) { + scanCell(prhs[1]); + numberOfHandles=neWithinAllCells; + //mexPrintf(" cell numberOfHandles %d",numberOfHandles); + } + + + + //statuses + plhs[1] = mxCreateNumericMatrix(1,numberOfHandles,mxINT32_CLASS,mxREAL); + longArray = (int32_T *) mxGetData (plhs[1]); + + mxClassID mxid =mxGetClassID(prhs[2]); + + mxArray * fout; + + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr (prhs[2]); + status=cafe.set((unsigned int *)handleULong, (unsigned int) numberOfHandles, inputDouble, (int *) longArray); + break; + case mxSINGLE_CLASS: + inputFloat = (float *) mxGetData (prhs[2]); + status=cafe.set((unsigned int *)handleULong, (unsigned int) numberOfHandles, inputFloat, (int *) longArray); + break; + case mxLOGICAL_CLASS: + inputBool = (bool *) mxGetData (prhs[2]); + fout = mxCreateNumericMatrix(1,numberOfHandles,mxINT8_CLASS, mxREAL); + inputShort = (short *) mxGetData ( fout ); + for (mwSignedIndex i=0; i3) { + mexPrintf("Ignoring arguments after the 3rd from the %d entered. Input: 'set', handle/pv, data \n", nrhs); + } + + handle=checkForHandle(prhs[1]); + if(handle==0) {return;} + + + if (!isValidClass(prhs[2])) return; + + size_t ne = mxGetNumberOfElements ( prhs[2]); + + if(ne==0) { + mexPrintf("Empty Data Array in Input \n"); + return; + } + + + neWithinAllCells=0; + iWithinAllCells=0; + + mxClassID mxid =mxGetClassID( prhs[2]); + + //This line is important for a string as the Number of Elements + //is interpreted as the number of characters!!! + //Hence for ne to be 1 + if (mxid==mxCHAR_CLASS) { ne=1; } + + nelem = cafe.getHandleHelper().getNelemClient(handle); + + + //handle does not exist + if(nelem==0) { + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=ECAFE_INVALID_HANDLE; + + if (withExceptions) { + mexErrMsgIdAndTxt(prepareExceptionID(ECAFE_INVALID_HANDLE).c_str(), prepareExceptionText(handle,ECAFE_INVALID_HANDLE).c_str()); + } + + return; + } + + if(nelem!=ne) {cafe.getHandleHelper().setNelem(handle,ne);} + + mxArray *fout; + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr (prhs[2]); + status=cafe.set(handle,inputDouble); + break; + case mxSINGLE_CLASS: + inputFloat = (float *) mxGetData (prhs[2]); + status=cafe.set(handle,inputFloat); + break; + case mxLOGICAL_CLASS: + inputBool = (bool *) mxGetData (prhs[2]); + fout = mxCreateNumericMatrix(1,ne,mxINT8_CLASS, mxREAL); + inputShort = (short *) mxGetData ( fout ); + for (mwSignedIndex i=0; i3) { + mexPrintf("Ignoring arguments after the 3rd from the %d entered. Input: 'set', handle/pv, data \n", nrhs); + } + + handle=checkForHandle(prhs[1]); + if(handle==0) {return;} + + + if (!isValidClass(prhs[2])) return; + + size_t ne = mxGetNumberOfElements ( prhs[2]); + + if(ne==0) { + mexPrintf("Empty Data Array in Input \n"); + return; + } + + neWithinAllCells=0; + iWithinAllCells=0; + + mxClassID mxid =mxGetClassID( prhs[2]); + + //This line is important for a string as the Number of Elements + //is interpreted as the number of characters!!! + //Hence for ne to be 1 + if (mxid==mxCHAR_CLASS) { ne=1; } + + nelem = cafe.getHandleHelper().getNelemClient(handle); + + + //handle does not exist + if(nelem==0) { + + + plhs[0] = mxCreateDoubleMatrix(1,nelem,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + doubleArray[0]=numeric_limits::signaling_NaN(); + + //status + plhs[1] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[1]); + longStatus[0]=ECAFE_INVALID_HANDLE; + + if (withExceptions) { + mexErrMsgIdAndTxt(prepareExceptionID(ECAFE_INVALID_HANDLE).c_str(), prepareExceptionText(handle,ECAFE_INVALID_HANDLE).c_str()); + } + + return; + } + + if(nelem!=ne) {cafe.getHandleHelper().setNelem(handle,ne);} + + size_t neOne=1; //Only deal with first element for the waveform!! + + mxArray *fout; + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr (prhs[2]); + + plhs[0] = mxCreateDoubleMatrix(1,ne,mxREAL); + doubleArray = (double *) mxGetPr (plhs[0]); + + status=cafe.setAndGet(handle,inputDouble[0], doubleArray[0]); + break; + case mxSINGLE_CLASS: + inputFloat = (float *) mxGetData (prhs[2]); + + plhs[0] = mxCreateNumericMatrix(1,ne,mxSINGLE_CLASS, mxREAL); + floatArray = (float *) mxGetData (plhs[0]); + + status=cafe.setAndGet(handle,inputFloat[0], floatArray[0]); + break; + case mxLOGICAL_CLASS: + inputBool = (bool *) mxGetData (prhs[2]); + fout = mxCreateNumericMatrix(1,ne,mxINT8_CLASS, mxREAL); + inputShort = (short *) mxGetData ( fout ); + for (mwSignedIndex i=0; i hV; hV.clear(); hV.reserve(numberOfHandles); + vector hrbV; hrbV.clear(); hrbV.reserve(numberOfHandles); + for (size_t i=0; i doubleV; doubleV.clear(); + vector floatV; floatV.clear(); + vector shortV; shortV.clear(); + vector ushortV; ushortV.clear(); + vector ucharV; ucharV.clear(); + vector longV; longV.clear(); + vector longlongV; longlongV.clear(); + vector stringV; stringV.clear(); + + switch(mxid) { + case mxDOUBLE_CLASS: + inputDouble = (double *) mxGetPr (prhs[2]); + doubleV.reserve(numberOfHandles); + for (size_t i=0; i2) { + + for (mwSize i=2; i numberOfHandles) { + mexPrintf("Handle does not exists for monAction: %s\n", monAction); + + } + + if (!mxIsChar(prhs[i]) ) { + mexPrintf("monitorAction does not have a string value \n" ); + mexPrintf("Input: 'monitor', handle/pv, monitorAction(optional)\n" ); + return; + } + //message + mData = (mxArray *) prhs[i]; + messLength = MONITOR_ACTION_MAX_SIZE; + mxGetString(mData, monAction, messLength); + + char monActionOriginal[MONITOR_ACTION_MAX_SIZE]; + strcpy(monActionOriginal,monAction); + + //remove leadingTrailing Blanks + const char * _monAction=monAction; + + cafe.getHandleHelper().removeLeadingAndTrailingSpaces(_monAction,monAction); + cafe.getHandleHelper().addMonitorAction(handleULong[i-2],monAction); + if (nrhs > 3) { + mexPrintf("Handle: %d has monAction: %s\n", handleULong[i-2], monAction); + } + } + } + + + int * statusArray = new int [numberOfHandles]; + unsigned int * monitorID = new unsigned int[numberOfHandles]; + + status=cafe.monitorStart(handleULong, (unsigned int) numberOfHandles, statusArray, monitorID); + + //monitorID + plhs[0] = mxCreateNumericMatrix(1,numberOfHandles,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (mwSignedIndex i=0; i stopping all monitors\n" ); + cafe.getHandleHelper().clearMonitorAction(); + status=cafe.monitorStop(); + + } + + else { + + handleULong = checkHandleArray(prhs[1],true); + + if (handleULong==NULL) { + mexPrintf("MONITOR: Ignoring NULL value in input \n"); + mexPrintf("Input Invalid. Should be: 'monitor', handle/pv array \n"); + return; + } + + if(handleULong[0]==0) { + mexPrintf("Input Invalid. Should be: 'monitor', handle/pv array \n"); + return; + } + + + size_t numberOfHandles=mxGetNumberOfElements (prhs[1]); + + + if (mxIsChar(prhs[1]) ) { + numberOfHandles=1; + } + else if (mxIsCell(prhs[1]) ) { + numberOfHandles=neWithinAllCells; + } + + //handle=checkForHandle(prhs[1]); + //if(handle==0) {return;} + handle=handleULong[0]; + if (numberOfHandles==1 && nrhs>2) { + + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("MonitorID does not have a numeric value \n" ); + mexPrintf("Input: 'monitorStop', handle/pv, monitorID(optional)\n" ); + return; + } + + monitorID = (uint32_T) mxGetScalar(prhs[2]); + cafe.getHandleHelper().clearMonitorAction(handle); + status=cafe.monitorStop(handle,monitorID); + + if (status!=ICAFE_NORMAL) { + cafe.printStatus(handle,status); + } + + } + else if (numberOfHandles==1) { + cafe.getHandleHelper().clearMonitorAction(handle); + status=cafe.monitorStop(handle); + if (status!=ICAFE_NORMAL) { + cafe.printStatus(handle,status); + } + + } + else { + + if (nrhs>2) { + mexPrintf("Ignoring third input argument; Stopping all monitors for given array of handles/pvs \n" ); + mexPrintf("Input: 'monitorStop', [handle/pv] array\n" ); + } + + int * statusArray = new int [numberOfHandles]; + + status=cafe.monitorStop(handleULong, (unsigned int) numberOfHandles, statusArray); + + if (status!=ICAFE_NORMAL) { + for (mwSignedIndex i=0; ial; + al=cafe.getHandleHelper().getMonitorAction(true); + + for (int i=0; ihwm; + vectoract; + + cafe.getHandleHelper().getMonitorHandlesAndActions(hwm,act); + + //return handle + plhs[0] = mxCreateNumericMatrix(1,hwm.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData(plhs[0]); + + //return action + plhs[1] = mxCreateCellMatrix(1,act.size()); + + for (size_t i=0; ihwm; + hwm=cafe.getHandleHelper().getHandlesWithMonitors(); + + //return handle + plhs[0] = mxCreateNumericMatrix(1,hwm.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData(plhs[0]); + + for (int i=0; i2) { + mexPrintf("Ignoring all input arguments to mocha after the first. \n"); + mexPrintf("Method returns all handles and their PV names \n"); + } + + + vector dhV; + vector pvV; + cafe.getHandleHelper().getHandles(dhV,pvV); + //return handle + plhs[0] = mxCreateNumericMatrix(1,dhV.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (size_t i=0; i1) { + mexPrintf("Ignoring all input arguments to mocha after the first. \n"); + mexPrintf("Method returns all handles, their PV names and connection states \n"); + } + + + vector dhV; + vector pvV; + vector connV; + cafe.getHandleHelper().getHandleStates(dhV,pvV,connV); + //return handle + plhs[0] = mxCreateNumericMatrix(1,dhV.size(),mxUINT32_CLASS,mxREAL); + plhs[2] = mxCreateNumericMatrix(1,dhV.size(),mxUINT16_CLASS,mxREAL); + + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (size_t i=0; i2) { + mexPrintf("Ignoring all input arguments to mocha after the first. \n"); + mexPrintf("Method returns all handles within a group \n"); + } + + + ghandle=checkForGroupHandle(prhs[1]); + if(ghandle==0) { + + //fill with data + mexPrintf("Group entered as input argument has not been defined!\n"); + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + + return; + } + + vector dhV = cafe.getHandlesFromWithinGroupV(ghandle); + //return handle + plhs[0] = mxCreateNumericMatrix(1,dhV.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (size_t i=0; i dhV; + vector pvV; + cafe.getHandleHelper().getDisconnectedHandles(dhV,pvV); + //return handle + plhs[0] = mxCreateNumericMatrix(1,dhV.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (size_t i=0; i dhV; + vector pvV; + + cafe.getHandleHelper().getConnectedHandles(dhV,pvV); + //return handle + plhs[0] = mxCreateNumericMatrix(1,dhV.size(),mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + for (size_t i=0; i1) { + mexPrintf("Method limited to one handle/pv only. Reporting on first given"); + } + + handle=checkForHandle(prhs[1]); //NoOpen(prhs[1]); + + if (handle==0) { + mexPrintf("Handle does not exist!\n"); + return; + } + + ChannelRegalia channelInfo; + + status=cafe.getChannelInfo(handle, channelInfo); + + /* + cout << channelInfo.getConnectFlag() << endl; + cout << channelInfo.getHostName() << endl; + cout << channelInfo.getChannelID() << endl; + cout << channelInfo.getClassNameAsString() << endl; + cout << channelInfo.getDataType() << endl; + cout << channelInfo.getNelem() << endl; + cout << channelInfo.getConnectionStateAsString() << endl; + cout << channelInfo.getAccessRead() << endl; + cout << channelInfo.getAccessWrite() << endl; + */ + + if (status != ICAFE_SUCCESS) { + NS_MOCHA::printStatus(status); + return; + } + + + plhs[0]=mxCreateStructMatrix(1, 1, nfieldsInfo, fnamesInfo); + +//const char * fnamesInfo[9] ={"channelID","connectFlag","hostName","dataType", +//"className","accessRead", "accessWrite","nelem","connectionState"}; + + + //fout0 = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + //ulongArray = (uint32_T *) mxGetData (fout1); + //ulongArray[0]=(chid) channelInfo.getChannelID(); + fout0 = mxCreateCellMatrix(1,1); + stringstream ss; + ss << channelInfo.getChannelID(); + string strH = ss.str(); + //mxSetCell (fout0, 0, mxCreateString( strH.c_str())); + + fout0 = mxCreateString( strH.c_str()); + fout1 = mxCreateLogicalScalar(channelInfo.getConnectFlag()); + + fout2 = mxCreateString( channelInfo.getHostName()); + + //fout2 = mxCreateCellMatrix(1,1); + //fout3 = mxCreateCellMatrix(1,1); + //fout4 = mxCreateCellMatrix(1,1); + //fout8 = mxCreateCellMatrix(1,1); + + switch (channelInfo.getDataType()){ + case CAFE_DOUBLE: + fout3 = mxCreateString("DBR_DOUBLE"); + break; + case CAFE_FLOAT: + fout3 = mxCreateString("DBR_FLOAT"); + break; + case CAFE_SHORT: + fout3 = mxCreateString("DBR_SHORT"); + break; + case CAFE_ENUM: + fout3 = mxCreateString("DBR_ENUM"); + break; + case CAFE_CHAR: + fout3 = mxCreateString("DBR_CHAR"); + break; + case CAFE_LONG: + fout3 = mxCreateString("DBR_LONG"); + break; + case CAFE_STRING: + fout3 = mxCreateString("DBR_STRING"); + break; + default: //If not connected for instance + fout3 = mxCreateString("DBR_UNKNOWN"); + break; + } + + + //mxSetCell (fout2, 0, mxCreateString( channelInfo.getHostName())); + //mxSetCell (fout4, 0, mxCreateString( channelInfo.getClassName())); + //mxSetCell (fout8, 0, mxCreateString( channelInfo.getConnectionStateAsString().c_str())); + + fout4 = mxCreateString( channelInfo.getClassNameAsString().c_str()); + fout8 = mxCreateString( channelInfo.getConnectionStateAsString().c_str()); + + fout5 = mxCreateLogicalScalar(channelInfo.getAccessRead()); + fout6 = mxCreateLogicalScalar(channelInfo.getAccessWrite()); + + fout7 = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + + inputULong = (uint32_T *) mxGetData (fout7); + inputULong[0]=channelInfo.getNelem(); + + + + fout16=mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + fHandle = (uint32_T *) mxGetData(fout16); + fHandle[0]=handle; + string s = cafe.getPVFromHandle(handle); + fout17 =mxCreateString( s.c_str() ); + + + + //Prepare struct + + + + mxSetFieldByNumber(plhs[0], 0, 0, fout16); //handle + mxSetFieldByNumber(plhs[0], 0, 1, fout17); //pv + mxSetFieldByNumber(plhs[0], 0, 2, fout0); + mxSetFieldByNumber(plhs[0], 0, 3, fout1); + mxSetFieldByNumber(plhs[0], 0, 4, fout2); + mxSetFieldByNumber(plhs[0], 0, 5, fout3); + mxSetFieldByNumber(plhs[0], 0, 6, fout4); + mxSetFieldByNumber(plhs[0], 0, 7, fout5); + mxSetFieldByNumber(plhs[0], 0, 8, fout6); + mxSetFieldByNumber(plhs[0], 0, 9, fout7); + mxSetFieldByNumber(plhs[0], 0,10, fout8); + + break; + } + + + + + case GET_READ_ACCESS: + { + if (nrhs<2) { + mexPrintf( + "Invalid Number of arguments %d. Input: 'getReadAccess', handle \n", nrhs); + return; + } + handle=checkForHandleNoOpen(prhs[1]); + plhs[0] = mxCreateLogicalScalar(cafe.getReadAccess(handle)); + + break; + } + + case GET_WRITE_ACCESS: + { + if (nrhs<2) { + mexPrintf( + "Invalid Number of arguments %d. Input: 'getWriteAccess', handle \n", nrhs); + return; + } + handle=checkForHandleNoOpen(prhs[1]); + plhs[0] = mxCreateLogicalScalar(cafe.getWriteAccess(handle)); + + break; + } + + + + case FETCH_INDEX_OF_COLLECTION_MEMBER: + { + if (nrhs<3) { + mexPrintf("Invalid Number of argument %d. Input: message, collectionName, deviceName \n", nrhs); + return; + } + + if (!mxIsChar(prhs[1]) ) { + mexPrintf("collectionName does not have a string value \n" ); + return; + } + if (!mxIsChar(prhs[2]) ) { + mexPrintf("deviceName does not have a string value \n" ); + return; + } + + //message groupName + yData = (mxArray *) prhs[1]; + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(yData, groupName, pvLength); + + //message pvname + xData = (mxArray *) prhs[2]; + mxGetString(xData, pv, pvLength); + + long idx=cafe.fetchIndexOfCollectionMember(groupName, pv); + idx=idx+1; + + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + uint32_T * idxArray = (uint32_T *) mxGetData ( plhs[0]); + + idxArray[0]=(uint32_T) idx; //+1 as first element is matlab array indexed by 1 not 0!! + + break; + } + + case FETCH_INDEX_OF_GROUP_MEMBER: + { + if (nrhs<3) { + mexPrintf("Invalid Number of argument %d. Input: message, groupName, pv \n", nrhs); + return; + } + + if (!mxIsChar(prhs[1]) ) { + mexPrintf("groupName does not have a string value \n" ); + return; + } + if (!mxIsChar(prhs[2]) ) { + mexPrintf("pv does not have a string value \n"); + return; + } + + //message groupName + yData = (mxArray *) prhs[1]; + pvLength = PVNAME_MAX_SIZE+1; + mxGetString(yData, groupName, pvLength); + + //message pvname + xData = (mxArray *) prhs[2]; + mxGetString(xData, pv, pvLength); + + long idx=cafe.fetchIndexOfGroupMember(groupName, pv); + idx=idx+1; + + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + uint32_T * idxArray = (uint32_T *) mxGetData ( plhs[0]); + + idxArray[0]=(uint32_T) idx; //+1 as first element is matlab array indexed by 1 not 0!! + + break; + } + case LIST_GROUPS: + { + vector glist; + glist.clear(); + cafe.groupList(glist); + plhs[0] = mxCreateCellMatrix(1,glist.size()); + for (size_t i=0; i glist; + glist.clear(); + cafe.groupMemberList(groupName,glist); + plhs[0] = mxCreateCellMatrix(glist.size(),1); + for (size_t i=0; i inList; + inList.clear(); + + for (mwSignedIndex k=1; k outList= cafe.generateChannelList(inList); + + + plhs[0] = mxCreateCellMatrix(1,outList.size()); + for (size_t i=0; i clist; + clist.clear(); + cafe.collectionList(clist); + plhs[0] = mxCreateCellMatrix(1,clist.size()); + for (size_t i=0; i clist; + clist.clear(); + cafe.collectionMemberList(groupName,clist); + plhs[0] = mxCreateCellMatrix(clist.size(),1); + for (size_t i=0; i/include/config.h is set to false.\n"); + mexPrintf("Please recompile the cafe library with qtxml to use this feature. \n"); + } + #endif + + } + else { + mexPrintf("Collections already loaded from XML. Collection names are:\n"); + + vector clist; + clist.clear(); + cafe.collectionList(clist); + + for (size_t i=0; i/include/config.h is false.\n"); + mexPrintf("Please recompile the cafe library with qtxml to use this feature. \n"); + + } + #endif + + } + else { + mexPrintf("Groups already loaded from XML. Group names are listed.\n"); + mexPrintf("mocha ('listGroupMembers', ) will list the members of the given group. \n"); + vector glist; + glist.clear(); + cafe.groupList(glist); + + for (size_t i=0; i2) { + if( !mxIsLogical(prhs[2]) ) { + mexPrintf("3rd input argument must be of Matlab type Logical, i.e.true/false \n" ); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + status=cafe.getPolicy().setSelfGoverningTimeout(handle,mxIsLogicalScalarTrue(prhs[2])); + } + else { + status=ECAFE_INVALID_HANDLE; + mexPrintf("handle=%d does not exist\n", handle); + } + } + else { + if( !mxIsLogical(prhs[1]) ) { + mexPrintf("If method is meant for all handles, then: \n" ); + mexPrintf("1st input argument must be of Matlab type Logical, i.e.true/false \n" ); + return; + } + status=cafe.getPolicy().setSelfGoverningTimeout(mxIsLogicalScalarTrue(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + + } + + + + + + case SET_TIMEOUT_DEFAULT: + { + if (nrhs>2) { + mexPrintf("Ignoring all input arguments after the 2nd\n"); + } + + if (nrhs>1) { + + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + status=cafe.getPolicy().setTimeoutToDefault(handle); + } + else { + status=ECAFE_INVALID_HANDLE; + } + } + else { + status=cafe.getPolicy().setTimeoutToDefault(); + + } + + plhs[0] = mxCreateDoubleMatrix(1,2,mxREAL); + doubleArray = mxGetPr ( plhs[0]); + + //Return default timeout + if (status==ICAFE_NORMAL) { + + + double ax=0,bx=0; + if (nrhs>1 && handle!=0) { + + cafe.getPolicy().getTimeout(handle,ax,bx); + doubleArray[0]=ax; + doubleArray[1]=bx; + break; + } + else { + double cx=0,dx=0; + cafe.getPolicy().getTimeoutRange(ax,bx,cx,dx); + + doubleArray[0]=min(ax,bx); //min put (min/max should be same) + doubleArray[1]=min(cx,dx); //min get (min/max should be same) + break; + } + } + else { + mexPrintf("Error in setting timeouts to default value!\n"); + doubleArray[0]=-1; + doubleArray[1]=-1; + } + break; + + } + + case SET_TIMEOUT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle, timeout \n", nrhs); + mexPrintf("or message, timeout (applied to all handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n" ); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + status=cafe.getPolicy().setTimeout(handle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_HANDLE; + } + } + else { + status=cafe.getPolicy().setTimeout(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + case SET_TIMEOUT_PUT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle, timeout (for put) \n", nrhs); + mexPrintf("or message, timeout (for put, applied to all handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n" ); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + status=cafe.getPolicy().setTimeoutPut(handle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_HANDLE; + } + } + else { + status=cafe.getPolicy().setTimeoutPut(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + + case SET_TIMEOUT_GET: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle, timeout (for get) \n", nrhs); + mexPrintf("or message, timeout (for get, applied to all handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n"); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + status=cafe.getPolicy().setTimeoutGet(handle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_HANDLE; + } + } + else { + status=cafe.getPolicy().setTimeoutGet(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + + case GET_TIMEOUT: + { + + plhs[0] = mxCreateDoubleMatrix(1,2,mxREAL); + doubleArray = mxGetPr ( plhs[0]); + + double ax=0,bx=0; + if (nrhs>1) { + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + cafe.getPolicy().getTimeout(handle,ax,bx); + doubleArray[0]=ax; + doubleArray[1]=bx; + break; + } + else { + mexPrintf("handle=%d does not exist", handle); + } + } + else { + double cx=0,dx=0; + cafe.getPolicy().getTimeoutRange(ax,bx,cx,dx); + + doubleArray[0]=min(ax,bx); //min put + doubleArray[1]=min(cx,dx); //min,get + break; + } + doubleArray[0]=0; + doubleArray[1]=0; + break; + } + + + case SET_SG_SELF_GOVERNING_TIMEOUT: + { + + + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, gHandle, true/false \n", nrhs); + mexPrintf("or message, true/false (applied to all group handles) \n"); + + return; + } + + if (nrhs>2) { + if( !mxIsLogical(prhs[2]) ) { + mexPrintf("3rd input argument must be of Matlab type Logical, i.e.true/false \n" ); + return; + } + + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + status=cafe.getPolicy().setSGSelfGoverningTimeout(ghandle,mxIsLogicalScalarTrue(prhs[2])); + } + else { + status=ECAFE_INVALID_GROUP_HANDLE; + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + if( !mxIsLogical(prhs[1]) ) { + mexPrintf("If method is meant for all handles, then: \n" ); + mexPrintf("1st input argument must be of Matlab type Logical, i.e.true/false \n" ); + return; + } + status=cafe.getPolicy().setSGSelfGoverningTimeout(mxIsLogicalScalarTrue(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + + } + + + + + case SET_SG_TIMEOUT_DEFAULT: + { + + if (nrhs>2) { + mexPrintf("Ignoring all input arguments after the 2nd\n"); + } + + if (nrhs>1) { + + + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + status=cafe.getPolicy().setSGTimeoutToDefault(ghandle); + } + else { + status=ECAFE_INVALID_GROUP_HANDLE; + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + status=cafe.getPolicy().setSGTimeoutToDefault(); + } + + plhs[0] = mxCreateDoubleMatrix(1,2,mxREAL); + doubleArray = mxGetPr ( plhs[0]); + + //Return default timeout + if (status==ICAFE_NORMAL) { + + + double ax=0,bx=0; + if (nrhs>1 && ghandle!=0) { + + cafe.getPolicy().getSGTimeout(ghandle,ax,bx); + doubleArray[0]=ax; + doubleArray[1]=bx; + break; + } + else { + double cx=0,dx=0; + cafe.getPolicy().getSGTimeoutRange(ax,bx,cx,dx); + + doubleArray[0]=min(ax,bx); //min put (min/max should be same) + doubleArray[1]=min(cx,dx); //min get (min/max should be same) + break; + } + } + else { + mexPrintf("Error in setting timeouts to default value!\n"); + doubleArray[0]=-1; + doubleArray[1]=-1; + } + break; + + } + + case SET_SG_TIMEOUT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, gHandle, timeout \n", nrhs); + mexPrintf("or message, timeout (applied to all group handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n" ); + return; + } + + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + status=cafe.getPolicy().setSGTimeout(ghandle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_GROUP_HANDLE; + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + status=cafe.getPolicy().setSGTimeout(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + case SET_SG_TIMEOUT_PUT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, gHandle, timeout (for put) \n", nrhs); + mexPrintf("or message, timeout (for put, applied to all group handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n" ); + return; + } + + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + status=cafe.getPolicy().setSGTimeoutPut(ghandle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_GROUP_HANDLE; + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + status=cafe.getPolicy().setSGTimeoutPut(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + + case SET_SG_TIMEOUT_GET: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, gHandle, timeout (for get) \n", nrhs); + mexPrintf("or message, timeout (for get, applied to all group handles) \n"); + + return; + } + + if (nrhs>2) { + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("Timeout does not have a numeric value \n"); + return; + } + + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + status=cafe.getPolicy().setSGTimeoutGet(ghandle,mxGetScalar(prhs[2])); + } + else { + status=ECAFE_INVALID_GROUP_HANDLE; + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + status=cafe.getPolicy().setSGTimeoutGet(mxGetScalar(prhs[1])); + } + //status + plhs[0] = mxCreateNumericMatrix(1,1,mxINT32_CLASS,mxREAL); + longStatus = (int32_T *) mxGetData ( plhs[0]); + longStatus[0]=status; + break; + } + + + case GET_SG_TIMEOUT: + { + + plhs[0] = mxCreateDoubleMatrix(1,2,mxREAL); + doubleArray = mxGetPr ( plhs[0]); + + double ax=0,bx=0; + if (nrhs>1) { + ghandle=checkForGroupHandleNoOpen(prhs[1]); + if (ghandle != 0) { + cafe.getPolicy().getSGTimeout(ghandle,ax,bx); + doubleArray[0]=ax; + doubleArray[1]=bx; + break; + } + else { + mexPrintf("ghandle=%d does not exist\n", ghandle); + } + } + else { + double cx=0,dx=0; + cafe.getPolicy().getSGTimeoutRange(ax,bx,cx,dx); + + doubleArray[0]=min(ax,bx); //min put + doubleArray[1]=min(cx,dx); //min,get + break; + } + doubleArray[0]=0; + doubleArray[1]=0; + break; + } + + case SET_NELEM: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle, nelem (else to native if not given) \n", nrhs); + return; + } + + uint32_T nDataTransfer= 0; + + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("nelem does not have a numeric value \n"); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + if (cacheFlag) { + if (nrhs >2) { + nDataTransfer=cafe.getHandleHelper().setNelemToRetrieveFromCache(handle,mxGetScalar(prhs[2])); + } + else if (nrhs==2) { + nDataTransfer=cafe.getHandleHelper().setNelemToRetrieveFromCache(handle); + } + //mexPrintf("nDataTransfer for Cache = %d", nDataTransfer); + } + else { + if (nrhs >2) { + nDataTransfer=cafe.getHandleHelper().setNelem(handle,mxGetScalar(prhs[2])); + } + else if (nrhs==2) { + nDataTransfer=cafe.getHandleHelper().setNelem(handle); + } + + } + } + + //nDataTransfer + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nDataTransfer; + break; + } + + case SET_OFFSET: + { + if (nrhs<3) { + mexPrintf("Invalid Number of argument %d. Input: message, handle, offset \n", nrhs); + return; + } + + uint32_T nOffset= 0; + + if (!mxIsNumeric(prhs[2]) ) { + mexPrintf("offset does not have a numeric value \n" ); + return; + } + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + nOffset=cafe.getHandleHelper().setOffset(handle,mxGetScalar(prhs[2])); + } + + + //nOffset + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nOffset; + break; + } + + case GET_NELEM_NATIVE: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle\n", nrhs); + return; + } + + uint32_T nElements= 0; + + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + nElements=cafe.getHandleHelper().getNelemNative(handle); + } + + + //nElements + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nElements; + break; + } + + case GET_NELEM_CLIENT: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle\n", nrhs); + return; + } + + uint32_T nElements= 0; + + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + nElements=cafe.getHandleHelper().getNelemClient(handle); + } + + + //nElements + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nElements; + break; + } + + + case GET_NELEM_REQUEST: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle\n", nrhs); + return; + } + + uint32_T nElements= 0; + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + if(cacheFlag) { + nElements=cafe.getHandleHelper().getNelemToRetrieveFromCache(handle); + } + else { + nElements=cafe.getHandleHelper().getNelemRequest(handle); + } + } + + + //nElements + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nElements; + break; + } + + + case GET_NELEM: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle\n", nrhs); + return; + } + + uint32_T nElements[3]; // client, native, requested + nElements[0]=0; nElements[1]=0; nElements[2]=0; + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + cafe.getHandleHelper().getNelem(handle, nElements[0], nElements[1], nElements[2]); + } + + + //nElements + plhs[0] = mxCreateNumericMatrix(1,3,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData ( plhs[0]); + ulongArray[0]= nElements[0]; + ulongArray[1]= nElements[1]; + ulongArray[2]= nElements[2]; + break; + } + + + case GET_OFFSET: + { + if (nrhs<2) { + mexPrintf("Invalid Number of argument %d. Input: message, handle\n", nrhs); + return; + } + + uint32_T nOffset= 0; + + handle=checkForHandleNoOpen(prhs[1]); + if (handle != 0) { + nOffset=cafe.getHandleHelper().getOffset(handle); + } + + //nOffset + plhs[0] = mxCreateNumericMatrix(1,1,mxUINT32_CLASS,mxREAL); + ulongArray = (uint32_T *) mxGetData (plhs[0]); + ulongArray[0]= nOffset; + break; + } + + + + + default: + char * _messOriginal=messOriginal; + cafe.getHandleHelper().removeLeadingAndTrailingSpaces(_messOriginal,messOriginal); + mexPrintf("%s %s\n","Unknown message--->", messOriginal); + plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL); + doubleArray = mxGetPr ( plhs[0]); + doubleArray[0]=numeric_limits::signaling_NaN(); + break; + + }//End Big Switch + +return; +} + + + diff --git a/makefile b/makefile new file mode 120000 index 0000000..b5a1cf6 --- /dev/null +++ b/makefile @@ -0,0 +1 @@ +makefile_rel_2014_1.3 \ No newline at end of file diff --git a/makefile_rel_2014_1.3 b/makefile_rel_2014_1.3 new file mode 100644 index 0000000..fac5503 --- /dev/null +++ b/makefile_rel_2014_1.3 @@ -0,0 +1,124 @@ +# +# Jan Chrin +# New Version: June 2016 +# +# makefile to build mocha mex file +# printenv | grep MATLAB to reveal your MATLAB Directory +# +# e.g. on sf-lc we have +# MATLAB=/afs/psi.ch/sys/linux/opt/matlab/2015a.x86_64 +# +# local executables are built in ./${EPICS_HOST_ARCH}/$(MVER) +# where the MATLAB version is grepped from $(MATLAB) + +MATLAB_ROOT=${MATLAB} +MATLAB_VERSION=$(notdir $(MATLAB_ROOT)) + +##### CHANGE AS APPROPRIATE ################# +#Mocha Version to install +MOCHA_VERSION=mocha-1.3.0-final-1 +#CAFE version to link to +CAFE_VERSION=cafe-1.3.0-final-1 + + + +EPICS_BASE=${EPICS}/base +#CAFE project base +CAFE_BASE=/opt/gfa/cafe +CAFE_MOCHA_BASE=${CAFE_BASE}/mocha +#CAFE_CPP_BASE=/afs/psi.ch/project/cafe/gitlab/CAFE/cpp +CAFE_CPP_BASE=$(CAFE_BASE)/cpp/$(CAFE_VERSION) + + +BOOST_BASE=${CAFE_BASE}/boost/boost_1_61_0/include +BOOST_LIB=/afs/psi.ch/project/zeromq/devl/mate/deps/boost/lib + +QT_LIB=/usr/lib64 + +INSTALL_MOCHA_LIBDIR= $(CAFE_MOCHA_BASE)/$(MOCHA_VERSION)/lib/$(MATLAB_VERSION) +############################################# + + +#First deteremine if we are on a 32/64 bit machine +#as mex file extensions are named differently +pattern64=x86_64 +pattern32=i386 + +PWD=$(shell pwd) + #hardware platform + HW=$(shell uname -i) + ifeq ($(pattern64),$(findstring $(pattern64), $(HW))) + MEXE=mexa64 + MATLAB_LIB = $(MATLAB_ROOT)/bin/glnxa64 + else + ifeq ($(pattern32),$(findstring $(pattern32), $(HW))) + MEXE=mexglx + MATLAB_LIB = $(MATLAB_ROOT)/bin/glnxa86 + endif + endif + + +INSTALL_PATH?=$(INSTALL_MOCHA_LIBDIR) +OBJ_DIR= ${EPICS_HOST_ARCH}/$(MATLAB_VERSION) + +INCLUDEPATH_MOCHA += -I$(MATLAB_ROOT)/extern/include \ + -I$(CAFE_CPP_BASE)/include -I./ \ + -I$(EPICS_BASE)/include -I$(EPICS_BASE)/include/os/Linux + + +INCLUDEPATH_MACHINETTA += $(INCLUDEPATH_MOCHA) -I$(BOOST_BASE) -I$(BOOST_BASE)/boost + + +LIB_DIR += \ + -L$(EPICS_BASE)/lib/${EPICS_HOST_ARCH} \ + -Wl,-rpath,$(EPICS_BASE)/lib/${EPICS_HOST_ARCH} \ + -L$(MATLAB_LIB) -Wl,-rpath,$(MATLAB_LIB) \ + -L$(CAFE_CPP_BASE) \ + -Wl,-rpath,$(CAFE_CPP_BASE) \ + -L$(QT_LIB) -Wl,-rpath,$(QT_LIB) + + +LIBS += -ldl -lca -lCom -lmx -lmex -lmat -lQtCore -lQtXml + +LIB_INSTALL = $(LIB_DIR) -L$(INSTALL_PATH) -Wl,-rpath,$(INSTALL_PATH) + +LIB_LOCAL = $(LIB_DIR) + + +CAFE_OBJS_DIR = $(CAFE_BASE)/cpp/$(CAFE_VERSION)/lib/libcafe.a + +# MATLAB Versions 2014 onwards, use +# LDFLAGS='$(LIB_LOCAL) $(LIBS) instead of $(LIB_LOCAL) $(LIBS) +# LDFLAGS='$(LIB_LOCAL) $(LIBS) instead of $(LIB_INSTALL) $(LIBS) + + +$(OBJ_DIR)/mocha.$(MEXE): mocha.cpp $(OBJ_DIR)/macchinettaSwitch.o + mex -largeArrayDims GCC='/usr/bin/gcc' CXXFLAGS='-v -largeArrayDims -ansi -fexceptions -fPIC -fno-omit-frame-pointer -pthread' \ + mocha.cpp $(OBJ_DIR)/macchinettaSwitch.o $(CAFE_OBJS_DIR) -outdir $(OBJ_DIR) -output mocha.$(MEXE) \ + $(INCLUDEPATH_MOCHA) \ + LDFLAGS='$(LIB_LOCAL) $(LIBS)' + + +$(OBJ_DIR)/macchinettaSwitch.o: macchinettaSwitch.cpp macchinettaHelper.h \ + macchinetta.h containerMochaccino.h + mex GCC='/usr/bin/g++' CXXFLAGS='-v -largeArrayDims -ansi -fexceptions -fPIC -fno-omit-frame-pointer -pthread' \ + -largeArrayDims -c macchinettaSwitch.cpp $(INCLUDEPATH_MACHINETTA) -outdir $(OBJ_DIR) + + +install: $(OBJ_DIR)/mocha.$(MEXE) + mkdir -p $(INSTALL_PATH) + mex -largeArrayDims GCC='/usr/bin/gcc' CXXFLAGS='-v -largeArrayDims -ansi -fexceptions -fPIC -fno-omit-frame-pointer -pthread' \ + mocha.cpp $(OBJ_DIR)/macchinettaSwitch.o $(CAFE_OBJS_DIR) -outdir $(INSTALL_PATH) -output mocha.$(MEXE) \ + $(INCLUDEPATH_MOCHA) \ + LDFLAGS='$(LIB_INSTALL) $(LIBS)' + cp example.m $(INSTALL_PATH) + cp scripts/*.m $(INSTALL_PATH) + cp scripts/test.xml $(INSTALL_PATH) + +install_lib: $(OBJ_DIR)/libmacchinetta.so + mkdir -p $(INSTALL_PATH) + cp $(OBJ_DIR)/libmacchinetta.so $(INSTALL_PATH) + +clean: + rm -f $(OBJ_DIR)/*.o $(OBJ_DIR)/*.so $(OBJ_DIR)/*.$(MEXE) + diff --git a/makefile_rel_2014_win.make b/makefile_rel_2014_win.make new file mode 100644 index 0000000..38c712c --- /dev/null +++ b/makefile_rel_2014_win.make @@ -0,0 +1,70 @@ +MATLAB_ROOT=C:\'Program Files'\MATLAB\R2016b_x64 +MEXE=mexw64 +#c:\local\boost_1_62_0\ + +INCLUDES = -IC:\CAFE\CAFE\cpp\include -IC:\CAFE\CAFE\cpp -IC:\local\boost_1_62_0 \ +-IC:\local\boost_1_62_0\boost -IC:\epics\base-3.14.12.5\include -IC:\epics\base-3.14.12.5\include\os\WIN32 \ +-I"C:\Program Files\MATLAB\R2016b_x64\extern\include" \ +-Ic:\Qt\qt-4.8.6-x64-msvc2010\include -Ic:\Qt\qt-4.8.6-x64-msvc2010\include\QtCore -Ic:\Qt\qt-4.8.6-msvc2010\include\QtXml + +CXX=cl +CXXFLAGS = /W4 /EHsc +OUTPUT_OPTION = /o $@ +LIB_LOCAL = C:\epics\base-3.14.12.5\lib\windows-x64\Com.lib C:\epics\base-3.14.12.5\lib\windows-x64\ca.lib \ +C:\CAFE\CAFE\cpp\cafe.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_thread-vc100-mt-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_system-vc100-mt-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-1_62.lib \ +C:\Qt\Qt-4.8.6-msvc2010\lib\QtCore4.lib C:\Qt\tq-4.8.6-msvc2010\lib\QtXml4.lib +#"C:\Program Files\MATLAB\R2016b_x64\extern\lib\win64\microsoft\libmat.lib" \ +#"C:\Program Files\MATLAB\R2016b_x64\extern\lib\win64\microsoft\libmex.lib" \ +#"C:\Program Files\MATLAB\R2016b_x64\extern\lib\win64\microsoft\libmx.lib" + +LIB_CAFE=C:\CAFE\CAFE\cpp\cafe.lib +LIB_BOOST =C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-1_62.lib + +LIB_BOOST2=C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-s-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_thread-vc100-mt-s-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_system-vc100-mt-s-1_62.lib \ +C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-s-1_62.lib + +#LIB_BOOST2=C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_thread-vc100-mt-s-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_system-vc100-mt-s-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-s-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-s-1_62.lib + +#LIB_BOOST=C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_thread-vc100-mt-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_system-vc100-mt-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_date_time-vc100-mt-1_62.lib \ +#C:\local\boost_1_62_0\lib64-msvc-10.0\libboost_chrono-vc100-mt-1_62.lib + +LIB_QT=C:\Qt\Qt-4.8.6-x64-msvc2010\lib\QtCore4.lib C:\Qt\qt-4.8.6-x64-msvc2010\lib\QtXml4.lib + +LIB_EPICS=C:\epics\base-3.14.12.5\lib\windows-x64\Com.lib C:\epics\base-3.14.12.5\lib\windows-x64\ca.lib + +OBJ_DIR=windows-x64 + +CAFE_OBJS = C:\CAFE\CAFE\cpp\src\cafeCache.obj C:\CAFE\CAFE\cpp\src\cafeGroup.obj C:\CAFE\CAFE\cpp\src\cafe.obj C:\CAFE\CAFE\cpp\src\cafeVectors.obj \ + C:\CAFE\CAFE\cpp\src\cafeXML.obj C:\CAFE\CAFE\cpp\src\callbackHandlerCreate.obj C:\CAFE\CAFE\cpp\src\callbackHandlerMonitor.obj \ + C:\CAFE\CAFE\cpp\src\conduitGroup.obj C:\CAFE\CAFE\cpp\src\conduit.obj \ + C:\CAFE\CAFE\cpp\src\connectCallbacks.obj C:\CAFE\CAFE\cpp\src\connectGroup.obj \ + C:\CAFE\CAFE\cpp\src\connect.obj C:\CAFE\CAFE\cpp\src\exceptionsHelper.obj C:\CAFE\CAFE\cpp\src\granules.obj C:\CAFE\CAFE\cpp\src\handleHelper.obj \ + C:\CAFE\CAFE\cpp\src\helper.obj \ + C:\CAFE\CAFE\cpp\src\loadCollectionXMLParser.obj C:\CAFE\CAFE\cpp\src\loadGroupXMLParser.obj C:\CAFE\CAFE\cpp\src\methodCallbacks.obj \ + C:\CAFE\CAFE\cpp\src\policyHelper.obj \ + C:\CAFE\CAFE\cpp\src\restorePVGroupXMLParser.obj C:\CAFE\CAFE\cpp\src\transpose.obj + +#\NODEFAULTLIB +$(OBJ_DIR)\mocha.$(MEXE): mocha.cpp $(OBJ_DIR)\macchinettaSwitch.obj + "C:\Program Files\MATLAB\R2016b_x64\bin\win64\mex" -v COMPFLAGS="$(COMPFLAGS) -Wall" mocha.cpp $(OBJ_DIR)/macchinettaSwitch.obj -DDB_TEXT_GLBLSOURCE -DMSCC -DWIN32 -DWIN64 -largeArrayDims $(INCLUDES) $(LIB_EPICS) $(LIB_CAFE) $(LIB_BOOST) $(LIB_BOOST2) $(LIB_QT) \ + -outdir $(OBJ_DIR) -output mocha.$(MEXE) + +$(OBJ_DIR)\macchinettaSwitch.obj: macchinettaSwitch.cpp macchinettaHelper.h \ + macchinetta.h containerMochaccino.h + "C:\Program Files\MATLAB\R2016b_x64\bin\win64\mex" -largeArrayDims \ + -c macchinettaSwitch.cpp $(INCLUDES) -outdir $(OBJ_DIR) + +clean: + rm -f $(OBJ_DIR)/*.obj $(OBJ_DIR)/*.$(MEXE) + diff --git a/matlab.sh b/matlab.sh new file mode 100755 index 0000000..312a4db --- /dev/null +++ b/matlab.sh @@ -0,0 +1,2 @@ +/opt/psi/Cafe/cafe-matlab.sh -v 2015a +matlab & diff --git a/mex_C++_win64.xml b/mex_C++_win64.xml new file mode 100644 index 0000000..2f98f99 --- /dev/null +++ b/mex_C++_win64.xml @@ -0,0 +1,146 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mocha.cpp b/mocha.cpp new file mode 100644 index 0000000..bf8376f --- /dev/null +++ b/mocha.cpp @@ -0,0 +1,12 @@ +/* Source of MEX-file which will call the wrapper shared library. + We moved the previous content of the mexFunction to the wrapper library and now + call the function in the wrapper library instead. +*/ +#include "macchinetta.h" + +extern void _main(); + +void mexFunction(int nlhs,mxArray *plhs[],int nrhs, const mxArray *prhs[]) +{ + macchinettaFunction(nlhs,plhs,nrhs,prhs); +} diff --git a/monAction.m b/monAction.m new file mode 100644 index 0000000..2bc5fad --- /dev/null +++ b/monAction.m @@ -0,0 +1,16 @@ +function varargout = monActionLocal(varargin) +disp('monActionLocal called for:'); +pvName=mocha('getPVFromHandle', varargin{1}); +disp(pvName); +X=['Handle =', num2str(varargin{1})]; +disp(X); + +%[varargout{1} varargout{2}] = mocha ('getCache', varargin{1}); +[var1,var2]=mocha ('getCache', varargin{1}); +[s,t]=mocha('getStatus', varargin{1}); +%X=['Value=', num2str(varargout{1}), ' Status=', num2str(s), ' [',t(1), ' ', t(2),']']; +X=['Value =', num2str(var1)]; +Y=['Status=', num2str(s)]; +disp(X) +disp(Y) +disp([t(1),t(2)]) diff --git a/monActionLocal.m b/monActionLocal.m new file mode 120000 index 0000000..8bb85ae --- /dev/null +++ b/monActionLocal.m @@ -0,0 +1 @@ +monAction.m \ No newline at end of file diff --git a/monitorAction.m b/monitorAction.m new file mode 120000 index 0000000..e07643b --- /dev/null +++ b/monitorAction.m @@ -0,0 +1 @@ +scripts/monitorAction.m \ No newline at end of file diff --git a/pvtable.m b/pvtable.m new file mode 120000 index 0000000..b30e72e --- /dev/null +++ b/pvtable.m @@ -0,0 +1 @@ +scripts/pvtable.m \ No newline at end of file diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..84d0354 --- /dev/null +++ b/readme.txt @@ -0,0 +1,115 @@ +MATLAB Compiler + +1. Prerequisites for Deployment + +. Verify the MATLAB Runtime is installed and ensure you + have installed version 9.0.1 (R2016a). + +. If the MATLAB Runtime is not installed, do the following: + (1) enter + + >>mcrinstaller + + at MATLAB prompt. The MCRINSTALLER command displays the + location of the MATLAB Runtime installer. + + (2) run the MATLAB Runtime installer. + +Or download the Linux 64-bit version of the MATLAB Runtime for R2016a +from the MathWorks Web site by navigating to + + http://www.mathworks.com/products/compiler/mcr/index.html + + +For more information about the MATLAB Runtime and the MATLAB Runtime installer, see +Package and Distribute in the MATLAB Compiler documentation +in the MathWorks Documentation Center. + + +2. Files to Deploy and Package + +Files to package for Standalone +================================ +-exampleFcn +-run_exampleFcn.sh (shell script for temporarily setting environment variables and + executing the application) + -to run the shell script, type + + ./run_exampleFcn.sh + + at Linux or Mac command prompt. is the directory + where version 9.0.1 of the MATLAB Runtime is installed or the directory where + MATLAB is installed on the machine. is all the + arguments you want to pass to your application. For example, + + If you have version 9.0.1 of the MATLAB Runtime installed in + /mathworks/home/application/v901, run the shell script as: + + ./run_exampleFcn.sh /mathworks/home/application/v901 + + If you have MATLAB installed in /mathworks/devel/application/matlab, + run the shell script as: + + ./run_exampleFcn.sh /mathworks/devel/application/matlab +-MCRInstaller.zip + -if end users are unable to download the MATLAB Runtime using the above + link, include it when building your component by clicking + the "Runtime downloaded from web" link in the Deployment Tool +-This readme file + +3. Definitions + +For information on deployment terminology, go to +http://www.mathworks.com/help. Select MATLAB Compiler > +Getting Started > About Application Deployment > +Deployment Product Terms in the MathWorks Documentation +Center. + + +4. Appendix + +A. Linux x86-64 systems: +In the following directions, replace MCR_ROOT by the directory where the MATLAB Runtime + is installed on the target machine. + +(1) Set the environment variable XAPPLRESDIR to this value: + + MCR_ROOT/v901/X11/app-defaults + + +(2) If the environment variable LD_LIBRARY_PATH is undefined, set it to the concatenation + of the following strings: + + MCR_ROOT/v901/runtime/glnxa64: + MCR_ROOT/v901/bin/glnxa64: + MCR_ROOT/v901/sys/os/glnxa64: + MCR_ROOT/v901/sys/opengl/lib/glnxa64 + + If it is defined, set it to the concatenation of these strings: + + ${LD_LIBRARY_PATH}: + MCR_ROOT/v901/runtime/glnxa64: + MCR_ROOT/v901/bin/glnxa64: + MCR_ROOT/v901/sys/os/glnxa64: + MCR_ROOT/v901/sys/opengl/lib/glnxa64 + + For more detail information about setting the MATLAB Runtime paths, see Package and + Distribute in the MATLAB Compiler documentation in the MathWorks Documentation Center. + + + + NOTE: To make these changes persistent after logout on Linux + or Mac machines, modify the .cshrc file to include this + setenv command. + NOTE: The environment variable syntax utilizes forward + slashes (/), delimited by colons (:). + NOTE: When deploying standalone applications, it is possible + to run the shell script file run_exampleFcn.sh + instead of setting environment variables. See + section 2 "Files to Deploy and Package". + + + + + + diff --git a/run_example.sh b/run_example.sh new file mode 100755 index 0000000..c166b11 --- /dev/null +++ b/run_example.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# script for execution of deployed applications +# +# Sets up the MATLAB Runtime environment for the current $ARCH and executes +# the specified command. +# +exe_name=$0 +exe_dir=`dirname "$0"` +echo "------------------------------------------" +if [ "x$1" = "x" ]; then + echo Usage: + echo $0 \ args +else + echo Setting up environment variables + MCRROOT="$1" + echo --- + LD_LIBRARY_PATH=.:${MCRROOT}/runtime/glnxa64 ; + LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/bin/glnxa64 ; + LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/sys/os/glnxa64; + LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${MCRROOT}/sys/opengl/lib/glnxa64; + export LD_LIBRARY_PATH; + echo LD_LIBRARY_PATH is ${LD_LIBRARY_PATH}; + shift 1 + args= + while [ $# -gt 0 ]; do + token=$1 + args="${args} \"${token}\"" + shift + done + eval "\"${exe_dir}/example\"" $args +fi +exit + diff --git a/scripts/cadelmon.m b/scripts/cadelmon.m new file mode 100755 index 0000000..9021cfe --- /dev/null +++ b/scripts/cadelmon.m @@ -0,0 +1,23 @@ +function cadelmon(channel) +% cadelmon('channel') +% Deletes monitor callback on EPICS channel + +% translate pv name to handle +if ischar(channel) + pv = mcaisopen(channel); + if pv == 0 + return; + end +elseif isnumeric(channel) + pv = channel; +else + error ('first argument must be channel name or handle'); +end + +% delete monitor +mcaclearmon(pv); + +% if no monitor left then stop monitoring +if isempty(mcamon) && mcamontimer + mcamontimer('stop') +end diff --git a/scripts/cafe-matlab.sh b/scripts/cafe-matlab.sh new file mode 100755 index 0000000..2571013 --- /dev/null +++ b/scripts/cafe-matlab.sh @@ -0,0 +1,244 @@ +#! /bin/bash + +# User to set the default MATLAB version here +# This default is ONLY activated +# (1) in the absence of the relevant input argument, and +# (2) if matlab is not already pre-loaded on your system +MATLAB_DEFAULT=2016b + +# cafe-matlab.sh script to enable use of the mocha mex-file +# The script executes the command: module load cafe-matlab/ +# which will pre-pend the $MATLABPATH environment variable with the location +# of the matching mocha mex-file +# Jan Chrin, 5 April 2017 +# +# Usage: cafe-matlab.sh -v -d -s +# where the input key value pairs are **optional** +# Examples of usage: +# (1) Use mocha with MATLAB version 2016b but do not start matlab [-s false is default] +# cafe-matlab.sh -v 2016b +# (2) Use mocha with MATLAB version 2016b and start matlab +# cafe-matlab.sh -v 2016b -s true +# (3) Use mocha with MATLAB version given by MATLAB_DEFAULT in script +# cafe-matlab.sh -v default -s true +# cafe-matlab.sh --usedefault [equivalent -v default -s false] +# (4) Use mocha with preloaded matlab (else if none, then that given by -d option else MATLAB_DEFAULT ) +# cafe-matlab.sh -d 2016b +# cafe-matlab.sh --preloaded [equivalent to -v preloaded -s false] + + +# If no instruction to the matlab version is given by the user then the procedure is: +# (1) If MATLAB is already loaded ($MATLAB has automatically been set), +# then the location of the corresponding mex-file will be pre-pended to $MATLABPATH +# (2) if MATLAB is **not** already loaded, then the script will use a default MATLAB +# version, as given by the -d option else that given by $MATLAB_DEFAULT in the above. +# and the location of the corresponding mex-file will be pre-pended to $MATLABPATH + +PRINT_INFO=false + +# Reset (required) +MATLAB_START=false +MATLAB_REQUESTED= + + +MATLAB_V=$MATLAB_VERSION + +#For MATLAB version 2015a and earlier +if [ ! $MATLAB_VERSION ] +then + if [ ${MATLAB} ] + then + MATLAB_EXT=${MATLAB##*/} + #use IFS to split string into arrays with . being the delimeter + IFS='.' read -ra NAMES <<< $MATLAB_EXT + MATLAB_V=${NAMES[0]} + #echo $MATLAB_EXT + fi +fi + + + +# Loop round input arguments +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -v|-V|--version|--Version) + c=$2 + MATLAB_REQUESTED=${c##*/} + if [ $PRINT_INFO = true ] + then + echo MATLAB VERSION REQUESTED = "${MATLAB_REQUESTED}" + fi + shift + ;; + -s|-S|--start|--Start) + MATLAB_START="$2" + if [ $PRINT_INFO = true ] + then + echo MATLAB START = "${MATLAB_START}" + fi + shift + ;; + -d|-D|--default|--Default) + MATLAB_DEFAULT="$2" + if [ $PRINT_INFO = true ] + then + echo MATLAB DEFAULT = "${MATLAB_DEFAULT}" + fi + shift + ;; + --preloaded) + MATLAB_REQUESTED="preloaded" + MATLAB_START=false + if [ $PRINT_INFO = true ] + then + echo MATLAB VERSION REQUESTED = "${MATLAB_REQUESTED}" + echo MATLAB START = "${MATLAB_START}" + fi + ;; + --usedefault) + MATLAB_REQUESTED="default" + MATLAB_START=false + if [ $PRINT_INFO = true ] + then + echo MATLAB VERSION REQUESTED = "${MATLAB_REQUESTED}" + echo MATLAB START = "${MATLAB_START}" + fi + ;; + -h|-H|--help|--Help) + echo '*********************************************************' + echo Usage: cafe-matlab.sh + echo '-v If omitted, uses pre-loaded matlab version, else default version' + echo '-d Override default version to be used if matlab module not already loaded' + echo '-s Whether or not to start matlab; default is false ' + echo '--show Shows matlab version currently loaded and the script default version' + echo '*********************************************************' + echo 'e.g. cafe-matlab.sh -v 2016b -s false % use matlab/2016b' + echo 'e.g. cafe-matlab.sh -d 2016b -s false % Use pre-loaded matlab module else matlab/2016b' + echo 'e.g. cafe-matlab.sh % Use pre-loaded matlab module, else that given in script' + return 2> /dev/null || exit + ;; + --show) + echo '*********************************************************' + if [ $MATLAB_V ] + then + echo MATLAB VERSION CURRENTLY LOADED IS ${MATLAB_V} + else + echo 'MATLAB MODULE NOT CURRENTLY LOADED' + fi + echo THE SCRIPT DEFAULT IS $MATLAB_DEFAULT BUT WILL ONLY BE ACTIVATED IF MATLAB + echo 'IS NOT ALREADY LOADED OR OTHERWISE SPECIFIED BY THE -v OPTION' + echo '$MATLAB_DEFAULT CAN BE OVERRIDDEN USING THE -d OPTION' + echo '*********************************************************' + return 2> /dev/null || exit + ;; + *) + echo Unknown input key: "$key" + echo Usage: 'cafe-matlab -v -s ' + echo where '-s true' will start matlab - default is false + echo Executing script with default options + # unknown option + ;; +esac +shift # +done + + + +if [ $MATLAB_REQUESTED ] +then + + if [ $MATLAB_REQUESTED == 'default' ] + then + MATLAB_REQUESTED=$MATLAB_DEFAULT + fi + if [ $MATLAB_REQUESTED == 'preloaded' ] + then + MATLAB_REQUESTED= #leave empty + fi + +fi + + +#echo $MATLAB_V +#echo $MATLAB_REQUESTED +#echo $MATLAB_DEFAULT + +module use Cafe + +#if -v is given then load MATLAB_REQUESTED +#if -v not given or if -v preloaded, then load MATLAB_V +#else load MATLAB_DEFAULT + +if [ $MATLAB_REQUESTED ] +then + + if test -f "/opt/psi/Cafe/modulefiles/cafe-matlab/${MATLAB_REQUESTED}" + then + + #unload removes $MATLAB_VERSION + module unload matlab + module unload cafe-matlab + module load cafe-matlab/${MATLAB_REQUESTED} + if [ $PRINT_INFO = true ] + then + echo "Using requested version: matlab/$MATLAB_REQUESTED" + fi + else + echo "Unknown requested version: matlab/$MATLAB_REQUESTED" + echo "'module avail cafe-matlab' gives the possibilities:" + module avail cafe-matlab + fi +elif [ $MATLAB_V ] +then + if test -f "/opt/psi/Cafe/modulefiles/cafe-matlab/${MATLAB_V}" + then + #unload removes $MATLAB_VERSION + module unload matlab + module unload cafe-matlab + module load cafe-matlab/${MATLAB_V} + if [ $PRINT_INFO = true ] + then + echo "Using matlab/$MATLAB_V" + fi + else + module unload matlab + module unload cafe-matlab + module load cafe-matlab/$MATLAB_DEFAULT + if [ $PRINT_INFO = true ] + then + echo "Using matlab/$MATLAB_DEFAULT" + fi + fi +else + if test -f "/opt/psi/Cafe/modulefiles/cafe-matlab/${MATLAB_DEFAULT}" + then + module unload matlab + module unload cafe-matlab + module load cafe-matlab/$MATLAB_DEFAULT + if [ $PRINT_INFO = true ] + then + echo "Using matlab/$MATLAB_DEFAULT" + fi + else + echo "The default requested version: matlab/$MATLAB_DEFAULT within cafe-matlab.sh is invalid!" + echo "'module avail cafe-matlab' gives the possibilities:" + module avail cafe-matlab + fi +fi + + +if [ $MATLAB_START = true ] +then +matlab & +fi + +## Or manually acticate cafe-matlab: +## module unload matlab +## module unload cafe-matlab +## module load cafe-matlab/2016b + +## or module switch cafe-matlab/2016b cafe-matlab/2015a + diff --git a/scripts/caget.m b/scripts/caget.m new file mode 100755 index 0000000..733af0a --- /dev/null +++ b/scripts/caget.m @@ -0,0 +1,108 @@ +function value = caget(channel,cached) +% caget('channel') returns current value and additional infos +% of given EPICS channel. +% caget('channel',1) returns last value and additional infos +% of given EPICS channel. +% +% channel can be a channel name or a handle as returned from mcaopen +% +% return value elements: +% val: value (scalar, vector or string) +% sevr: severity as a number +% sevr_str: severity as a string +% stat: status as a number +% stat_str: status as a string +% time: timestamp as a date vector +% units: units string + +persistent severity_str +persistent status_str +persistent zerotime +persistent units + +if ischar(channel) + pv = mocha('open',channel); + + if mocha('isConnected', channel) == false + mocha('openNowAndWait', 1.5) + end + + if mocha('isConnected', channel) == false + error('EPICS channel %s not found', channel); + end +elseif isnumeric(channel) + pv = channel; +else + error ('first argument must be channel name or handle'); +end +if isvector(pv) + pv=pv(1); % truncate +end + +chInfo=mocha ('getChannelInfo',pv); + +if nargin > 1 && cached + pvStruct = mocha('getPVCache',pv); +else + pvStruct = mocha('getPV', pv); +end + + + +pvCtrl = mocha('getCtrlCache',pv); +%pvCtrl + +% initialize severity and status enums +if isempty(severity_str) + severity_str = {'NO_ALARM';'MINOR';'MAJOR';'INVALID'}; + status_str = {'NO_ALARM';'READ';'WRITE';'HIHI';'HIGH';'LOLO';'LOW';'STATE';'COS';'COMM';'TIMEOUT';'HWLIMIT';'CALC';'SCAN';'LINK';'SOFT';'BAD_SUB';'UDF';'DISABLE';'SIMM';'READ_ACCESS';'WRITE_ACCESS'}; +end + + +value.val = pvStruct.val; + +units = pvCtrl.units; + + +if (pvCtrl.noEnumStrings>0) + value.val_str = value.val; + value.val = mocha('getCache',pv,'int8'); +end + + +value.units=units; +value.sevr = pvStruct.alarmSeverity; +indx=max(pvStruct.alarmSeverity, 0); +value.sevr_str = severity_str{indx+1}; +value.stat = pvStruct.alarmStatus; +indx=max(pvStruct.alarmStatus, 0); +value.stat_str = status_str{ indx+1}; + + + +timestamp = mocha('getTimestamp',pv); +if (numel(timestamp) == 2) +% old mca version +% do not use mcatime here because 1. it is slow, 2. is returns UTC +% calculating zerotime only once is faster and takes localtime into account +% When daylight saving time begins or ends, restart the program! + if isempty(zerotime) + [status,timezone]=system('date +%z'); % get localtime offset + timeoffs=str2double(timezone); + houroffs=floor(timeoffs/100); + minoffs=(timeoffs-100*houroffs); + zerotime = datenum('1-Jan-1990') + (minoffs/60 + houroffs)/24; + end + time=timestamp(1)+timestamp(2)/1000000000; + if time + time = zerotime+time/24/3600; + end + value.time = datevec(time); +else +% new mca version + timestamp(6)=timestamp(6)+timestamp(7)/1000000000; + value.time = timestamp(1:6); +end + + + diff --git a/scripts/caget.m- b/scripts/caget.m- new file mode 100755 index 0000000..60e9f0a --- /dev/null +++ b/scripts/caget.m- @@ -0,0 +1,109 @@ +function value = caget(channel,cached) +% caget('channel') returns current value and additional infos +% of given EPICS channel. +% caget('channel',1) returns last value and additional infos +% of given EPICS channel. +% +% channel can be a channel name or a handle as returned from mcaopen +% +% return value elements: +% val: value (scalar, vector or string) +% sevr: severity as a number +% sevr_str: severity as a string +% stat: status as a number +% stat_str: status as a string +% time: timestamp as a date vector +% units: units string + +persistent severity_str +persistent status_str +persistent zerotime +persistent units + +if ischar(channel) + pv = mocha('open',channel); + + if mocha('isConnected', channel) == false + mocha('openNowAndWait', 0.5) + end + + if mocha('isConnected', channel) == false + error('EPICS channel %s not found', channel); + end +elseif isnumeric(channel) + pv = channel; +else + error ('first argument must be channel name or handle'); +end +if isvector(pv) + pv=pv(1); % truncate +end +if nargin > 1 && cached + pvStruct = mocha('getPVCache',pv); +else + pvStruct = mocha('getPV', pv); +end + +val=pvStruct.val + +pvCtrl = mocha('getCtrlCache',pv); +%pvCtrl + +% initialize severity and status enums +if isempty(severity_str) + severity_str = {'NO_ALARM';'MINOR';'MAJOR';'INVALID'}; + status_str = {'NO_ALARM';'READ';'WRITE';'HIHI';'HIGH';'LOLO';'LOW';'STATE';'COS';'COMM';'TIMEOUT';'HWLIMIT';'CALC';'SCAN';'LINK';'SOFT';'BAD_SUB';'UDF';'DISABLE';'SIMM';'READ_ACCESS';'WRITE_ACCESS'}; +end + + +value.val = val; + +units = pvCtrl.units; +string = pvCtrl.enumStrings; + +if size(string) > 1 + disp(size(string)) + value.val_str = value.val; + value.val = mocha('getCache',pv,'int8'); +end + + +%if ~isempty(units{1}) + %value.units = units{1}; +%end +value.units=units; +value.sevr = pvStruct.alarmSeverity; +indx=max(pvStruct.alarmSeverity, 0); +value.sevr_str = severity_str{indx+1}; +value.stat = pvStruct.alarmStatus; +indx=max(pvStruct.alarmStatus, 0); +value.stat_str = status_str{ indx+1}; + + + +timestamp = mocha('getTimestamp',pv); +if (numel(timestamp) == 2) +% old mca version +% do not use mcatime here because 1. it is slow, 2. is returns UTC +% calculating zerotime only once is faster and takes localtime into account +% When daylight saving time begins or ends, restart the program! + if isempty(zerotime) + [status,timezone]=system('date +%z'); % get localtime offset + timeoffs=str2double(timezone); + houroffs=floor(timeoffs/100); + minoffs=(timeoffs-100*houroffs); + zerotime = datenum('1-Jan-1990') + (minoffs/60 + houroffs)/24; + end + time=timestamp(1)+timestamp(2)/1000000000; + if time + time = zerotime+time/24/3600; + end + value.time = datevec(time); +else +% new mca version + timestamp(6)=timestamp(6)+timestamp(7)/1000000000; + value.time = timestamp(1:6); +end + + + diff --git a/scripts/cagetOld.m b/scripts/cagetOld.m new file mode 100755 index 0000000..efb95e1 --- /dev/null +++ b/scripts/cagetOld.m @@ -0,0 +1,118 @@ +function value = caget(channel,cached) +% caget('channel') returns current value and additional infos +% of given EPICS channel. +% caget('channel',1) returns last value and additional infos +% of given EPICS channel. +% +% channel can be a channel name or a handle as returned from mcaopen +% +% return value elements: +% val: value (scalar, vector or string) +% sevr: severity as a number +% sevr_str: severity as a string +% stat: status as a number +% stat_str: status as a string +% time: timestamp as a date vector +% units: units string + +persistent severity_str +persistent status_str +persistent zerotime +persistent units + +if ischar(channel) + pv = mocha('open',channel); + + if mocha('isConnected', channel) == false + mocha('openNowAndWait', 0.5) + end + + if mocha('isConnected', channel) == false + error('EPICS channel %s not found', channel); + end +elseif isnumeric(channel) + pv = channel; +else + error ('first argument must be channel name or handle'); +end +if isvector(pv) + pv=pv(1); % truncate +end + +chInfo=mocha ('getChannelInfo',pv); +%dt='native' + +%if (chInfo.dataType=='DBR_ENUM') +% dt='int8' +%end + +if nargin > 1 && cached + pvStruct = mocha('getPVCache',pv); +else + pvStruct = mocha('getPV', pv); +end + + + +pvCtrl = mocha('getCtrlCache',pv); +%pvCtrl + +% initialize severity and status enums +if isempty(severity_str) + severity_str = {'NO_ALARM';'MINOR';'MAJOR';'INVALID'}; + status_str = {'NO_ALARM';'READ';'WRITE';'HIHI';'HIGH';'LOLO';'LOW';'STATE';'COS';'COMM';'TIMEOUT';'HWLIMIT';'CALC';'SCAN';'LINK';'SOFT';'BAD_SUB';'UDF';'DISABLE';'SIMM';'READ_ACCESS';'WRITE_ACCESS'}; +end + + +value.val = pvStruct.val; + +units = pvCtrl.units; +%string = pvCtrl.enumStrings; + +if (pvCtrl.noEnumStrings>0) +%if size(string) > 1 + %disp(size(string)) + value.val_str = value.val; + value.val = mocha('getCache',pv,'int8'); +end + + +%if ~isempty(units{1}) + %value.units = units{1}; +%end +value.units=units; +value.sevr = pvStruct.alarmSeverity; +indx=max(pvStruct.alarmSeverity, 0); +value.sevr_str = severity_str{indx+1}; +value.stat = pvStruct.alarmStatus; +indx=max(pvStruct.alarmStatus, 0); +value.stat_str = status_str{ indx+1}; + + + +timestamp = mocha('getTimestamp',pv); +if (numel(timestamp) == 2) +% old mca version +% do not use mcatime here because 1. it is slow, 2. is returns UTC +% calculating zerotime only once is faster and takes localtime into account +% When daylight saving time begins or ends, restart the program! + if isempty(zerotime) + [status,timezone]=system('date +%z'); % get localtime offset + timeoffs=str2double(timezone); + houroffs=floor(timeoffs/100); + minoffs=(timeoffs-100*houroffs); + zerotime = datenum('1-Jan-1990') + (minoffs/60 + houroffs)/24; + end + time=timestamp(1)+timestamp(2)/1000000000; + if time + time = zerotime+time/24/3600; + end + value.time = datevec(time); +else +% new mca version + timestamp(6)=timestamp(6)+timestamp(7)/1000000000; + value.time = timestamp(1:6); +end + + + diff --git a/scripts/cainfo.m b/scripts/cainfo.m new file mode 100755 index 0000000..da2bb20 --- /dev/null +++ b/scripts/cainfo.m @@ -0,0 +1,34 @@ +function value = cainfo(pvname) +% cainfo('pvname') returns handle,element count, native type, state, ... +% + + +mcaNoConnection ={'unknown', 'disconnected','Disconnected due to server or network problem'}; +mcaConnection ={'known', 'connected','Normal connection'}; +mcaClosedConnection={'unknown', 'disconnected','Permanently disconnected (cleared)'}; + + +value=struct('Handle',{}, 'PVName',{}, 'ElementCount',{},'NativeType',{},'State',{},'MCAMessage',{},'Host',{},'Units',{}); +chInfo=mocha ('getChannelInfo', pvname); +pvCtrl=mocha ('getCtrlCache', pvname); +value(1).Handle= mocha('getHandleFromPV', pvname); +value(1).PVName= mocha('getPVFromHandle', value(1).Handle); +value(1).ElementCount=chInfo.nelem; +nativeType=strsplit(chInfo.dataType,'_'); +value(1).NativeType=nativeType{2}; + +if (chInfo.connectFlag==1) + value(1).State=mcaConnection{2}; + value(1).MCAMessage=mcaConnection{3}; +else + value(1).State=mcaNoConnection{2}; + value(1).MCAMessage=mcaNoConnection{3}; +end + + +%value(1).MCAMessage=mocha('statusInfo', mocha('getStatus', pvname)); +value(1).Host =chInfo.hostName; +value(1).Units=pvCtrl.units; + +%value(1)=setfield(value(1),'Units',pvCtrl.units) + diff --git a/scripts/camon.m b/scripts/camon.m new file mode 100755 index 0000000..176c98f --- /dev/null +++ b/scripts/camon.m @@ -0,0 +1,62 @@ +function camon(channel,callback,userarg) +% camon('channel', 'callback') +% camon('channel', 'callback', userarg) +% camon('channel', @callback) +% camon('channel', @callback, userarg) +% +% Installs a callback function (given as string or handle) +% on an EPICS channel. +% Whenever the channel updates, the callback is called +% with a structure as defined below and an optional +% numeric, string, or matrix user argument +% +% callback argument structure elements: +% val: value (scalar, vector or string) +% sevr: severity as a number +% sevr_str: severity as a string +% stat: status as a number +% stat_str: status as a string +% time: timestamp as a date vector +% +% A monitor can be deleted with +% cadelmon ('channel') + + +% initialize monitoring the first time +if ~mcamontimer + mcamontimer('start'); +end + +% translate channel name to handle +if ischar(channel) + pv = mcacheckopen(channel); + if pv == 0 + error('EPICS channel %s not found', channel); + end +elseif isnumeric(channel) + pv = channel; +else + error ('usage: camon(''channel'',@callback,userarg)'); +end + +% callback can be string or function handle -- we need string +if nargin>1 + if isa(callback,'function_handle') + callback = func2str(callback); + elseif ~ischar(callback) + error ('usage: camon(''channel'',@callback,userarg)'); + end +end + +% install monitor +if nargin==1 + mcamon(pv); + return +elseif nargin==2 + cb=sprintf('%s(caget(%d,1))',callback,pv); +else + cb=sprintf('%s(caget(%d,1),''%s'')',callback,pv,mat2str(userarg)); +end +disp(pv) +disp(cb) +mcamon(pv, cb); diff --git a/scripts/caput.m b/scripts/caput.m new file mode 100755 index 0000000..748202e --- /dev/null +++ b/scripts/caput.m @@ -0,0 +1,30 @@ +function sts = caput(pvname, value) +% sts=caput('pvname',value) sets the value of EPICS PV 'pvname'. + +% +channel=pvname; + +if ischar(channel) + pv = mocha('open',channel); + + if mocha('isConnected', channel) == false + mocha('openNowAndWait', 1.5) + end + + if mocha('isConnected', channel) == false + error('EPICS channel %s not found', channel); + end +elseif isnumeric(channel) + + if mocha('isConnected', channel) == false + error('EPICS channel with handle %d not connected', channel); + end + pv = channel; + +else + error ('First argument must be channel name or handle'); +end + + +sts= mocha('set', pv, value); + diff --git a/scripts/example.m b/scripts/example.m new file mode 120000 index 0000000..7e0c926 --- /dev/null +++ b/scripts/example.m @@ -0,0 +1 @@ +../example.m \ No newline at end of file diff --git a/scripts/mcaalarm.m b/scripts/mcaalarm.m new file mode 100644 index 0000000..c4593e1 --- /dev/null +++ b/scripts/mcaalarm.m @@ -0,0 +1,36 @@ +function varargout = mcaalarm(varargin) +%MCAALARM - read alarm status and severity for PVs previously read with MCAGET or MCAMON +% +% VALUE = MCAALARM(HANDLE) +% returns the status and severity of a PV specified by integer HANDLE: +% +% VALUE is a structure: +% 'status' : Status code +% 'severity': Severity code +% +% Refer to the EPICS header file "alarmString.h" for the code definitions. +% +% [VALUE1, ... VALUEN] = MCAALARM(HANDLE1, ... , HANDLEN) +% returns status and severity of multiple PVs of any type and length +% Number of outputs must match the number of inputs +% +% See also MCAGET, MCAMON. +% +if nargin<1 + error('No arguments were specified in mcaalarm') +elseif nargin==1 + result{1} = mocha('getAlarm',varargin{1}); %mca(61,varargin{1}); + varargout{1}.status = result{1}(1,1); + varargout{1}.severity = result{1}(1,2); +elseif nargin>1 + if nargin ~= nargout + error('Number of outputs must match the number of inputs') + end + %[result{1:nargin}] = mca(61,varargin{:}); + for k = 1:nargin + [result{k}] = mocha('getAlarm',varargin{k}); + varargout{k}.status=result{k}(1,1); + varargout{k}.severity=result{k}(1,2); + end +end + diff --git a/scripts/mcacache.m b/scripts/mcacache.m new file mode 100644 index 0000000..cd1f038 --- /dev/null +++ b/scripts/mcacache.m @@ -0,0 +1,40 @@ +function varargout = mcacache(varargin) +%MCACACHE - reads locally cached value of a PV. +% MCACACHE does NOT communicate with the server or use resources of CA library +% +% VALUE = MCACACHE(HANDLE) returns a value of a PV by integer HANDLE +% The type (EPICS strings are returned as MATLAB strings) +% All numeric EPICS types returned are as MATLAB double +% If a PV is is a waveform VALUE is a vector +% +% [ VALUE1 , ... VALUEN ] = MCACACHE(HANDLE1, ... , HANDLEN) +% returns values of multiple PV's. +% Number of outputs must match the number of inputs +% +% Notes: The cache value for a PV does not exist until the first use of a +% monitor on that PV +% See also: MCAMON + +if nargin>1 && nargin~=nargout + error('Number of outputs must match the number of inputs') +end + + +for k = 1:nargin + [varargout{k}] = mocha('getCache',varargin{k}); + +end + +%for k = 1:nargin +% scalarValues(k) = varargin{k}; +%end + +%[a,isAllOk,s]=mocha('getScalarArrayCache',scalarValues); + +%for k = 1:nargin +% [varargout{k}]= a(k); +%end +% + +%[varargout{1:nargin}] = mca(300,varargin{:}); + diff --git a/scripts/mcacheck.m b/scripts/mcacheck.m new file mode 100644 index 0000000..6c48338 --- /dev/null +++ b/scripts/mcacheck.m @@ -0,0 +1,20 @@ +function varargout = mcacheck(varargin) +%MCACHECK - Same as MCASTATE +% See also MCAOPEN + +if nargin > 0 + %varargout{1} = mca(13,varargin{:}); + for k = 1:nargin + if mocha('isConnected', varargin{k}) == true + isConnected(k) = uint16(1); + else + isConnected(k) = uint16(0); + end + end + varargout{1} = isConnected; +else + [h,pv,state] = mocha('getHandleStates'); + %[varargout{1}, varargout{2}] = mca(12); + varargout{1} = h; + varargout{2} = state; +end diff --git a/scripts/mcacheckopen.m b/scripts/mcacheckopen.m new file mode 100644 index 0000000..c6bde51 --- /dev/null +++ b/scripts/mcacheckopen.m @@ -0,0 +1,48 @@ +function varargout = mcacheckopen(varargin) +%MCACHECKOPEN - returns handle(s) to PV(s) +% Returns existing handles for PVs already connected, +% opens new connections otherwise. +% Returns 0 for PVs that failed to connect. +% +% HANDLE = MCACHECKOPEN('NAME') +% +% [HANDLE1, ... , HANDLEN] = MCACHECKOPEN('PVNAME1', ... , 'PVNAMEN') +% +% HANDLES = MCACHECKOPEN(NAMES) +% When NAMES is a cell array of strings, HANDLES is a numeric array of +% handles +% +% Note: +% In principle, one should open, use, close PVs. +% But in some cases the bookkeeping of PV handles might +% be a bit too much for quick script hacks, +% in which case mcacheckopen can help with re-use of +% existing handles for PVs that were opened earlier yet +% their handles are lost. +% +% See also MCAOPEN, MCAISOPEN + +if iscellstr(varargin{1}) + varargout{1} = zeros(size(varargin{1})); + + for i=1:length(varargin{1}) + + varargout{1}(i) = mcaisopen(varargin{1}{i}); + if ~varargout{1}(i) + + varargout{1}(i) = mcaopen(varargin{1}{i}); + end + end +else + + + for i=1:nargin + + varargout{i} = mcaisopen(varargin{i}); + if ~varargout{i} + + varargout{i} = mcaopen(varargin{i}); + end + end +end + diff --git a/scripts/mcaclearmon.m b/scripts/mcaclearmon.m new file mode 100644 index 0000000..6538893 --- /dev/null +++ b/scripts/mcaclearmon.m @@ -0,0 +1,19 @@ +function mcaclearmon(varargin) +%MCACLEARMON - uninstall monitors, previously installed with MCAMON +% +% MCACLEARMON(H1,H2,...,HN) +% H1,H2..,HN - integer channel handles +% +% Note: Monitors can be installed with MCAMON and cleared with +% MCACLEARMON any number of times. +% +% See also MCAMON, MCAMONTIMER, MCACACHE + +if nargin <1 + error('Must specify channel handles to close'); +else + for i=1:nargin + %mca(200,varargin{i}) + mocha('monitorStop',varargin{i}) + end +end diff --git a/scripts/mcaclose.m b/scripts/mcaclose.m new file mode 100644 index 0000000..776ea40 --- /dev/null +++ b/scripts/mcaclose.m @@ -0,0 +1,22 @@ +function mcaclose(varargin) +%MCACLOSE - permanently closes channels +% MCACLOSE(H1,H2,...,HN) closes the channels identified by their +% integer handles, previously opened with MCAOPEN. +% MCACLOSE(H) is the same for the case that H is an array of handles. +% +% Note: Once a channel is closed, it can not be used +% by MCAGET,MCAPUT or MCAMON. It can not be reopened. +% Use MCAOPEN again in order to connect to the same PV. +% +% See also MCAOPEN, MCASTATE, MCAINFO +if nargin <1 + error('Must specify channel handles to close'); +else + for i=1:nargin + pvs = varargin{i}; + for j=1:length(pvs) + %mca(5, pvs(j)) + mocha('close', pvs(j)) + end + end +end diff --git a/scripts/mcadebug.m b/scripts/mcadebug.m new file mode 100644 index 0000000..6c1cb33 --- /dev/null +++ b/scripts/mcadebug.m @@ -0,0 +1,12 @@ +function mcadebug(onoff) +%MCADEBUG - Enable/disable debugging +% +% Used only for development, not user-callable. +if onoff + %mca(9999, 1); + disp('Not relevant to mocha'); +else + %mca(9999); + disp('Not relevant to mocha'); +end + diff --git a/scripts/mcaegu.m b/scripts/mcaegu.m new file mode 100644 index 0000000..6849338 --- /dev/null +++ b/scripts/mcaegu.m @@ -0,0 +1,34 @@ +function varargout = mcaegu(varargin) +%MCAEGU - read engineering units from PV's +% +% VALUES = MCAEGU(HANDLE) returns a string array of enum strings of the +% PV specified by integer HANDLE. +% The function does not handle arrays of PV handles, but only a single PV at at time. +% +% +% Error handling: +% An empty cell string array will be returned if the PV type is not ENUM. +% A matlab exception will be thrown when the PV handle is invalid, +% i.e. not the result of a successful MCAOPEN. +% Furthermore, an error can result from a 'get' timeout, +% configurable via MCATIMEOUT. +% In addition, an error can result from a network disconnect. +% In principle, one can check beforehand via MCASTATE, but since +% a disconnect might happen just between the sucessful MCASTATE call +% and the following MCAGET, the only safe thing might be to surround +% MCAGET calls with TRY....CATCH. +% +% See also TRY, CATCH, MCASTATE, MCATIMEOUT, MCAPUT +if nargin<1 + error('No arguments were specified in mcaget') +elseif nargin==1 + if length(varargin{1})>1 + error('Only single PV can be handled at a time') + else + pvCtrl=mocha('getCtrlCache', varargin{1}); + varargout{1} = {pvCtrl.units}; %mca(41,varargin{1}); + end +elseif nargin>1 + error('Only single PV can be handled at a time') +end + diff --git a/scripts/mcaenums.m b/scripts/mcaenums.m new file mode 100644 index 0000000..e43afbe --- /dev/null +++ b/scripts/mcaenums.m @@ -0,0 +1,39 @@ +function varargout = mcaenums(varargin) +%MCAENUMS - read enum strings from PV's +% +% VALUES = MCAENUMS(HANDLE) returns a string array of enum strings of the +% PV specified by integer HANDLE. +% The function does not handle arrays of PV handles, but only a single PV at at time. +% +% +% Error handling: +% An empty cell string array will be returned if the PV type is not ENUM. +% A matlab exception will be thrown when the PV handle is invalid, +% i.e. not the result of a successful MCAOPEN. +% Furthermore, an error can result from a 'get' timeout, +% configurable via MCATIMEOUT. +% In addition, an error can result from a network disconnect. +% In principle, one can check beforehand via MCASTATE, but since +% a disconnect might happen just between the sucessful MCASTATE call +% and the following MCAGET, the only safe thing might be to surround +% MCAGET calls with TRY....CATCH. +% +% See also TRY, CATCH, MCASTATE, MCATIMEOUT, MCAPUT +if nargin<1 + error('No arguments were specified in mcaget') +elseif nargin==1 + if length(varargin{1})>1 + error('Only single PV can be handled at a time') + else + pvCtrl=mocha('getCtrlCache', varargin{1}); + ens13=pvCtrl.enumStrings; + ens=cell(max(1,pvCtrl.noEnumStrings),1); + for k=1:pvCtrl.noEnumStrings + ens(k)=ens13(k); + end + varargout{1} = ens; %mca(40,varargin{1}); + end +elseif nargin>1 + error('Only single PV can be handled at a time') +end + diff --git a/scripts/mcaexit.m b/scripts/mcaexit.m new file mode 100644 index 0000000..e93988b --- /dev/null +++ b/scripts/mcaexit.m @@ -0,0 +1,5 @@ +function mcaexit() +%MCAEXIT - Shut down channel access... +% +% Disconnects all PVs. +mocha('close') %mca(999) diff --git a/scripts/mcaget.m b/scripts/mcaget.m new file mode 100644 index 0000000..19f0bea --- /dev/null +++ b/scripts/mcaget.m @@ -0,0 +1,71 @@ +function varargout = mcaget(varargin) +%MCAGET - read values from PV's +% +% VALUE = MCAGET(HANDLE) returns a value of a PV specified by integer HANDLE. +% Type of return value depends on the native type and the number of elements +% in the EPICS record: +% +% EPICS strings are returned as MATLAB strings +% EPICS array of strings - MATLAB cell array of strings +% All numeric EPICS types are returned as MATLAB double arrays +% +% VALUES = MCAGET(HANDLES) an easy get for a group of scalar numeric PV's +% HANDLES - array of handles +% VALUES - numeric array of values. +% If any of the PVs is a waveform, +% only the first element is returned +% +% [VALUE1, ... VALUEN] = MCAGET(HANDLE1, ... , HANDLEN) +% returns values of multiple PV's of any type and length +% Number of outputs must match the number of inputs +% +% Error handling: +% A matlab exception will be thrown when any of the PVs are invalid, +% i.e. not the result of a successful MCAOPEN. +% Furthermore, an error can result from a 'get' timeout, +% configurable via MCATIMEOUT. +% In addition, an error can result from a network disconnect. +% In principle, one can check beforehand via MCASTATE, but since +% a disconnect might happen just between the sucessful MCASTATE call +% and the following MCAGET, the only safe thing might be to surround +% MCAGET calls with TRY....CATCH. +% +% See also TRY, CATCH, MCASTATE, MCATIMEOUT, MCAPUT +if nargin<1 + error('No arguments were specified in mcaget') +elseif nargin==1 + if length(varargin{1})>1 + [a, isallOK]=mocha('getScalarArray', varargin{1}, 'double'); + + varargout{1} = [a]; %mocha('getScalarArray', varargin{1}); %mca(51,varargin{1}); + else + chInfo=mocha('getInfo', varargin{1}); + if( strcmp(chInfo.dataType,'DBR_ENUM') ) + varargout{1} = mocha('get', varargin{1},'double'); + else + varargout{1} = mocha('get', varargin{1}); %mca(50,varargin{1}); + end + end +elseif nargin>1 + if nargin ~= nargout + error('Number of outputs must match the number of inputs') + end + [a, isallOK]=mocha('getStructArray', [varargin{:}]); + for k=1:length(a) + chInfo=mocha('getInfo', varargin{k}); + if( length(a(k).val) ==1 && strcmp(chInfo.dataType,'DBR_ENUM') ) + varargout{k}=mocha('getCache', varargin{k}, 'double'); + %if (length(a(k).val)==1 && iscell(a(k).val)) + % varargout{k}=a(k).val{1}; + else + if (length(a(k).val)==1 && iscell(a(k).val)) + varargout{k}=a(k).val{1}; + else + varargout{k}=a(k).val; + end + + end + end + %[varargout{1:nargin}] mca(50,varargin{:}); +end + diff --git a/scripts/mcagets.m b/scripts/mcagets.m new file mode 100644 index 0000000..c0379a9 --- /dev/null +++ b/scripts/mcagets.m @@ -0,0 +1,76 @@ +function varargout = mcagets(varargin) +%MCAGETS - read values from PV's, with string output for ENUMs +% +% VALUE = MCAGETS(HANDLE) returns a value of a PV specified by integer HANDLE. +% Type of return value depends on the native type and the number of elements +% in the EPICS record: +% +% EPICS strings are returned as MATLAB strings +% EPICS array of strings - MATLAB cell array of strings +% All numeric EPICS types are returned as MATLAB double arrays +% This routine returns the string value of ENUM types, when the input +% parameter is a single handle. Otherwise this routine behaves +% identically to MCAGET +% +% VALUES = MCAGETS(HANDLES) an easy get for a group of scalar numeric PV's +% HANDLES - array of handles +% VALUES - numeric array of values. +% If any of the PVs is a waveform, +% only the first element is returned +% +% [VALUE1, ... VALUEN] = MCAGETS(HANDLE1, ... , HANDLEN) +% returns values of multiple PV's of any type and length +% Number of outputs must match the number of inputs +% +% Error handling: +% A matlab exception will be thrown when any of the PVs are invalid, +% i.e. not the result of a successful MCAOPEN. +% Furthermore, an error can result from a 'get' timeout, +% configurable via MCATIMEOUT. +% In addition, an error can result from a network disconnect. +% In principle, one can check beforehand via MCASTATE, but since +% a disconnect might happen just between the sucessful MCASTATE call +% and the following MCAGET, the only safe thing might be to surround +% MCAGET calls with TRY....CATCH. +% +% See also TRY, CATCH, MCASTATE, MCATIMEOUT, MCAPUT +if nargin<1 + error('No arguments were specified in mcaget') +elseif nargin==1 + if length(varargin{1})>1 + [a, isallOK]=mocha('getScalarArray', varargin{1}, 'double'); + varargout{1} = [a]; %mca(51,varargin{1}); + else + + varargout{1} = mocha('get', varargin{1}); + + %if(strcmp(mca(43,varargin{1}),'ENUM')) + % enumvalues=mca(40,varargin{1}); + % varargout{1}= enumvalues{mca(50,varargin{1})+1}; + % else + % varargout{1} =mca(50,varargin{1}); + % end + end +elseif nargin>1 + if nargin ~= nargout + error('Number of outputs must match the number of inputs') + end + [a, isallOK]=mocha('getStructArray', [varargin{:}]); + for k=1:length(a) + chInfo=mocha('getInfo', varargin{k}); + if( length(a(k).val) ==1 && strcmp(chInfo.dataType,'DBR_ENUM') ) + varargout{k}=mocha('getCache', varargin{k}, 'double'); + + else + if (length(a(k).val)==1 && iscell(a(k).val)) + varargout{k}=a(k).val{1}; + else + varargout{k}=a(k).val; + end + end + end + %[varargout{1:nargin}] mca(50,varargin{:}) + +end + + diff --git a/scripts/mcainfo.m b/scripts/mcainfo.m new file mode 100644 index 0000000..1ad07d7 --- /dev/null +++ b/scripts/mcainfo.m @@ -0,0 +1,86 @@ +function varargout = mcainfo(varargin); +%MCAINFO - get connection status and other information about a PV +% INFO = MCAINFO(PV) returns information on a single PV +% PV can be a string PV name or an integer handle +% Returns a 1-by-1 structure with fields: +% +% Handle +% PVName +% ElementCount: +% NativeType { STRING | INT | FLOAT | ENUM | CHAR | DOUBLE } +% State { connected | disconnected } +% MCAMessage +% Host +% +% [HANDLES, INFO] = MCAINFO with no argument returns information on +% all open channels in a structure array. +% HANDLES is a numeric array of handles +% INFO is a structure array of inoformation on the PV in the +% same format as above +% +% Note: A channel may become disconnected +% due to a server or network problem. This will be reflected in +% MCAMessage field. Any attempts to read, write or monitor this channel +% will return an error. CA library will periodically attempt to reestablish +% connection without any action required from the user. +% When the connection is closed by the user with MCACLOSE, +% that PV handle becomes invalid, and attempts to call MCAINFO +% will result in an error. +% +% See also: MCAOPEN MCACLOSE MCASTATE +value=struct('Handle',{}, 'PVName',{}, 'ElementCount',{},'NativeType',{},'State',{},'MCAMessage',{},'Host',{},'Units',{}); + + +mcaNoConnection ={'unknown', 'disconnected','Disconnected due to server or network problem'}; +mcaConnection ={'known', 'connected','Normal connection'}; +mcaClosedConnection={'unknown', 'disconnected','Permanently disconnected (cleared)'}; + +if nargin>0 + if ischar(varargin{1}) + %[handles, names] = mca(3); + %matchfound = find(strcmp(varargin{1},names)); + %if isempty(matchfound) + % error(['No open channels found for a PV: ',varargin{1}]); + %end + + %h = handles(matchfound); + h(1)=mocha('getHandleFromPV',varargin{1}); + if (h(1)==0) + error(['No open channels found for a PV: ',varargin{1}]); + end + elseif isnumeric(varargin{1}) + h(1)=(varargin{1}); + else + error('Argument must be a string PV Name or an integer handle'); + end + %varargout{1} = mca(11,h); +else % Return info on all channels + %[varargout{1} varargout{2}] = mca(10); + [h,pv]=mocha('getHandles'); +end + +for k=1:length(h) + chInfo=mocha ('getChannelInfo', h(k)); + pvCtrl=mocha ('getCtrlCache', h(k)); + value(k).Handle=h(k); + value(k).PVName= mocha('getPVFromHandle', h(k)); + value(k).ElementCount=chInfo.nelem; + nativeType=strsplit(chInfo.dataType,'_'); + value(k).NativeType=nativeType{2}; + if (chInfo.connectFlag==1) + value(k).State=mcaConnection{2}; + value(k).MCAMessage=mcaConnection{3}; + else + value(k).State=mcaNoConnection{2}; + value(k).MCAMessage=mcaNoConnection{3}; + end + %value(k).MCAMessage=mocha('statusInfo', mocha('getStatus', h(k))); + value(k).Host =chInfo.hostName; + value(k).Units=pvCtrl.units; +end +if (length(h)==1) + varargout{1} = value; +else + varargout{1} = h; + varargout{2} = value; +end diff --git a/scripts/mcaisopen.m b/scripts/mcaisopen.m new file mode 100644 index 0000000..19c4249 --- /dev/null +++ b/scripts/mcaisopen.m @@ -0,0 +1,20 @@ +function h = mcaisopen(PVNAMESTRING); +%MCAISOPEN - Check if a channel to a PV is open with MCAOPEN +% +% H = MCAISOPEN(PVNAMESTRING) returns an integer handle if open +% and 0 otherwise. If more than one channel is open to the +% same PV, an array of handles is returned. +% +% See also MCAINFO MCASTATE + +if ~ischar(PVNAMESTRING) + error('Argument must be a string') +end + +[handles, names] = mcaopen; +matchfound = find(strcmp(PVNAMESTRING,names)); +if isempty(matchfound) + h = 0; +else + h = handles(matchfound); +end; diff --git a/scripts/mcamon.m b/scripts/mcamon.m new file mode 100644 index 0000000..16e36fc --- /dev/null +++ b/scripts/mcamon.m @@ -0,0 +1,66 @@ +function varargout = mcamon(handle,varargin) +%MCAMON - install or replace monitor on a PV +% +% STS = MCAMON(HANDLE) installs monitor with default callback. +% Default callback updates local copy of the channel data +% every time the data changes on the server. +% This cached data can be read at later time into MATLAB with MCACACHE. +% HANDLE - integer handle to a channel previously opened with MCAOPEN +% Returns 1 on success, 0 on failure +% +% STS = MCAMON(HANDLE,CALLBACKSTRING) installs a monitor and specifies +% a callback string for each. A callback string must be a MATLAB command, +% sequence of commands or a name of a script/function on the MATLAB path. +% It is executed in the 'base' workspace (AFTER the default callback) on +% the next poll of the queue by the MCAMONTIMER command. +% Returns 1 on success, 0 on failure +% +% [HANDLES, CALLBACKSTRINGS]=MCAMON with no arguments returns information +% on all currently installed monitors +% +% Note: Monitors can be installed with MCAMON and cleared with +% MCACLEARMON any number of times. Use MCAMONTIMER to initialise +% the MATLAB timer which polls and processes the outstanding MCA Monitor +% callback queue. +% +% Note: Use of asynchronous features of EPICS (such as monitors) +% with MATLAB requires special care - read MCA notes. +% +% 1.In CA client library (EPICS R3.13.4) asynchronous callbacks run one at a time +% to completion. This means that MATLAB callback string installed with MCAMON +% may not itself contain other MCA functions that call CA library such as MCAGET +% For example MCAMON(H1, 'X=MCAGET(H2);') will not work. +% MCAMON(H1, X='MCACACHE(H2);') is OK since MCACACHE does not use CA library. +% +% See also MCAMONTIMER, MCACACHE, MCAGET, MCACLEARMON. + + +if nargin ==1 + %varargout{1}=mca(100,handle); + monID=mocha('monitor', handle); %return monitorID + status=0; + if (monID > 4095) %1st onid is 0xff (4096) + status=1; + end + varargout{1}=status; +elseif nargin==2 + if ischar(varargin{1}) + %varargout{1} = mca(100,handle,varargin{1}); + monID=mocha('monitor', handle, varargin{1} ) + status=0; + if (monID > 4095) + status=1; + end + else + error('Second argument must be a string'); + end +elseif nargin == 0 + if nargout == 2 + %[varargout{1},varargout{2}]=mca(500); + [varargout{1},varargout{2}]=mocha ('getMonitorHandlesAndActions'); + else + %varargout{1}=mca(500); + varargout{1}=mocha ('getMonitorHandles'); + end +end + diff --git a/scripts/mcamonevents.m b/scripts/mcamonevents.m new file mode 100644 index 0000000..c3ce922 --- /dev/null +++ b/scripts/mcamonevents.m @@ -0,0 +1,25 @@ +function varargout = mcamonevents(varargin) +%MCAMONEVENTS - returns the number of monitor events which have +% occurred for channels since the last call to MCACACHE. +% +% [HANDLES, EVENTCOUNT] = MCAMONEVENTS +% Returns handles and event counts for all open channels +% +% EVENTCOUNT = MCAMONEVENTS(HANDLES) +% Returns event counts for specified channel(s) +% +% See also MCAMON, MCACACHE, MCAGET, MCACLEARMON + +disp('not supported in mocha'); + + +%[handles, count] = mca(510); +%if nargin == 0 +% varargout{1} = handles; +% varargout{2} = count; +%elseif nargin > 0 && isnumeric(varargin{1}) +% for i=1:length(varargin{1}) +% ind(i)=find(handles==varargin{1}(i)); +% end +% varargout{1} = count(ind); +%end diff --git a/scripts/mcamontimer.m b/scripts/mcamontimer.m new file mode 100644 index 0000000..c26373d --- /dev/null +++ b/scripts/mcamontimer.m @@ -0,0 +1,64 @@ +function varargout = mcamontimer(varargin) +%MCAMONTIMER - Controls the initialisation and termination of the MATLAB +% timer used to poll the MCA monitor command queue. +% +% Started = mcamontimer - returns 1 if monitor polling has been started +% returns 0 if monitor polling has not been started +% +% mcamontimer('start') - starts the timer polling every 0.1 seconds +% mcamontimer('stop') - stops the timer +% +% Notes: +% (1) If monitors are installed using mcamon but mcaTimer has not been +% started, the monitor events will queue up indefinitely. There is +% no limit to the size of the queue, so eventually you will +% run out of memory and crash. +% (2) A polling period of 0.1 seconds is used. This may be varied if +% desired by modifying the 'Period' argument in the definition of +% mcaTimer. +% (3) Call mcamontimer('start') once. +% +% See also MCAMON, MCAMONEVENTS, MCACACHE, MCACLEARMON +% +persistent mcaTimer TimerStarted; + +%mocha('test') + +if (nargin == 0) + if (TimerStarted) + varargout{1} = 1; + else + varargout{1} = 0; + end +elseif (nargin == 1) + switch varargin{1} + case 'start' + if (TimerStarted) + error('MCA monitor polling is already started.'); + end + mlock; + %mcaTimer = timer('TimerFcn', 'mca(600)', 'Period', 0.1, 'ExecutionMode', 'fixedSpacing'); + + + + mcaTimer = timer('TimerFcn', 'mocha(402)', 'Period', 10.1, 'ExecutionMode', 'fixedSpacing'); + %%mcaTimer.TimerFcn= {@mocha, 'monitorflushevent'}; + start (mcaTimer); + TimerStarted = 1; + case 'stop' + if (TimerStarted) + munlock; + stop (mcaTimer); + clear mcaTimer; + TimerStarted = 0; + + + else + error('MCA monitor polling has not been started.'); + end + otherwise + error('Invalid parameter specified for mcamontimer. Use ''start'' or ''stop''.') + end +else + error('Invalid number of arguments in mcamontimer.') +end diff --git a/scripts/mcaopen.m b/scripts/mcaopen.m new file mode 100644 index 0000000..fa1013c --- /dev/null +++ b/scripts/mcaopen.m @@ -0,0 +1,61 @@ +function varargout = mcaopen(varargin); +%MCAOPEN - open a Channel Access connection to an EPICS Process Variable +% +% H = MCAOPEN(PVNAME); +% If successful H is a unique nonzero integer handle associated with this PV. +% Returned handle is 0 if a connection could not be established +% +% [H1, ... ,Hn] = MCAOPEN(PVNAME1, ... ,PVNAMEn); +% Is equivalent to but more efficient than multiple single-argument calls +% H1 = MCAOPEN(PVNAME1); +% ... +% Hn = MCAOPEN(PVNAMEn); +% +% HANDLES = MCAOPEN(NAMES) is convenient when working with long lists of PV names +% HANDLES is a numeric array of assigned handles +% NAMES is a cell array of strings with PV names +% +% [HANDLES, NAMES] = MCAOPEN with no arguments returns a list of PV Names for all open connections. +% HANDLES is a numeric array of handles +% NAMES is a cell array of strings with PV names +% +% Note: +% When done, one should probably use MCACLOSE on the handle. +% When you use the same channel again "later", you might keep it open. +% See MCACHECKOPEN for a lazy person's bookkeeping helper. +% +% See also: MCACHECKOPEN, MCAISOPEN, MCACLOSE + +if nargin>1 && nargin ~= nargout + error('Number of outputs must match the number of inputs') +end + + +if nargin==0 + [varargout{1} varargout{2}] = mocha('getHandles'); %mca(3); + +elseif iscellstr(varargin) && nargin ==1 + varargout{1} = mocha('open', varargin{1} ); + +elseif iscellstr(varargin{1}) && nargin==1 + if length(varargin{1}) > 1 + mocha ('openPrepare'); + varargout{1} = mocha('open', varargin{1} ); + mocha ('openNow') + else + varargout{1} = mocha('open', varargin{1} ); % mca(2,varargin{1}); + end + +elseif iscellstr(varargin) + mocha('openPrepare'); + %[varargout{1:nargin}] = + h1=mocha('openArray',{varargin{:}}) %mca(1,varargin{:}); + for i = 1:length(h1) + [varargout{i}] = h1(i); + end + mocha('openNow'); +else + error('All arguments must be strings') +end + + diff --git a/scripts/mcapoll.m b/scripts/mcapoll.m new file mode 100644 index 0000000..2cbfbc7 --- /dev/null +++ b/scripts/mcapoll.m @@ -0,0 +1,4 @@ +function mcapoll() +%MCAPOLL - poll channel access... +%mca(30) +mocha('capoll') diff --git a/scripts/mcaprec.m b/scripts/mcaprec.m new file mode 100644 index 0000000..99e0961 --- /dev/null +++ b/scripts/mcaprec.m @@ -0,0 +1,35 @@ +function varargout = mcaprec(varargin) +%MCAPREC - read precision from PV's +% +% VALUES = MCAPREC(HANDLE) returns the precision field of a channel as a double +% +% The function does not handle arrays of PV handles, but only a single PV at at time. +% +% +% Error handling: +% An empty cell string array will be returned if the PV type is not ENUM. +% A matlab exception will be thrown when the PV handle is invalid, +% i.e. not the result of a successful MCAOPEN. +% Furthermore, an error can result from a 'get' timeout, +% configurable via MCATIMEOUT. +% In addition, an error can result from a network disconnect. +% In principle, one can check beforehand via MCASTATE, but since +% a disconnect might happen just between the successful MCASTATE call +% and the following MCAGET, the only safe thing might be to surround +% MCAGET calls with TRY....CATCH. +% +% See also TRY, CATCH, MCASTATE, MCATIMEOUT, MCAPUT +if nargin<1 + error('No arguments were specified in mcaget') +elseif nargin==1 + if length(varargin{1})>1 + error('Only single PV can be handled at a time') + else + %varargout{1} = mca(42,varargin{1}); + pvCtrl = mocha('getCtrl', varargin{1}); + varargout{1} =pvCtrl.precision(); + end +elseif nargin>1 + error('Only single PV can be handled at a time') +end + diff --git a/scripts/mcaput.m b/scripts/mcaput.m new file mode 100644 index 0000000..a9e0948 --- /dev/null +++ b/scripts/mcaput.m @@ -0,0 +1,109 @@ +function sts = mcaput(varargin) +%MCAPUT - Write values to EPICS Process Variables +% +% MCAPUT(HANDLE1, VALUE1) - one handle, one value +% MCAPUT(HANDLE1, VALUE1, ... , HANDLE_N, VALUE_N) - handles and values in pairs +% +% EPICS STRING values are passed as MATLAB strings. For example: +% >> mcaput(H, 'MATLAB') +% >> mcaput(H1, 'MATLAB', H2, 'EPICS') +% or cell arrays of strings. +% +% MCAPUT(HANDLES_CELL_ARRAY, VALUES_CELL_ARRAY) - arguments are grouped +% in cell array of integer handles and a cell array of values +% of equal length. +% +% Returns an array of status values: 1 success, 0 failure, -1 timeout +% +% MCAPUT is implemented as a call to the ca_put_array_callback +% function in CA client library. +% MCAPUT returns 1 or 0 if we get an OK respectively error status within +% the timeout, or -1 if we don't get any response within the timeout. +% +% Note: +% The special case of MCAPUT([PV, PV, ...], [SCALAR, SCALAR, ...]) +% will simply write the scalar values to the PVs without waiting for the +% callback. +% +% See also MCAGET, MCATIMEOUT. + +if nargin==2 + if iscell(varargin{1}) && iscell(varargin{2}) + % {pv, pv, pv, ...}, {value, value, value, ...} + if length(varargin{1}) ~= length(varargin{2}) + error('Cell array of MCA handles and cell array of values must be the same length') + end + HANDLES = varargin{1}; VALUES = varargin{2}; + ARGS = reshape([HANDLES(:)';VALUES(:)'],1,2*length(varargin{1})); + %sts = mca(70,ARGS{:}); + mocha('setputwait',HANDLES); + [gsts,sts]=mocha('setScalarArray', HANDLES, VALUES); + elseif isnumeric(varargin{1}) + if length(varargin{1})>1 + if length(varargin{1}) ~= length(varargin{2}) + error('Array of handles and array of values must be the same length'); + end + % [pv, pv, pv, ...], [value, value, value, ...] + %sts = mca(80,varargin{1},varargin{2}); + mocha('setputwait', varargin{1}); + [gsts,sts]=mocha('setScalarArray', varargin{1},varargin{2}); + else + ARGS = varargin; + % (pv, value) + if (isnumeric(ARGS{2}(1))) + %if (isnumeric(ARGS(2))) + %sts = mca(70,ARGS{:}); + mocha('setputwait',ARGS{1}); + sts = mocha('set',ARGS(1), ARGS(2)); + else + chInfo=mocha('getInfo', varargin{1}); + if(strcmp(chInfo.dataType,'DBR_ENUM')&&~isnumeric(varargin{2})) + %if(strcmp(mca(43,varargin{1}),'ENUM')&&~isnumeric(varargin{2})) + pvCtrl=mocha('getCtrlCache', varargin{1}); + enumvalues= pvCtrl.enumStrings; %mca(40,varargin{1}); + %enumvalues=mca(40,varargin{1}); + found = 0; + for ind = 1:numel(enumvalues) + if(strcmp(ARGS(2),enumvalues(ind))) + valueToPut=ind-1; + found=1; + end + end + if(found) + ARGS{2}=valueToPut; + mocha('setputwait',ARGS(1)); + sts = mocha('set',ARGS(1), ARGS(2)); % mca(70,ARGS{:}); + else + strings = sprintf(' "%s" ',enumvalues{:}); + error('mcaput:enumCheck','Invalid value for this channel. Try one of: [%s]',strings); + end + else + %sts = mca(70,ARGS{:}); + mocha('setputwait',ARGS(1)); + sts = mocha('set',ARGS(1), ARGS(2)); + end + end + end + else + error('Invalid mcaput args, need PV, VALUE'); + end +elseif mod(nargin,2) == 0 + % 'pv, value, pv, value, ...' + %sts = mca(70,varargin{:}); + + + j=uint16(0); + for i=1:2:nargin + j=j+1; + handles(j)=varargin{i}; + values{j}=varargin{i+1}; + end + + + + mocha('setputnowait',handles); + [gsts,sts]=mocha('setMany', handles, values{1:j}); + +else + error('Incorrect number of inputs, need a sequence of PV, VALUE') +end diff --git a/scripts/mcaputnowait.m b/scripts/mcaputnowait.m new file mode 100644 index 0000000..6aaee19 --- /dev/null +++ b/scripts/mcaputnowait.m @@ -0,0 +1,118 @@ +function sts = mcaputnowait(varargin) +%MCAPUT - Write values to EPICS Process Variables +% +% MCAPUT(HANDLE1, VALUE1) - one handle, one value +% MCAPUT(HANDLE1, VALUE1, ... , HANDLE_N, VALUE_N) - handles and values in pairs +% +% EPICS STRING values are passed as MATLAB strings. For example: +% >> mcaput(H, 'MATLAB') +% >> mcaput(H1, 'MATLAB', H2, 'EPICS') +% or cell arrays of strings. +% +% MCAPUT(HANDLES_CELL_ARRAY, VALUES_CELL_ARRAY) - arguments are grouped +% in cell array of integer handles and a cell array of values +% of equal length. +% +% Returns an array of status values: 1 success, 0 failure, -1 timeout +% +% MCAPUT is implemented as a call to the ca_put_array_callback +% function in CA client library. +% MCAPUT returns 1 or 0 if we get an OK respectively error status within +% the timeout, or -1 if we don't get any response within the timeout. +% +% Note: +% The special case of MCAPUT([PV, PV, ...], [SCALAR, SCALAR, ...]) +% will simply write the scalar values to the PVs without waiting for the +% callback. +% +% See also MCAGET, MCATIMEOUT. + +if nargin==2 + if iscell(varargin{1}) && iscell(varargin{2}) + % {pv, pv, pv, ...}, {value, value, value, ...} + if length(varargin{1}) ~= length(varargin{2}) + error('Cell array of MCA handles and cell array of values must be the same length') + end + HANDLES = cell2mat(varargin{1}); VALUES = cell2mat(varargin{2}); + disp('first call to mca 80') + %sts = mca(80,HANDLES,VALUES); + mocha('setputnowait',HANDLES); + [gsts,sts]=mocha('setScalarArray', HANDLES, VALUES); + elseif isnumeric(varargin{1}) + if length(varargin{1})>1 + if length(varargin{1}) ~= length(varargin{2}) + error('Array of handles and array of values must be the same length'); + end + % [pv, pv, pv, ...], [value, value, value, ...] + disp('call mca 80') + %sts = mca(80,varargin{1},varargin{2}); + mocha('setputnowait', varargin{1}); + [gsts,sts]=mocha('setScalarArray', varargin{1},varargin{2}); + else + ARGS = varargin; + %a=ARGS{1}; + %b=ARGS{2}; + + % (pv, value) + if (isnumeric(ARGS{2}(1))) %(ARGS(2))) + %sts = mca(80,ARGS{:}); + mocha('setputnowait',ARGS{1}); + sts = mocha('set',ARGS(1), ARGS(2)); + else + chInfo=mocha('getInfo', varargin{1}); + %if(strcmp(mca(43,varargin{1}),'ENUM')&&~isnumeric(varargin{2})) + if(strcmp(chInfo.dataType,'DBR_ENUM')&&~isnumeric(varargin{2})) + pvCtrl=mocha('getCtrlCache', varargin{1}); + enumvalues= pvCtrl.enumStrings; %mca(40,varargin{1}); + + found = 0; + for ind = 1:numel(enumvalues) + if(strcmp(ARGS(2),enumvalues(ind))) + valueToPut=ind-1; + found=1; + end + end + if(found) + ARGS{2}=valueToPut; + mocha('setputnowait',ARGS(1)); + sts = mocha('set',ARGS(1), ARGS(2)); % mca(70,ARGS{:}); + else + strings = sprintf(' "%s" ',enumvalues{:}); + error('mcaput:enumCheck','Invalid value for this channel. Try one of: [%s]',strings); + end + else + mocha('setputnowait',ARGS(1)); + sts = mocha('set',ARGS(1), ARGS(2)); %mca(80,ARGS{:}); + + end + end + end + else + error('Invalid mcaput args, need PV, VALUE'); + end +elseif mod(nargin,2) == 0 + % 'pv, value, pv, value, ...' + % sts = mca(80,handles,values); + %for i=1:nargin + %params(i)=varargin{i}; + %end + %nargin; + %data=reshape(params,2,nargin/2); + %handles=data(1,:); + %values=data(2,:); + j=uint16(0); + for i=1:2:nargin + j=j+1; + handles(j)=varargin{i}; + values{j}=varargin{i+1}; + end + + disp(handles) + disp(values) + + mocha('setputnowait',handles); + [gsts,sts]=mocha('setMany', handles, values{1:j}); + %disp('pv,val,pv,val') +else + error('Incorrect number of inputs, need a sequence of PV, VALUE') +end diff --git a/scripts/mcastate.m b/scripts/mcastate.m new file mode 100644 index 0000000..fbb0d6c --- /dev/null +++ b/scripts/mcastate.m @@ -0,0 +1,46 @@ +function varargout = mcastate(varargin); +%MCASTATE - returns an array of connection states for open channels +% MCASTATE is used as diagnostics prior to issuing other +% MCA commands such as MCAGET, MCAPUT and MCAMON +% +% STATES = MCASTATE(H1,H2,...,HN) returns the states of +% the specified channels previously opened with MCAOPEN. +% STATES = an array of the states of the channels listed in the HANDLES +% array +% +% [HANDLES, STATES] = MCASTATE is an array of states of all +% currently open channels. +% HANDLES = an array of all the currently open channels +% STATES = an array of the states of the channels listed in the HANDLES +% array +% +% Possible values +% 1 - Connected: MCAGET, MCAPUT and MCAMON are valid +% 0 - Disconnected: MCAGET, MCAPUT and MCAMON will return invalid +% data or fail. This may be due to a server/network problem +% +% See also MCAINFO, MCAOPEN, MCACLOSE. + +%if nargin > 0 +% varargout{1} = mca(13,varargin{:}); +%else +% [varargout{1}, varargout{2}] = mca(12); +%end + + +if nargin > 0 + %varargout{1} = mca(13,varargin{:}); + for k = 1:nargin + if mocha('isConnected', varargin{k}) == true + isConnected(k) = uint16(1); + else + isConnected(k) = uint16(0); + end + end + varargout{1} = isConnected; +else + [h,pv,state] = mocha('getHandleStates'); + %[varargout{1}, varargout{2}] = mca(12); + varargout{1} = h; + varargout{2} = state; +end diff --git a/scripts/mcatime.m b/scripts/mcatime.m new file mode 100644 index 0000000..215934b --- /dev/null +++ b/scripts/mcatime.m @@ -0,0 +1,44 @@ +function varargout = mcatime(varargin) +%MCATIME - read timestamps for PVs previously read with MCAGET or MCAMON +% +% The timestamp is returned as a MATLAB serial date number suitable +% for use in the DATESTR function. +% +% The original time stamp is in the UTC timezone, +% but since Matlab doesn't handle timezones in datenum/datastr, +% it's converted to the 'local' timezone, so that +% datestr(mcatime(pv)) +% should give a time that is close to the wall clock +% for channels that changed recently. +% +% VALUE = MCATIME(HANDLE) +% returns the timestamp of a PV specified by integer HANDLE. +% +% [VALUE1, ... VALUEN] = MCATIME(HANDLE1, ... , HANDLEN) +% returns timestamps of multiple PVs of any type and length +% Number of outputs must match the number of inputs +% +% See also MCAGET, MCAMON. +% +for i=1:nargin + + % We get y/m/d H:M:S plus nanosecs... + %pieces = mca(60,varargin{i}); + % but datenum doesn't handle nanosecs + %varargout{i} = datenum(pieces(1:6)); + timestamp=mocha('getTimeStamp',varargin{i}); + timestamp=double(timestamp); + + timestamp(6)=timestamp(6)+timestamp(7)/double(1000000000); + %value.time(1)=double(timestamp(1)); + %value.time(2)=(timestamp(2)); + %value.time(3)=(timestamp(3)); + %value.time(4)=(timestamp(4)); + %value.time(5)=(timestamp(5)); + + %varargout{i}(1:5)=value.time(1:5);= + %varargout{i}(6)=double(timestamp6); + varargout{i}=timestamp(1:6); + %format longG; +end + diff --git a/scripts/mcatimeout.m b/scripts/mcatimeout.m new file mode 100644 index 0000000..e51dcc5 --- /dev/null +++ b/scripts/mcatimeout.m @@ -0,0 +1,64 @@ +function varargout = mcatimeout(varargin) +%MCATIMEOUT - set or display MCA timeout setings +% +% MCATIMEOUT('open', t1) +% 'open' option sets the internal variable MCA_SEARCH_TIMEOUT to t1 (sec) +% +% MCATIMEOUT('get', t1) +% 'get' option sets the internal variable MCA_GET_TIMEOUT to t1 (sec) +% +% MCATIMEOUT('put', t1) +% 'put' option sets the internal variable MCA_PUT_TIMEOUT to t1 (sec) +% +% MCATIMEOUT('default') sets the default values +% MCA_SEARCH_TIMEOUT = 1.0 (sec) +% MCA_GET_TIMEOUT = 5.0 (sec) +% MCA_PUT_TIMEOUT = 0.01 (sec) +% +% TIMEOUTS = MCATIMEOUT with no arguments returns a vector of currently set timeouts +% in the format [MCA_SEARCH_TIMEOUT MCA_GET_TIMEOUT MCA_PUT_TIMEOUT] +% +% Notes: +% See also: MCA.cpp +% +switch nargin + case 0 + a=mocha('getTimeout'); + %a(1) Put %a(2)Get + b=mocha('getOpenWaitTime'); + AB=[b(1); a(2); a(1)]; %search, get, put + varargout{1} = AB(1:3); %mca(1000); + case 1 + if strcmp(varargin{1}, 'default') + a=mocha('setTimeOutDefault'); + b=mocha('openWaitWithTimeDefault'); + AB=[b(1); a(2); a(1)]; %search, get, put + varargout{1} = AB(1:3); %mca(1004); + else + error ('Invalid command option.') + end + case 2 + if strcmp(varargin{1}, 'open') + if ~isnumeric(varargin{2}) || varargin{2} <= 0 + error('Second argument must be numeric, positive seconds'); + end + mocha('openWaitWithTime',varargin{2}); + %mca(1001,varargin{2}); + elseif strcmp(varargin{1}, 'get') + if ~isnumeric(varargin{2}) || varargin{2} <= 0 + error('Second argument must be numeric, positive seconds'); + end + mocha('setTimeoutGet',varargin{2}); + %mca(1002,varargin{2}); + elseif strcmp(varargin{1}, 'put') + if ~isnumeric(varargin{2}) || varargin{2} <= 0 + error('Second argument must be numeric, positive seconds'); + end + mocha('setTimeoutPut',varargin{2}); + %mca(1003,varargin{2}); + else + error('Invalid command option.') + end + otherwise + error ('Invalid number of arguments.') +end diff --git a/scripts/mcaunlock.m b/scripts/mcaunlock.m new file mode 100644 index 0000000..1d97e26 --- /dev/null +++ b/scripts/mcaunlock.m @@ -0,0 +1,11 @@ +function mcaunlock; +%MCAUNLOCK - unlocks the MCAMAIN mex-file +% .. so that it can be cleared from memory with CLEAR +% +% MCAMAIN starts in a locked state +% to protect from it from being +% accidentally cleared and +% loosing channel access connections. +%mca(0); +mocha('mexUnlock'); +disp('mca mex-file is now UNLOCKED'); diff --git a/scripts/mcaversion.m b/scripts/mcaversion.m new file mode 100644 index 0000000..ee06a6b --- /dev/null +++ b/scripts/mcaversion.m @@ -0,0 +1,8 @@ +function ver = mcaversion() +%MCAVERSION - get version info +% ver = mcaversion() +% +% returns the mca version as a string + +%ver = mca(-1); +ver = mocha('version'); diff --git a/scripts/monitorAction.m b/scripts/monitorAction.m new file mode 100644 index 0000000..28a261e --- /dev/null +++ b/scripts/monitorAction.m @@ -0,0 +1,16 @@ +function varargout = monActionLocal(varargin) +disp('monitorAction called for:'); +pvName=mocha('getPVFromHandle', varargin{1}); +disp(pvName); +X=['Handle =', num2str(varargin{1})]; +disp(X); + +%[varargout{1} varargout{2}] = mocha ('getCache', varargin{1}); +[var1,var2]=mocha ('getCache', varargin{1}); +[s,t]=mocha('getStatus', varargin{1}); +%X=['Value=', num2str(varargout{1}), ' Status=', num2str(s), ' [',t(1), ' ', t(2),']']; +X=['Value =', num2str(var1)]; +Y=['Status=', num2str(s)]; +disp(X) +disp(Y) +disp([t(1),t(2)]) diff --git a/scripts/pvtable.m b/scripts/pvtable.m new file mode 100755 index 0000000..cc0f56e --- /dev/null +++ b/scripts/pvtable.m @@ -0,0 +1,44 @@ +function pvt = pvtable() +% +% pvt=pvtable() +% returns a table displaying all pvs and their status +% +[hpv,pvn,state] = mocha('getHandleStates'); + +pvt=[]; +if (isempty(hpv)) + disp('THERE ARE NO CHANNELS!'); + return; +end + +%If monitor then uses cache value +mocha('getAsyn', hpv); +mocha('sendNow'); %otherwise getPVCache will do the send! +dstruct = mocha('getPVCache', hpv); + +%If NaN then following warning given from struct2table: +%Warning: Out of range or non-integer values truncated during +%conversion to character +% +t=struct2table(dstruct); + +for n=1:length(hpv) + s1(n).handle=hpv(n); + s1(n).pv=pvn(n); + s1(n).cs=state(n); +end + +t1=struct2table(s1); + + +pvt=table(t1.handle,t1.pv,t.val, t.status, t1.cs); +pvt.Properties.VariableNames={'h','pv', 'val', 'stat','c'}; +%tNew.Properties.VariableNames{'Var1'}= 'handle'; +%tNew.Properties.VariableNames{'Var2'}= 'pv'; +%tNew.Properties.VariableNames{'Var3'}= 'val'; + + +%2017a +%setColHeading(tNew, 1, 'handle'); +%setColHeading(tNew, 2, 'pv'); +%setColHeading(tNew, 3, 'val'); diff --git a/scripts/test.xml b/scripts/test.xml new file mode 100644 index 0000000..f951bbb --- /dev/null +++ b/scripts/test.xml @@ -0,0 +1,18 @@ + + + + + ARIDI-BPM-01LE:X-AVG + + ARIDI-BPM-01LE:Y-AVG + + + diff --git a/windows-x64/example.m b/windows-x64/example.m new file mode 100644 index 0000000..a671384 --- /dev/null +++ b/windows-x64/example.m @@ -0,0 +1,260 @@ +mocha('openNoWait') + +h1=mocha('open','ARIDI-BPM-01LE:X-AVG') +h2=mocha('open','ARIDI-BPM-01LB:X-AVG') +h3=mocha('open','ARIDI-BPM-01LE:Y-AVG') +h4=mocha('open','ARIDI-BPM-01LB:Y-AVG') +h5=mocha('open','ARIDI-BPM-01SE:X-AVG') +h6=mocha('open','ARIDI-BPM-01SE:Y-AVG') +h7=mocha('open','ARIDI-BPM-01SE:WF-INT-2') +h8=mocha('open','ARIDI-BPM-01SE:GET-ENABLE') +mocha('openNow') + +hAll=[h1,h2,h3,h4,h5,h6,h7,h8]; +kkl= 1.1; + +clock + +for mm=1:2 + +[s, allOK] = mocha('setScalarArray',[h5,h6],[kkl,kkl]); % all in one +s, allOK +[a]=mocha('getStructArray', [h1,h2,h7,h4]); +a +a(1).val +a(2).val +a(3).val +a(4).val + +[a, allOK]=mocha('getScalarArray', [h1,h2,h7,h4]); +[r]=mocha('getCtrl',h5); +[r]=mocha('get',h1); +pause(0.05); +[r]=mocha('getCtrlCache',h5,'string'); +end +clock + + +for mm=1:10 +[bret1]=mocha('getStructArrayCache', {'ARIDI-BPM-01LE:X-AVG','ARIDI-BPM-01LB:X-AVG','ARIDI-BPM-01SE:WF-INT-2','ARIDI-BPM-01LB:Y-AVG'}); +[bret2]=mocha('getStructArrayCache',[h1,h2,h7,h4]); +pause(0.05); +end +clock + +%[ST,I]=dbstack('-completenames') +[ST,I]=dbstack() +ST.file +ST.line + +pause(5) + +for mm=1:10 +[r]=mocha('get', [h1]); +[r]=mocha('get', [h2]); +[r]=mocha('get', [h7]); +[r]=mocha('get', [h4]); +r +end +clock + + +[monID1,s]=mocha('monitor',h1); +[monID2,s]=mocha('monitor',h2); +[monID3,s]=mocha('monitor',h3); +[monID4,s]=mocha('monitor',h4); + + +s=mocha('defineGroup','gTest8',{'ARIDI-BPM-01LE:X-AVG','ARIDI-BPM-01LB:X-AVG','ARIDI-BPM-01LE:Y-AVG','ARIDI-BPM-01LB:Y-AVG','ARIDI-BPM-01SE:X-AVG','ARIDI-BPM-01SE:Y-AVG','ARIDI-BPM-01SE:WF-INT-2','ARIDI-BPM-01SE:GET-ENABLE'}) +s=mocha('defineGroup','gTest', {'ARIDI-BPM-01LE:X-AVG','ARIDI-BPM-01LE:Y-AVG'}) + +g8=mocha('openGroup','gTest8'); + +%% pause to reduce growth in MATLAB memory +for mm =1:10 +[r]=mocha('getStructArray', [h1,h2,h3,h4]); %byhandle +pause(0.05); +end + +s=mocha('getAsyn',h5); +[r,s]=mocha('getCache',h5); +pause(0.1); + +s=mocha('set','ARIDI-BPM-01LE:X-AVG',1.234); %bypvname +pause(0.1); +[r,s]=mocha('get', h1); %byhandle +pause(0.1); +s=mocha('set','ARIDI-BPM-01LE:X-AVG',1.234); %byhandle +pause(0.1); +[r,s]=mocha('getCache', h1); %byhandle +pause(0.1); +[r]=mocha('getStruct', h1); %byhandle +pause(0.1); +[r]=mocha('getStructArray', [h1,h2,h3,h4]); %byhandle +pause(0.1); + +[r,s]=mocha('get', h1); %byhandle +pause(0.1); + +%[r,s, allOK]=mocha('getScalarArray', [h1,h2,h3,h4]); %byhandle +%pause(0.1); + + +s=mocha('getAsyn',h5); +[r,s]=mocha('getCache',h5); + + +%why not combine the getNoWait and getNoWaitArray? +[s,allOK]=mocha('getAsyn',[h1,h2,h3]); +disp('s') +disp('allOK') +disp (s) +disp (allOK) + +pause(10); +[r,allOK]=mocha('getStructArrayCache', [h1,h2,h3,h4]); %byhandle +r(1).val +r(2).val +r(3).val +r(4).val + +%pause(0.1); +[r,s]=mocha('getCache',h5); +%pause(0.1); +s=mocha('set',h5,1.134); +pause(0.1); +s=mocha('set',h5,0.134); +pause(0.1); +s=mocha('getAsyn',h5); +[r,s]=mocha('getCache',h5); +pause(0.1); +%disp 'r should be 0.134' + +for kkj =1:10 +s=mocha('set',h5,mm); +[s, allOK] = mocha('setStructArray',[h5,h6],[1],[kkj]); %{'on'},[kk]); +[s, allOK] = mocha('setScalarArray',[h5,h6],[mm,mm]); % all in one +pause(0.01); +end + + +%tic; +%ts=tic; +for kk =1:10 +mocha('isConnected',h1); +mocha('isConnected','ARIDI-BPM-01LE:X-AVG'); +[s, allOK] = mocha('get',h1); +[r, allOK] = mocha('getScalarArray',[h1,h2,h3,h4,h5,h6,h7,h8]); %sequential gets +pause(0.01); +s +allOK +end +%te=toc(ts) + +%tic; +%ts=tic; +for kk =1:10 +[r, allOK] = mocha('getStructArray',[h1,h2,h3,h4,h5,h6,h7,h8]); %sequential gets +pause(0.01); +end +%te=toc(ts) + +%tic; +%ts=tic +for kk =1:10 +[r, allOK] = mocha('getGroup',g8); %sequential gets +pause(0.01); +end +%te=toc(ts) + +%r(2).val +%pause(2.1); +%end; +%disp 'getStructArray h8,h7' +[r, allOK] = mocha('getStructArray',[h8,h7]); +%r.val +pause(0.01); +[s, allOK] = mocha('setScalarArray',[h5,h6],{'0.112','1.13'}); +pause(0.01); + + + +%disp(mm) +%disp 'getArrayNoWait h5,h6' +[s, allOK] = mocha('getArrayAsyn',[h5,h6]); +disp('getArrayAsyn') +pause(10); +%disp 'getScalarArrayCache h5,h6' +[r, s, allOK]=mocha('getScalarArrayCache',[h5,h6]); + + +pause(0.01); +%disp 'r should be 0.112' +s=mocha('set',h5,1.1345); +pause(0.01); +%disp 'getScalarArrayCache h5,h6' +[r, s, allOK]=mocha('getScalarArrayCache',[h5,h6]); + +%disp 'r should be 0.112 not 1.1345' +%[s]=mocha('getAsyn',h1) +%[s]=mocha('getAsyn',h2) +%s=mocha('set',h1,int32(7)) +%s=mocha('set',h1,single(8)) +[a,s]=mocha('getCache',h1); +pause(0.01); +[a,s]=mocha('getCache',h2); +pause(0.01); + +disp ('getArrayAsyn h5,h6') +[s, allOK]=mocha('getArrayAsyn',[h5,h6]); + +pause(10); +s=mocha('set',h6,0.115); +pause(0.01); +[r, allOK]=mocha('getStructArrayCache',[h5,h6]); + +%disp 'r should be 0.1345 and 0.115' +%pause(0.1); +%disp 'getCtrl h5' +[r]=mocha('getCtrl',h5); +pause(0.01); +[r]=mocha('getCtrlCache',h5,'string'); + +pause(0.01); + +[res, allOK] = mocha('getGroup', 'gTest'); + +[res, allOK] = mocha('getGroup', 'gTest'); + + +mocha('loadXMLCollections','Collections/collection_swissfel.xml'); +mocha('loadXMLGroups','Groups/group_swissfel.xml'); + + +pause(0.01); +lgr=mocha('listgroups'); + +lgr + +g1=mocha('openGroup','gWF'); +pause(0.01); + +pause(0.01); +[a,allOK]=mocha('getGroup', 'gWF'); %bygroupName +a +[b,allOK]=mocha('getGroup', g1); %bygrouphandle +b +pause(0.01); +[a,allOK]=mocha('setGroup', g1, b.val); %bygroupName +pause(0.01); +l=mocha('listgroupmembers','gWF'); + +i=mocha('idxgrpmem', 'gWF', 'ARIDI-BPM-01LE:GET-ENABLE'); +pause(0.01); +%end + +r=mocha('monitorstop',h1, monID1); +r=mocha('monitorstop'); % stops all monitors + + +%mocha('closeGroup','gTest'); diff --git a/windows-x64/macchinettaSwitch.obj b/windows-x64/macchinettaSwitch.obj new file mode 100644 index 0000000..86d35a0 Binary files /dev/null and b/windows-x64/macchinettaSwitch.obj differ diff --git a/windows-x64/mocha.mexw64 b/windows-x64/mocha.mexw64 new file mode 100644 index 0000000..ad348fb Binary files /dev/null and b/windows-x64/mocha.mexw64 differ diff --git a/windows-x64/mocha.pdb b/windows-x64/mocha.pdb new file mode 100644 index 0000000..32ee9e3 Binary files /dev/null and b/windows-x64/mocha.pdb differ