Skip to content

Commit 816c0c3

Browse files
committed
Update API for latest bossdevice firmware.
1 parent 84040c1 commit 816c0c3

File tree

7 files changed

+76
-60
lines changed

7 files changed

+76
-60
lines changed

toolbox/dependencies/+bossapi

toolbox/examples/demo_amplitude_threshold_tracking.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
% Prepare instrument object with signals to stream
4141
inst = slrealtime.Instrument;
42-
inst.addSignal('osc','BusElement','alpha.ia','Decimation',5); % OSC signals run x5 faster than QLY
42+
inst.addSignal('instAmplitude','BusElement','alpha','Decimation',5);
4343
inst.addSignal('sig_clean');
4444
inst.BufferData = true;
4545
bd.addInstrument(inst);

toolbox/examples/demo_measure_loop_latency.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
runObj = Simulink.sdi.Run.getLatest;
2121

2222
% Get signal objects and add to subplot
23-
mrkSig = runObj.getSignalsByName('biosignal.mrk');
23+
mrkSig = runObj.getSignalsByName('biosignal.MRK');
2424
mrkSig.plotOnSubPlot(1,1,true);
2525

2626
genRunSig = runObj.getSignalsByName('gen_running');

toolbox/examples/demo_phase_prediction_error_simple.m

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,25 @@
2323
% bd.alpha.bpf_fir_coeffs = firls(70, [0 6 9 13 16 (500/2)]/(500/2), [0 0 1 1 0 0], [1 1 1]);
2424
%fvtool(bd.alpha.bpf_fir_coeffs, 'Fs', 500) % visualize filter
2525

26-
27-
%% Configuring an instrument buffer to acquire data
28-
spfBuf = bd.createAsyncBuffer('spf_sig',10);
29-
oscBuf = bd.createAsyncBuffer('osc',10,'SignalProps',{'BusElement','alpha.ip'});
30-
31-
instObj = slrealtime.Instrument;
32-
33-
spfBuf.addToInstrument(instObj);
34-
instObj.connectCallback(@spfBuf.write);
35-
36-
oscBuf.addToInstrument(instObj);
37-
instObj.connectCallback(@oscBuf.write);
38-
39-
bd.addInstrument(instObj);
26+
% Prepare instrument object with signals to stream
27+
inst = slrealtime.Instrument;
28+
inst.addSignal('instPhase','BusElement','alpha');
29+
inst.addSignal('spf_eeg');
30+
inst.BufferData = true;
31+
bd.addInstrument(inst);
4032

4133
%% Retrieve signal data from bossdevice
4234
tWait = 10;
4335
fprintf('Waiting %is to accumulate data in buffer...\n',tWait);
4436
pause(tWait);
45-
spf_sig = spfBuf.peek("extractAsTimetable",true);
46-
osc_alpha_ip = oscBuf.peek("extractAsTimetable",true);
47-
disp('Done.');
4837

49-
% Synchronized data in buffers
50-
syncedData = synchronize(osc_alpha_ip, spf_sig, 'first', 'nearest');
38+
% Read data from buffer
39+
mapData = inst.getBufferedData;
40+
sigData = mapData.values;
41+
42+
spf_eeg = squeeze(sigData{2}.data)';
43+
alpha_ip = sigData{1}.data;
44+
disp('Done.');
5145

5246
% Compensante offset in instantaneous predicted phase
5347
numSamples = bd.alpha.offset_samples;
@@ -60,11 +54,11 @@
6054
% Prepare IIR Butterworth filter
6155
peakFrequency = 10;
6256
oscBPFfilter = designfilt('bandpassiir','FilterOrder',12,'HalfPowerFrequency1',peakFrequency-2,...
63-
'HalfPowerFrequency2',peakFrequency+2,'SampleRate',osc_alpha_ip.Properties.SampleRate,'DesignMethod','butter');
57+
'HalfPowerFrequency2',peakFrequency+2,'SampleRate',1/mode(diff(sigData{1}.time)),'DesignMethod','butter');
6458

6559
% Compute phase prediction error
6660
[phaseError, meanError, meanDev] = bossapi.boss.computePhasePredictionError(oscBPFfilter,...
67-
syncedData.spf_sig(1+numSamples:end-1), syncedData.osc(2:end-numSamples));
61+
spf_eeg(1+numSamples:end-1), alpha_ip(2:end-numSamples));
6862

6963
disp('Done.');
7064

toolbox/examples/demo_sdi.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
runObj = Simulink.sdi.Run.getLatest;
2424

2525
% Get signal objects and expand to convert multidimensional signals to scalar channels
26-
eegSig = runObj.getSignalsByName("biosignal.eeg");
26+
eegSig = runObj.getSignalsByName("biosignal.EEG");
2727
eegSig.expand;
28-
spfSig = runObj.getSignalsByName("spf");
28+
spfSig = runObj.getSignalsByName("spf_eeg");
2929
spfSig.expand;
3030

3131
% Plot signals in subplots

toolbox/src/bossdevice.m

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
end
4848

