From 32ed13125d74349e608a5cd5587f023bf9e55e31 Mon Sep 17 00:00:00 2001 From: Jan Chrin Date: Mon, 22 Mar 2021 12:41:12 +0100 Subject: [PATCH] cafe-1.13.0 --- .gitignore | 1 + example.m | 1069 ++++++++++++++++++++++++++++++++++++++++- macchinettaSwitch.cpp | 2 +- makefile | 2 +- 4 files changed, 1071 insertions(+), 3 deletions(-) mode change 120000 => 100644 example.m diff --git a/.gitignore b/.gitignore index 5c589f8..cda6523 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *~ *.bak *.*- +RHEL7-x86_64 SL6-x86_64 windows-x64 felix-cache diff --git a/example.m b/example.m deleted file mode 120000 index 2d6dd2b..0000000 --- a/example.m +++ /dev/null @@ -1 +0,0 @@ -exampleNew.m \ No newline at end of file diff --git a/example.m b/example.m new file mode 100644 index 0000000..7cece65 --- /dev/null +++ b/example.m @@ -0,0 +1,1068 @@ +%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 maximum 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 a maximum of 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 -overwrite pvData +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 + +pause(0.1) + +[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(0.5); +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/macchinettaSwitch.cpp b/macchinettaSwitch.cpp index a4ae28d..e18a0fd 100644 --- a/macchinettaSwitch.cpp +++ b/macchinettaSwitch.cpp @@ -501,7 +501,7 @@ void macchinettaFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prh break; case MOCHA_VERSION: - plhs[0]=mxCreateString((char *) "mocha-1.12.5 (Qt5 compatible) : 15 March 2021"); + plhs[0]=mxCreateString((char *) "mocha-1.13.0 : 22 March 2021"); break; case SHOW: diff --git a/makefile b/makefile index 84f8d55..ececc00 120000 --- a/makefile +++ b/makefile @@ -1 +1 @@ -makefile_rel_1.12-gcc-6.3.0 \ No newline at end of file +makefile_rel_1.13-gcc-6.3.0 \ No newline at end of file