From 14a7e14baa1f398fa43a27b6ca0e21e673a98aa5 Mon Sep 17 00:00:00 2001 From: Florian Rau Date: Wed, 9 Mar 2022 19:29:09 +0100 Subject: [PATCH] support serial communication during streaming mode --- software/MATLAB/BpodStepperLive.m | 6 +-- software/MATLAB/BpodStepperModule.m | 70 ++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/software/MATLAB/BpodStepperLive.m b/software/MATLAB/BpodStepperLive.m index ee183c9..1fd7bb7 100644 --- a/software/MATLAB/BpodStepperLive.m +++ b/software/MATLAB/BpodStepperLive.m @@ -65,8 +65,7 @@ drawnow set(obj.h.figure,'Visible','on') - flushinput(obj.s.Port.Port) - obj.s.Port.write(['L' 1], 'uint8'); + obj.s.StreamingMode = true; end function update(obj,~,~) @@ -109,9 +108,8 @@ function update(obj,~,~) end function delete(obj,~,~) - obj.s.Port.write(['L' 0], 'uint8'); obj.s.Port.Port.BytesAvailableFcn = ''; - flushinput(obj.s.Port.Port) + obj.s.StreamingMode = false; end end diff --git a/software/MATLAB/BpodStepperModule.m b/software/MATLAB/BpodStepperModule.m index 955a67d..bab39e9 100644 --- a/software/MATLAB/BpodStepperModule.m +++ b/software/MATLAB/BpodStepperModule.m @@ -35,12 +35,17 @@ MaxSpeed % peak velocity (full steps / s) Position % absolute position end + + properties (Dependent, Access = {?BpodStepperLive}) + StreamingMode + end properties (Access = private) privMaxSpeed % private: peak velocity privAcceleration % private: acceleration privRMScurrent % private: RMS current privChopper % private: Chopper mode + privStreamingMode = false % private: streaming mode CurrentFirmwareVersion = 2 % most recent firmware version end @@ -96,8 +101,10 @@ end function set.MaxSpeed(obj, newSpeed) obj.Port.write('V', 'uint8', newSpeed, 'uint16'); + obj.pauseStreaming(true); obj.Port.write('GV', 'uint8'); obj.privMaxSpeed = obj.Port.read(1, 'uint16'); + obj.pauseStreaming(false); end function out = get.Acceleration(obj) @@ -105,8 +112,10 @@ end function set.Acceleration(obj, newAccel) obj.Port.write('A', 'uint8', newAccel, 'uint16'); + obj.pauseStreaming(true); obj.Port.write('GA', 'uint8'); obj.privAcceleration = obj.Port.read(1, 'uint16'); + obj.pauseStreaming(false); end function out = get.RMScurrent(obj) @@ -115,8 +124,11 @@ function set.RMScurrent(obj, newCurrent) validateattributes(newCurrent,{'numeric'},... {'scalar','integer','nonnegative'}) - obj.Port.write('I', 'uint8', newCurrent, 'uint16', 'GI', 'uint8'); + obj.Port.write('I', 'uint8', newCurrent, 'uint16'); + obj.pauseStreaming(true); + obj.Port.write('GI', 'uint8'); obj.privRMScurrent = obj.Port.read(1, 'uint16'); + obj.pauseStreaming(false); end function out = get.ChopperMode(obj) @@ -125,13 +137,18 @@ function set.ChopperMode(obj, mode) validateattributes(mode,{'numeric'},... {'scalar','integer','nonnegative','<=',1}) - obj.Port.write('C', 'uint8', mode, 'uint8', 'GC', 'uint8'); + obj.Port.write('C', 'uint8', mode, 'uint8'); + obj.pauseStreaming(true); + obj.Port.write('GC', 'uint8'); obj.privChopper = obj.Port.read(1, 'uint8'); + obj.pauseStreaming(false); end function out = get.Position(obj) + obj.pauseStreaming(true); obj.Port.write('GP', 'uint8'); out = obj.Port.read(1, 'int16'); + obj.pauseStreaming(false); end function set.Position(obj,position) validateattributes(position,{'numeric'},{'scalar','integer'}) @@ -200,11 +217,13 @@ function setTarget(obj, varargin) end n = numel(id); out = zeros(n,3); + obj.pauseStreaming(true); for ii = 1:n obj.Port.write(['G' id(ii)], 'uint8'); out(ii,1) = obj.Port.read(1, 'int32'); out(ii,2:3) = obj.Port.read(2, 'uint16'); end + obj.pauseStreaming(false); out([false(n,1) out(:,2:3)==0]) = NaN; if nargout varargout = mat2cell(out',[1 1 1],n); @@ -261,10 +280,12 @@ function rotate(obj,dir) {'2d','increasing','integer','>=',1,'<=',6}) end out = zeros(1,numel(idx)); + obj.pauseStreaming(true); for ii = 1:numel(idx) obj.Port.write(['GR' idx(ii)], 'uint8'); out(ii) = obj.Port.read(1, 'uint8'); end + obj.pauseStreaming(false); if nargout varargout{1} = out; else @@ -300,10 +321,12 @@ function setResistor(obj, idx, R) {'2d','increasing','integer','>=',1,'<=',6},'','ID') end out = zeros(1,numel(id)); + obj.pauseStreaming(true); for ii = 1:numel(id) obj.Port.write(['GM' id(ii)], 'uint8'); out(ii) = obj.Port.read(1, 'uint8'); end + obj.pauseStreaming(false); if nargout varargout{1} = out; else @@ -348,5 +371,48 @@ function delete(obj) function liveView(obj) BpodStepperLive(obj); end + + function out = get.StreamingMode(obj) + out = obj.privStreamingMode; + end + + function set.StreamingMode(obj,enable) + if xor(obj.privStreamingMode,enable) + if enable + flushinput(obj.Port.Port) + obj.Port.write(['L' 1], 'uint8'); + else + obj.Port.write(['L' 0], 'uint8'); + flushinput(obj.Port.Port) + end + obj.privStreamingMode = enable; + end + end + end + + methods (Access = private) + function pauseStreaming(obj,doPause) + persistent BytesAvailableFcn isPaused; + if isempty(BytesAvailableFcn) + BytesAvailableFcn = ''; + isPaused = false; + end + if doPause + if isPaused || ~obj.privStreamingMode + return + end + BytesAvailableFcn = obj.Port.Port.BytesAvailableFcn; + obj.Port.Port.BytesAvailableFcn = ''; + obj.StreamingMode = false; + isPaused = true; + else + if ~isPaused || obj.privStreamingMode + return + end + obj.Port.Port.BytesAvailableFcn = BytesAvailableFcn; + obj.StreamingMode = true; + isPaused = false; + end + end end end