4949
properties (Constant, Hidden)
50-
appName = 'mainmodel';
50+
appName = 'bossdevice_main';
5151
end
5252

5353
methods (Static)
@@ -274,16 +274,16 @@ function stop(obj)
274274

275275
% getters and setters for dependent properties
276276
function duration = get.sample_and_hold_seconds(obj)
277-
duration = obj.getparam('UDP', 'sample_and_hold_seconds');
277+
duration = obj.getparam('biosignal Sample and Hold', 'sample_and_hold_seconds');
278278
end
279279

280280
function set.sample_and_hold_seconds(obj, duration)
281-
obj.setparam('UDP', 'sample_and_hold_seconds', duration);
281+
obj.setparam('biosignal Sample and Hold', 'sample_and_hold_seconds', duration);
282282
end
283283

284284

285285
function spatial_filter_weights = get.spatial_filter_weights(obj)
286-
spatial_filter_weights = getparam(obj, 'OSC', 'weights');
286+
spatial_filter_weights = getparam(obj, '', 'spfWeights');
287287
end
288288

289289
function set.spatial_filter_weights(obj, weights)
@@ -303,7 +303,7 @@ function stop(obj)
303303
if size(weights, 1) < num_rows
304304
weights(num_rows, 1) = 0; % fill with zeros
305305
end
306-
setparam(obj, 'OSC', 'weights', single(weights));
306+
setparam(obj, '', 'spfWeights', single(weights));
307307
end
308308

309309

@@ -340,19 +340,27 @@ function stop(obj)
340340
end
341341

342342
function n = get.num_eeg_channels(obj)
343-
n = getparam(obj, 'UDP', 'num_eeg_channels');
343+
n = getparam(obj, {'UDP Decode','UDP_Decode_Biosignal/Decode UDP Messages/NeurOne Decode'},'numEEGch');
344344
end
345345

346346
function set.num_eeg_channels(obj, n)
347-
setparam(obj, 'UDP', 'num_eeg_channels', n);
347+
arguments
348+
obj
349+
n uint8 {mustBeInteger,mustBeNonnegative}
350+
end
351+
setparam(obj, {'UDP Decode','UDP_Decode_Biosignal/Decode UDP Messages/NeurOne Decode'},'numEEGch', n);
348352
end
349353

350354
function n = get.num_aux_channels(obj)
351-
n = getparam(obj, 'UDP', 'num_aux_channels');
355+
n = getparam(obj, {'UDP Decode','UDP_Decode_Biosignal/Decode UDP Messages/NeurOne Decode'},'numAUXch');
352356
end
353357

354358
function set.num_aux_channels(obj, n)
355-
setparam(obj, 'UDP', 'num_aux_channels', n);
359+
arguments
360+
obj
361+
n uint8 {mustBeInteger,mustBeNonnegative}
362+
end
363+
setparam(obj, {'UDP Decode','UDP_Decode_Biosignal/Decode UDP Messages/NeurOne Decode'},'numAUXch', n);
356364
end
357365

358366
function val = get.marker_pulse_width_sec(obj)
@@ -389,7 +397,7 @@ function stop(obj)
389397
end
390398

391399
function generator_running = get.isGeneratorRunning(obj)
392-
generator_running = obj.getsignal('GEN',5);
400+
generator_running = obj.getsignal('GEN',3);
393401
end
394402

395403
function obj = arm(obj)
@@ -571,12 +579,24 @@ function reboot(obj)
571579
end
572580

573581
function setparam(obj, path, varargin)
574-
setparam(obj.targetObject, [obj.appName,'/bosslogic/', path], varargin{:});
582+
if isempty(path)
583+
setparam(obj.targetObject, '', varargin{:});
584+
elseif ~iscell(path)
585+
setparam(obj.targetObject, [obj.appName,'/', char(path)], varargin{:});
586+
else
587+
setparam(obj.targetObject, [{[obj.appName,'/', path{1}]},path(2:end)], varargin{:});
588+
end
575589
end
576590

577591
function val = getparam(obj, path, varargin)
578592
if obj.isInitialized
579-
val = getparam(obj.targetObject, [obj.appName,'/bosslogic/', path], varargin{:});
593+
if isempty(path)
594+
val = getparam(obj.targetObject, '', varargin{:});
595+
elseif ~iscell(path)
596+
val = getparam(obj.targetObject, [obj.appName,'/', char(path)], varargin{:});
597+
else
598+
val = getparam(obj.targetObject, [{[obj.appName,'/', path{1}]},path(2:end)], varargin{:});
599+
end
580600
else
581601
val = [];
582602
end
@@ -591,9 +611,9 @@ function setparam(obj, path, varargin)
591611

592612
if obj.isInitialized
593613
if ~iscell(path)
594-
val = getsignal(obj.targetObject, [obj.appName,'/bosslogic/', path], portIndex);
614+
val = getsignal(obj.targetObject, [obj.appName,'/', path], portIndex);
595615
else
596-
val = getsignal(obj.targetObject, [{[obj.appName,'/bosslogic/', path{1}]},path(2:end)], portIndex);
616+
val = getsignal(obj.targetObject, [{[obj.appName,'/', path{1}]},path(2:end)], portIndex);
597617
end
598618
end
599619
end

toolbox/src/bossdevice_oscillation.m

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
logObj bossapi.Logger
1212
end
1313

14+
properties (Constant, Hidden)
15+
appName = 'bossdevice_main'
16+
end
17+
1418
properties (Dependent)
1519
phase_target
1620
phase_plusminus
@@ -35,18 +39,18 @@
3539
obj.logObj = logObj;
3640

3741
if obj.targetObj.isConnected && obj.targetObj.isLoaded
38-
obj.phase_target = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_target');
39-
obj.phase_plusminus = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_plusminus');
40-
obj.amplitude_min = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_min');
41-
obj.amplitude_max = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_max');
42+
obj.phase_target = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_target');
43+
obj.phase_plusminus = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_plusminus');
44+
obj.amplitude_min = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_min');
45+
obj.amplitude_max = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_max');
4246
else
4347
obj.logObj.obj.logObj.error('bossdevice is not ready. Initialize your bossdevice object before further processing. For example, if you are using "bd = bossdevice", run "bd.initialize".');
4448
end
4549
end
4650

4751

4852
function phase_target = get.phase_target(obj)
49-
phase_target = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_target');
53+
phase_target = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_target');
5054
end
5155

5256
function obj = set.phase_target(obj, phi)
@@ -63,70 +67,68 @@
6367
return
6468
end
6569
end
66-
setparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_target', newValue);
70+
setparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_target', single(newValue));
6771
end
6872

6973

7074
function phase_plusminus = get.phase_plusminus(obj)
71-
phase_plusminus = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_plusminus');
75+
phase_plusminus = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_plusminus');
7276
end
7377

7478
function obj = set.phase_plusminus(obj, phase_plusminus)
7579
%set.phase_plusminus Set phase tolerance
7680
% A tolerance of pi ignores the phase in generation of events
77-
setparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'phase_plusminus', phase_plusminus);
81+
setparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'phase_plusminus', single(phase_plusminus));
7882
end
7983

8084

8185
function amplitude_min = get.amplitude_min(obj)
82-
amplitude_min = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_min');
86+
amplitude_min = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_min');
8387
end
8488

8589
function obj = set.amplitude_min(obj, amplitude_min)
8690
%METHOD1 Summary of this method goes here
8791
% Detailed explanation goes here
88-
setparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_min', amplitude_min);
92+
setparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_min', single(amplitude_min));
8993
end
9094

9195

9296
function amplitude_max = get.amplitude_max(obj)
93-
amplitude_max = getparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_max');
97+
amplitude_max = getparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_max');
9498
end
9599

96100
function obj = set.amplitude_max(obj, amplitude_max)
97-
%METHOD1 Summary of this method goes here
98-
% Detailed explanation goes here
99-
setparam(obj.targetObj, ['mainmodel/bosslogic/EVD/' obj.name], 'amplitude_max', amplitude_max);
101+
setparam(obj.targetObj, [obj.appName,'/EVD/' obj.name], 'amplitude_max', single(amplitude_max));
100102
end
101103

102104

103105
function lpf_fir_coeffs = get.lpf_fir_coeffs(obj)
104-
lpf_fir_coeffs = getparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'lpf_fir_coeffs');
106+
lpf_fir_coeffs = getparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'lpf_fir_coeffs');
105107
end
106108

107109
function obj = set.lpf_fir_coeffs(obj, coeffs)
108-
setparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'lpf_fir_coeffs', coeffs)
110+
setparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'lpf_fir_coeffs', coeffs);
109111
end
110112

111113

112114
function bpf_fir_coeffs = get.bpf_fir_coeffs(obj)
113-
bpf_fir_coeffs = getparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'bpf_fir_coeffs');
115+
bpf_fir_coeffs = getparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'bpf_fir_coeffs');
114116
end
115117

116118
function obj = set.bpf_fir_coeffs(obj, coeffs)
117119
assert(numel(coeffs) <= numel(obj.bpf_fir_coeffs), 'number of coefficients exceeds maximum')
118120
if numel(coeffs) < numel(obj.bpf_fir_coeffs)
119121
coeffs(numel(obj.bpf_fir_coeffs)) = 0; % fill with zeros
120122
end
121-
setparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'bpf_fir_coeffs', coeffs)
123+
setparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'bpf_fir_coeffs', single(coeffs));
122124
end
123125

124126
function offset_samples = get.offset_samples(obj)
125-
offset_samples = getparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'ipe_offset_samples');
127+
offset_samples = getparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'ipe_offset_samples');
126128
end
127129

128130
function obj = set.offset_samples(obj, weights)
129-
setparam(obj.targetObj, ['mainmodel/bosslogic/OSC/' obj.name], 'ipe_offset_samples', weights)
131+
setparam(obj.targetObj, [obj.appName,'/OSC/' obj.name], 'ipe_offset_samples', weights)
130132
end
131133

132134

0 commit comments

Comments
 (0)