1 | %------------------------------------------------------------------------- |
---|
2 | % WARPLab Framework |
---|
3 | % |
---|
4 | % Copyright 2013, Mango Communications. All rights reserved. |
---|
5 | % Distributed under the WARP license (http://warpproject.org/license) |
---|
6 | % |
---|
7 | % Chris Hunter (chunter [at] mangocomm.com) |
---|
8 | % Patrick Murphy (murphpo [at] mangocomm.com) |
---|
9 | % Erik Welsh (welsh [at] mangocomm.com) |
---|
10 | %------------------------------------------------------------------------- |
---|
11 | |
---|
12 | classdef wl_trigger_manager_proc < wl_trigger_manager & handle_light |
---|
13 | % Trigger manager object |
---|
14 | % User code should not use this object directly -- the parent wl_node will |
---|
15 | % instantiate the appropriate baseband object for the hardware in use |
---|
16 | properties (SetAccess = public) |
---|
17 | coreVersion; |
---|
18 | input_delayStep_ns; |
---|
19 | input_delayMax_ns; |
---|
20 | output_delayStep_ns; |
---|
21 | output_delayMax_ns; |
---|
22 | end |
---|
23 | |
---|
24 | properties (SetAccess = protected) |
---|
25 | description; % Description of this trigger manager object |
---|
26 | triggerInputIDs; |
---|
27 | triggerOutputIDs; |
---|
28 | numInputs; |
---|
29 | numOutputs; |
---|
30 | end |
---|
31 | |
---|
32 | properties(Hidden = true,Constant = true) |
---|
33 | % These constants define specific command IDs used by this object. |
---|
34 | % Their C counterparts are found in wl_trigger_manager.h |
---|
35 | GRP = 'trigger_manager'; |
---|
36 | |
---|
37 | CMD_ADD_ETHERNET_TRIG = 1; % 0x000001 |
---|
38 | CMD_DEL_ETHERNET_TRIG = 2; % 0x000002 |
---|
39 | CMD_CLR_ETHERNET_TRIGS = 3; % 0x000003 |
---|
40 | CMD_HW_SW_ETHERNET_TRIG = 4; % 0x000004 |
---|
41 | |
---|
42 | CMD_INPUT_SEL = 16; % 0x000010 |
---|
43 | CMD_OUTPUT_DELAY = 17; % 0x000011 |
---|
44 | CMD_OUTPUT_HOLD = 18; % 0x000012 |
---|
45 | CMD_OUTPUT_READ = 19; % 0x000013 |
---|
46 | CMD_OUTPUT_CLEAR = 20; % 0x000014 |
---|
47 | |
---|
48 | CMD_INPUT_ENABLE = 32; % 0x000020 |
---|
49 | CMD_INPUT_DEBOUNCE = 33; % 0x000021 |
---|
50 | CMD_INPUT_DELAY = 34; % 0x000022 |
---|
51 | CMD_IDELAY = 35; % 0x000023 |
---|
52 | CMD_ODELAY = 36; % 0x000024 |
---|
53 | |
---|
54 | CMD_ENERGY_BUSY_THRESH = 48; % 0x000030 |
---|
55 | CMD_ENERGY_AVG_LEN = 49; % 0x000031 |
---|
56 | CMD_ENERGY_BUSY_MIN_LEN = 50; % 0x000032 |
---|
57 | CMD_ENERGY_IFC_SELECTION = 51; % 0x000033 |
---|
58 | |
---|
59 | CMD_TEST_TRIGGER = 128; % 0x000080 |
---|
60 | |
---|
61 | TRIGGER_INPUT_FLAG = hex2dec('80000000'); % Used to check trigger input IDs vs trigger output IDs |
---|
62 | end |
---|
63 | |
---|
64 | methods |
---|
65 | function obj = wl_trigger_manager_proc() |
---|
66 | obj.description = 'WARPLab Trigger Configuration Module'; |
---|
67 | end |
---|
68 | |
---|
69 | function out = setNumInputs(obj, N) |
---|
70 | obj.numInputs = N; |
---|
71 | obj.triggerInputIDs = 1:N; |
---|
72 | obj.triggerInputIDs = obj.triggerInputIDs + obj.TRIGGER_INPUT_FLAG; % Set "Trigger Input" Flag |
---|
73 | obj.input_delayStep_ns = zeros(1,N); |
---|
74 | obj.input_delayMax_ns = zeros(1,N); |
---|
75 | end |
---|
76 | |
---|
77 | function out = setNumOutputs(obj, N) |
---|
78 | obj.numOutputs = N; |
---|
79 | obj.triggerOutputIDs = 1:N; |
---|
80 | obj.output_delayStep_ns = zeros(1,N); |
---|
81 | obj.output_delayMax_ns = zeros(1,N); |
---|
82 | end |
---|
83 | |
---|
84 | function out = isInputID(obj, input_ids) |
---|
85 | out = true; |
---|
86 | |
---|
87 | if (~isempty(input_ids)) |
---|
88 | for index = 1:length(input_ids) |
---|
89 | if (bitand(input_ids(index), obj.TRIGGER_INPUT_FLAG) ~= obj.TRIGGER_INPUT_FLAG) |
---|
90 | out = false; |
---|
91 | end |
---|
92 | end |
---|
93 | end |
---|
94 | end |
---|
95 | |
---|
96 | function out = isOutputID(obj, output_ids) |
---|
97 | out = true; |
---|
98 | |
---|
99 | if (~isempty(output_ids)) |
---|
100 | for index = 1:length(output_ids) |
---|
101 | if (bitand(output_ids(index), obj.TRIGGER_INPUT_FLAG) == obj.TRIGGER_INPUT_FLAG) |
---|
102 | out = false; |
---|
103 | end |
---|
104 | end |
---|
105 | end |
---|
106 | end |
---|
107 | |
---|
108 | function out = procCmd(obj, nodeInd, node, varargin) |
---|
109 | % wl_trigger_manager procCmd(obj, nodeInd, node, varargin) |
---|
110 | % obj: Node object (when called using dot notation) |
---|
111 | % nodeInd: Index of the current node, when wl_node is iterating over nodes |
---|
112 | % node: Current node object |
---|
113 | % varargin: |
---|
114 | % [1] Command string |
---|
115 | % [2:N} Command arguments |
---|
116 | % |
---|
117 | out = []; |
---|
118 | cmdStr = varargin{1}; |
---|
119 | cmdStr = lower(cmdStr); |
---|
120 | |
---|
121 | if(length(varargin) > 1) |
---|
122 | varargin = varargin(2:end); |
---|
123 | else |
---|
124 | varargin = {}; |
---|
125 | end |
---|
126 | |
---|
127 | switch(cmdStr) |
---|
128 | %--------------------------------------------------------- |
---|
129 | case 'add_ethernet_trigger' |
---|
130 | % Associates node to a trigger input |
---|
131 | % |
---|
132 | % Arguments: (wl_trigger_manager TRIGGER) |
---|
133 | % Returns: none |
---|
134 | % |
---|
135 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ADD_ETHERNET_TRIG)); |
---|
136 | |
---|
137 | triggers = varargin{1}; |
---|
138 | triggerID = uint32(0); |
---|
139 | |
---|
140 | for index = 1:length(triggers) |
---|
141 | triggerID = bitor(triggerID, triggers(index).ID); |
---|
142 | end |
---|
143 | |
---|
144 | myCmd.addArgs(triggerID); |
---|
145 | node.sendCmd(myCmd); |
---|
146 | |
---|
147 | %--------------------------------------------------------- |
---|
148 | case 'delete_ethernet_trigger' |
---|
149 | % De-associates node to a trigger input |
---|
150 | % |
---|
151 | % Arguments: (wl_trigger_manager TRIGGER) |
---|
152 | % Returns: none |
---|
153 | % |
---|
154 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_DEL_ETHERNET_TRIG)); |
---|
155 | |
---|
156 | triggers = varargin{1}; |
---|
157 | triggerID = uint32(0); |
---|
158 | |
---|
159 | for index = 1:length(triggers) |
---|
160 | triggerID = bitor(triggerID, triggers(index).ID); |
---|
161 | end |
---|
162 | |
---|
163 | myCmd.addArgs(triggerID); |
---|
164 | node.sendCmd(myCmd); |
---|
165 | |
---|
166 | %--------------------------------------------------------- |
---|
167 | case 'clear_ethernet_triggers' |
---|
168 | % Clears all trigger associations in the node |
---|
169 | % |
---|
170 | % Arguments: none |
---|
171 | % Returns: none |
---|
172 | % |
---|
173 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_CLR_ETHERNET_TRIGS)); |
---|
174 | |
---|
175 | node.sendCmd(myCmd); |
---|
176 | |
---|
177 | %--------------------------------------------------------- |
---|
178 | case 'set_ethernet_trigger_type' |
---|
179 | % Set the Ethernet trigger type |
---|
180 | % |
---|
181 | % In WARP v3, the ability was added to the trigger manager to "sniff" |
---|
182 | % the axi stream between the Ethernet controller and the AXI interface |
---|
183 | % to the Ethernet controller, such as the AXI DMA or AXI FIFO. This |
---|
184 | % allows for more predictable timing for Ethernet triggers since it does |
---|
185 | % not depend on any SW interaction. However, this feature could not be |
---|
186 | % added to the WARP v2 trigger manager due to differences in Ethernet |
---|
187 | % components. Therefore, in reference designs since this feature was |
---|
188 | % introduced, WARP v3 has used hardware for Ethernet triggers while WARP v2 |
---|
189 | % has used software. |
---|
190 | % |
---|
191 | % Unfortunately, this introduced a large timing difference between WARP v2 |
---|
192 | % and WARP v3 when asserting the Ethernet trigger within the node in response |
---|
193 | % to a broadcast Ethernet trigger. This adds a complication to experiments |
---|
194 | % involving a mix of WARP v2 and WARP v3 nodes. Therefore, trigger manager |
---|
195 | % v1.04.a addressed this by being able to select between using the hardware |
---|
196 | % capabilities WARP v3 or using software, like WARP v2, for Ethernet triggers. |
---|
197 | % |
---|
198 | % This command allows users to set whether the WARP v3 node uses hardware |
---|
199 | % or software for Ethernet triggers. Since WARP v2 does not support using |
---|
200 | % hardware for Ethernet triggers, this command does nothing. |
---|
201 | % |
---|
202 | % Arguments: 'hardware' or 'software' |
---|
203 | % Returns: none |
---|
204 | % |
---|
205 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_HW_SW_ETHERNET_TRIG)); |
---|
206 | |
---|
207 | % See values in wl_trigger_manager.h for ETH_TRIG_* defined values |
---|
208 | switch(varargin{1}) |
---|
209 | case 'hardware' |
---|
210 | trigger_type = uint32(0); |
---|
211 | |
---|
212 | case 'software' |
---|
213 | trigger_type = uint32(1); |
---|
214 | |
---|
215 | otherwise |
---|
216 | error('Unsupported argument ''%s''. Please use ''hardware'' or ''software''.', varargin{1}); |
---|
217 | end |
---|
218 | |
---|
219 | myCmd.addArgs(trigger_type); |
---|
220 | node.sendCmd(myCmd); |
---|
221 | |
---|
222 | %--------------------------------------------------------- |
---|
223 | case 'get_ethernet_trigger' |
---|
224 | % Reads current trigger association from node |
---|
225 | % |
---|
226 | % Arguments: node |
---|
227 | % Returns: (uint32 TRIGGER_ASSOCIATION) |
---|
228 | % TRIGGER_ASSOCIATION: bit-wise AND of associated trigger IDs |
---|
229 | % |
---|
230 | myCmd = wl_cmd(node.calcCmd(obj.GRP,obj.CMD_ADD_ETHERNET_TRIG)); |
---|
231 | |
---|
232 | triggerID = uint32(0); |
---|
233 | |
---|
234 | myCmd.addArgs(triggerID); |
---|
235 | resp = node.sendCmd(myCmd); |
---|
236 | |
---|
237 | out = resp.getArgs(); |
---|
238 | |
---|
239 | %--------------------------------------------------------- |
---|
240 | case 'output_config_input_selection' |
---|
241 | % Selects which trigger inputs drive the selected outputs |
---|
242 | % Arguments: (uint32 OUTPUTS), (uint32 OR_INPUTS), [optional] (uint32 AND_INPUTS) |
---|
243 | % Returns: none |
---|
244 | % |
---|
245 | % OUTPUTS: vector of output trigger IDs, provided by |
---|
246 | % wl_getTriggerOutputIDs |
---|
247 | % |
---|
248 | % OR_INPUTS: vector of input trigger IDs, provided by |
---|
249 | % wl_getTriggerInputIDs. Any triggers in |
---|
250 | % this vector that assert will cause the |
---|
251 | % output trigger to assert. |
---|
252 | % |
---|
253 | % AND_INPUTS: vector of input trigger IDs, provided by |
---|
254 | % wl_getTriggerInputIDs. Only if all triggers |
---|
255 | % in this vector assert will the output |
---|
256 | % trigger assert. |
---|
257 | % |
---|
258 | % NOTE: This command replaces the current input selection on the board for the |
---|
259 | % specified outputs (unspecified outputs are not modified). The previous |
---|
260 | % state of the output is not saved. |
---|
261 | % |
---|
262 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_INPUT_SEL)); |
---|
263 | |
---|
264 | if(length(varargin) == 2) |
---|
265 | OUTPUTS = varargin{1}; |
---|
266 | OR_INPUTS = varargin{2}; |
---|
267 | AND_INPUTS = []; |
---|
268 | elseif(length(varargin) == 3) |
---|
269 | OUTPUTS = varargin{1}; |
---|
270 | OR_INPUTS = varargin{2}; |
---|
271 | AND_INPUTS = varargin{3}; |
---|
272 | end |
---|
273 | |
---|
274 | % Check IDs |
---|
275 | if (~obj.isOutputID(OUTPUTS)) |
---|
276 | error('Output trigger ID invalid') |
---|
277 | end |
---|
278 | |
---|
279 | if (~obj.isInputID(OR_INPUTS)) |
---|
280 | error('OR Input trigger ID invalid') |
---|
281 | else |
---|
282 | OR_INPUTS = OR_INPUTS - obj.TRIGGER_INPUT_FLAG; % Strip flag to pass value to node |
---|
283 | end |
---|
284 | |
---|
285 | if (~obj.isInputID(AND_INPUTS)) |
---|
286 | error('AND Input trigger ID invalid') |
---|
287 | else |
---|
288 | AND_INPUTS = AND_INPUTS - obj.TRIGGER_INPUT_FLAG; % Strip flag to pass value to node |
---|
289 | end |
---|
290 | |
---|
291 | if(~isempty(OUTPUTS)) |
---|
292 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
293 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
294 | else |
---|
295 | error('Output trigger argument must be non-empty') |
---|
296 | end |
---|
297 | |
---|
298 | myCmd.addArgs(uint32(length(OR_INPUTS))); |
---|
299 | |
---|
300 | if(~isempty(OR_INPUTS)) |
---|
301 | myCmd.addArgs(uint32(OR_INPUTS)); |
---|
302 | end |
---|
303 | |
---|
304 | myCmd.addArgs(uint32(length(AND_INPUTS))); |
---|
305 | |
---|
306 | if(~isempty(AND_INPUTS)) |
---|
307 | myCmd.addArgs(uint32(AND_INPUTS)); |
---|
308 | end |
---|
309 | |
---|
310 | node.sendCmd(myCmd); |
---|
311 | |
---|
312 | %--------------------------------------------------------- |
---|
313 | case 'output_config_delay' |
---|
314 | % Configures specified output triggers to be have an |
---|
315 | % additional delay relative to their inputs |
---|
316 | % |
---|
317 | % Arguments: (uint32 OUTPUTS), (double DELAY_NS) |
---|
318 | % Returns: none |
---|
319 | % |
---|
320 | % OUTPUTS: vector of output trigger IDs, provided by |
---|
321 | % wl_getTriggerOutputIDs |
---|
322 | % |
---|
323 | % DELAY_NS: scalar value of the intended delay, |
---|
324 | % specified in nanoseconds (1e-9 seconds) |
---|
325 | % |
---|
326 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_OUTPUT_DELAY)); |
---|
327 | |
---|
328 | OUTPUTS = varargin{1}; |
---|
329 | delay_ns = varargin{2}; |
---|
330 | |
---|
331 | % Check IDs |
---|
332 | if (~obj.isOutputID(OUTPUTS)) |
---|
333 | error('Output trigger ID invalid') |
---|
334 | end |
---|
335 | |
---|
336 | if(~isempty(OUTPUTS)) |
---|
337 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
338 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
339 | else |
---|
340 | error('Output trigger argument must be non-empty') |
---|
341 | end |
---|
342 | |
---|
343 | for k = 1:length(OUTPUTS) |
---|
344 | index = find(OUTPUTS(k) == obj.triggerOutputIDs); |
---|
345 | |
---|
346 | if k == 1 |
---|
347 | enforced_step = obj.output_delayStep_ns(index); |
---|
348 | enforced_max = obj.output_delayMax_ns(index); |
---|
349 | else |
---|
350 | enforced_step = max([enforced_step, obj.output_delayStep_ns(index)]); |
---|
351 | enforced_max = min([enforced_max, obj.output_delayMax_ns(index)]); |
---|
352 | end |
---|
353 | end |
---|
354 | |
---|
355 | if (delay_ns < enforced_max) |
---|
356 | requested_delay = floor(delay_ns/enforced_step); |
---|
357 | else |
---|
358 | requested_delay = floor(enforced_max/enforced_step); |
---|
359 | end |
---|
360 | |
---|
361 | if ( ~(requested_delay == delay_ns/enforced_step) ) |
---|
362 | warning('Node %d with Serial # %d has a delay step of %.3f ns and a maximum delay of %.3f ns.\nRequested output delay of %.3f ns actually set to %.3f ns.', node.ID, node.serialNumber, enforced_step, enforced_max, delay_ns, enforced_step*requested_delay); |
---|
363 | end |
---|
364 | |
---|
365 | myCmd.addArgs(requested_delay); |
---|
366 | node.sendCmd(myCmd); |
---|
367 | |
---|
368 | %--------------------------------------------------------- |
---|
369 | case 'output_config_hold_mode' |
---|
370 | % Configures whether specified output triggers should |
---|
371 | % hold their outputs once triggered |
---|
372 | % |
---|
373 | % Arguments: (uint32 OUTPUTS), (boolean MODE) |
---|
374 | % Returns: none |
---|
375 | % |
---|
376 | % OUTPUTS: vector of output trigger IDs, provided by |
---|
377 | % wl_getTriggerOutputIDs |
---|
378 | % |
---|
379 | % MODE: true enables output hold mode |
---|
380 | % false disables output hold mode |
---|
381 | % |
---|
382 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_OUTPUT_HOLD)); |
---|
383 | |
---|
384 | OUTPUTS = varargin{1}; |
---|
385 | mode = varargin{2}; |
---|
386 | |
---|
387 | if (ischar(mode)) |
---|
388 | % Print warning that this syntax will be deprecated |
---|
389 | try |
---|
390 | temp = evalin('base', 'wl_output_config_hold_mode_did_warn'); |
---|
391 | catch |
---|
392 | fprintf('WARNING: This syntax for output_config_hold_mode() is being deprecated.\n'); |
---|
393 | fprintf('WARNING: Please use: wl_triggerManagerCmd(node, ''output_config_hold_mode'', OUTPUTS, <true, false>);\n'); |
---|
394 | fprintf('WARNING: See WARPLab documentation for more information\n\n'); |
---|
395 | |
---|
396 | assignin('base', 'wl_output_config_hold_mode_did_warn', 1) |
---|
397 | end |
---|
398 | |
---|
399 | if(strcmp(lower(mode),'enable')) |
---|
400 | mode = 0; |
---|
401 | elseif(strcmp(lower(mode),'disable')) |
---|
402 | mode = 1; |
---|
403 | else |
---|
404 | error('mode selection must be ''enable'' or ''disable''') |
---|
405 | end |
---|
406 | elseif (islogical(mode)) |
---|
407 | if(mode) |
---|
408 | mode = 0; |
---|
409 | else |
---|
410 | mode = 1; |
---|
411 | end |
---|
412 | else |
---|
413 | error('mode selection must be true or false') |
---|
414 | end |
---|
415 | |
---|
416 | % Check IDs |
---|
417 | if (~obj.isOutputID(OUTPUTS)) |
---|
418 | error('Output trigger ID invalid') |
---|
419 | end |
---|
420 | |
---|
421 | if(~isempty(OUTPUTS)) |
---|
422 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
423 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
424 | else |
---|
425 | error('Output trigger argument must be non-empty') |
---|
426 | end |
---|
427 | |
---|
428 | myCmd.addArgs(mode); |
---|
429 | node.sendCmd(myCmd); |
---|
430 | |
---|
431 | %--------------------------------------------------------- |
---|
432 | case 'output_state_read' |
---|
433 | % Reads current state of output triggers. Note: this |
---|
434 | % command is intended to be used on output triggers |
---|
435 | % that have enabled their hold mode. |
---|
436 | % |
---|
437 | % Arguments: (uint32 OUTPUTS) |
---|
438 | % Returns: (bool STATES) |
---|
439 | % |
---|
440 | % OUTPUTS: vector of output trigger IDs, provided by |
---|
441 | % wl_getTriggerOutputIDs |
---|
442 | % |
---|
443 | % STATES: vector of (true, false) trigger states |
---|
444 | % corresponding to state of OUTPUTS vector |
---|
445 | % |
---|
446 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_OUTPUT_READ)); |
---|
447 | |
---|
448 | OUTPUTS = varargin{1}; |
---|
449 | |
---|
450 | % Check IDs |
---|
451 | if (~obj.isOutputID(OUTPUTS)) |
---|
452 | error('Output trigger ID invalid') |
---|
453 | end |
---|
454 | |
---|
455 | if(~isempty(OUTPUTS)) |
---|
456 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
457 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
458 | else |
---|
459 | error('Output trigger argument must be non-empty') |
---|
460 | end |
---|
461 | |
---|
462 | resp = node.sendCmd(myCmd); |
---|
463 | out = resp.getArgs(); |
---|
464 | |
---|
465 | %--------------------------------------------------------- |
---|
466 | case 'output_state_clear' |
---|
467 | % Clears current state of output triggers. |
---|
468 | % |
---|
469 | % Arguments: (uint32 OUTPUTS) |
---|
470 | % Returns: none |
---|
471 | % |
---|
472 | % OUTPUTS: vector of output trigger IDs, provided by |
---|
473 | % wl_getTriggerOutputIDs |
---|
474 | % |
---|
475 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_OUTPUT_CLEAR)); |
---|
476 | |
---|
477 | OUTPUTS = varargin{1}; |
---|
478 | |
---|
479 | % Check IDs |
---|
480 | if (~obj.isOutputID(OUTPUTS)) |
---|
481 | error('Output trigger ID invalid') |
---|
482 | end |
---|
483 | |
---|
484 | if(~isempty(OUTPUTS)) |
---|
485 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
486 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
487 | else |
---|
488 | error('Output trigger argument must be non-empty') |
---|
489 | end |
---|
490 | |
---|
491 | resp = node.sendCmd(myCmd); |
---|
492 | out = resp.getArgs(); |
---|
493 | |
---|
494 | %--------------------------------------------------------- |
---|
495 | case 'input_config_enable_selection' |
---|
496 | fprintf('In WARPLab 7.6.0, the input_config_enable_selection command is no longer\n'); |
---|
497 | fprintf('supported. This command is not necessary since you can disable any input\n'); |
---|
498 | fprintf('by disconnecting it from the output.\n'); |
---|
499 | |
---|
500 | %--------------------------------------------------------- |
---|
501 | case 'input_config_debounce_mode' |
---|
502 | % Configures specified input triggers to enable or |
---|
503 | % disable debounce circuit. Note: debounce circuit adds |
---|
504 | % delay of 4 cycles, where each cycle is a duration |
---|
505 | % specified in the input_delayStep_ns property of the |
---|
506 | % wl_manager_proc.m class. |
---|
507 | % |
---|
508 | % Arguments: (uint32 INPUTS), (boolean MODE) |
---|
509 | % Returns: none |
---|
510 | % |
---|
511 | % INPUTS: vector of output trigger IDs, provided by |
---|
512 | % wl_getTriggerInputIDs |
---|
513 | % |
---|
514 | % MODE: true enables input debounce mode |
---|
515 | % false disables input debounce mode |
---|
516 | % |
---|
517 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_INPUT_DEBOUNCE)); |
---|
518 | |
---|
519 | INPUTS = varargin{1}; |
---|
520 | mode = varargin{2}; |
---|
521 | input_ids = node.wl_getTriggerInputIDs(); |
---|
522 | |
---|
523 | if (ischar(mode)) |
---|
524 | % Print warning that this syntax will be deprecated |
---|
525 | try |
---|
526 | temp = evalin('base', 'wl_input_config_debounce_mode_did_warn'); |
---|
527 | catch |
---|
528 | fprintf('WARNING: This syntax for input_config_debounce_mode() is being deprecated.\n'); |
---|
529 | fprintf('WARNING: Please use: wl_triggerManagerCmd(node, ''input_config_debounce_mode'', INPUTS, <true, false>);\n'); |
---|
530 | fprintf('WARNING: See WARPLab documentation for more information\n\n'); |
---|
531 | |
---|
532 | assignin('base', 'wl_input_config_debounce_mode_did_warn', 1) |
---|
533 | end |
---|
534 | |
---|
535 | if(strcmp(lower(mode),'enable')) |
---|
536 | mode = 1; |
---|
537 | elseif(strcmp(lower(mode),'disable')) |
---|
538 | mode = 0; |
---|
539 | else |
---|
540 | error('mode selection must be ''enable'' or ''disable''') |
---|
541 | end |
---|
542 | elseif (islogical(mode)) |
---|
543 | if(mode) |
---|
544 | mode = 1; |
---|
545 | else |
---|
546 | mode = 0; |
---|
547 | end |
---|
548 | else |
---|
549 | error('mode selection must be true or false') |
---|
550 | end |
---|
551 | |
---|
552 | for k = 1:length(INPUTS) |
---|
553 | if ((INPUTS(k) == input_ids.ETH_A) || (INPUTS(k) == input_ids.ETH_B) || (INPUTS(k) == input_ids.ENERGY_DET) || (INPUTS(k) == input_ids.AGC_DONE) || (INPUTS(k) == input_ids.SW_REG)) |
---|
554 | error('one or more selected inputs do not have debounce circuitry') |
---|
555 | end |
---|
556 | end |
---|
557 | |
---|
558 | % Check IDs |
---|
559 | if (~obj.isInputID(INPUTS)) |
---|
560 | error('Input trigger ID invalid') |
---|
561 | else |
---|
562 | INPUTS = INPUTS - obj.TRIGGER_INPUT_FLAG; % Strip flag to pass value to node |
---|
563 | end |
---|
564 | |
---|
565 | if(~isempty(INPUTS)) |
---|
566 | myCmd.addArgs(uint32(length(INPUTS))); |
---|
567 | myCmd.addArgs(uint32(INPUTS)); |
---|
568 | else |
---|
569 | error('Input trigger argument must be non-empty') |
---|
570 | end |
---|
571 | |
---|
572 | myCmd.addArgs(mode); |
---|
573 | node.sendCmd(myCmd); |
---|
574 | |
---|
575 | %--------------------------------------------------------- |
---|
576 | case 'input_config_delay' |
---|
577 | % Configures specified input triggers to be have an |
---|
578 | % additional delay relative to their inputs |
---|
579 | % |
---|
580 | % Arguments: (uint32 INPUTS), (double DELAY_NS) |
---|
581 | % Returns: none |
---|
582 | % |
---|
583 | % INPUTS: vector of input trigger IDs, provided by |
---|
584 | % wl_getTriggerInputIDs |
---|
585 | % |
---|
586 | % DELAY_NS: scalar value of the intended delay, |
---|
587 | % specified in nanoseconds (1e-9 seconds) |
---|
588 | % |
---|
589 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_INPUT_DELAY)); |
---|
590 | |
---|
591 | INPUTS = varargin{1}; |
---|
592 | delay_ns = varargin{2}; |
---|
593 | |
---|
594 | % Check IDs |
---|
595 | if (~obj.isInputID(INPUTS)) |
---|
596 | error('Input trigger ID invalid') |
---|
597 | else |
---|
598 | INPUTS = INPUTS - obj.TRIGGER_INPUT_FLAG; % Strip flag to pass value to node |
---|
599 | end |
---|
600 | |
---|
601 | if(~isempty(INPUTS)) |
---|
602 | myCmd.addArgs(uint32(length(INPUTS))); |
---|
603 | myCmd.addArgs(uint32(INPUTS)); |
---|
604 | else |
---|
605 | error('Input trigger argument must be non-empty') |
---|
606 | end |
---|
607 | |
---|
608 | for k = 1:length(INPUTS) |
---|
609 | % Find the index of the ID |
---|
610 | % NOTE: Add trigger input flag when finding the index because it was stripped off above |
---|
611 | % |
---|
612 | index = find((INPUTS(k) + obj.TRIGGER_INPUT_FLAG) == obj.triggerInputIDs); |
---|
613 | |
---|
614 | if k == 1 |
---|
615 | enforced_step = obj.input_delayStep_ns(index); |
---|
616 | enforced_max = obj.input_delayMax_ns(index); |
---|
617 | else |
---|
618 | enforced_step = max([enforced_step, obj.input_delayStep_ns(index)]); |
---|
619 | enforced_max = min([enforced_max, obj.input_delayMax_ns(index)]); |
---|
620 | end |
---|
621 | end |
---|
622 | |
---|
623 | if (delay_ns < enforced_max) |
---|
624 | requested_delay = floor(delay_ns/enforced_step); |
---|
625 | else |
---|
626 | requested_delay = floor(enforced_max/enforced_step); |
---|
627 | end |
---|
628 | |
---|
629 | if (~(requested_delay == delay_ns/enforced_step)) |
---|
630 | warning('Node %d with Serial # %d has a delay step of %.3f ns and a maximum delay of %.3f ns.\nRequested output delay of %.3f ns actually set to %.3f ns.', node.ID, node.serialNumber, enforced_step, enforced_max, delay_ns, enforced_step*requested_delay); |
---|
631 | end |
---|
632 | |
---|
633 | myCmd.addArgs(requested_delay); |
---|
634 | node.sendCmd(myCmd); |
---|
635 | |
---|
636 | %--------------------------------------------------------- |
---|
637 | case 'energy_config_busy_threshold' |
---|
638 | % Configures the threshold above which RSSI is |
---|
639 | % considered as a "busy" medium. |
---|
640 | % |
---|
641 | % Arguments: (uint32 THRESH) |
---|
642 | % Returns: none |
---|
643 | % |
---|
644 | % THRESH: busy threshold. For the MAX2829-based |
---|
645 | % interfaces, WARP uses a 10-bit ADC for |
---|
646 | % RSSI (range of [0,1023]). |
---|
647 | % |
---|
648 | % Note: RSSI averaging in the core does NOT divide by |
---|
649 | % the number of samples that are summed together. |
---|
650 | % Averaging by N cycles means that the maximum possible |
---|
651 | % RSSI post-averaging is N*1023. |
---|
652 | % |
---|
653 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ENERGY_BUSY_THRESH)); |
---|
654 | |
---|
655 | thresh_busy = varargin{1}; |
---|
656 | |
---|
657 | myCmd.addArgs(thresh_busy); |
---|
658 | node.sendCmd(myCmd); |
---|
659 | |
---|
660 | %--------------------------------------------------------- |
---|
661 | case 'energy_config_average_length' |
---|
662 | % Configures the number of samples over which RSSI is |
---|
663 | % averaged before it is compared to any threshold. |
---|
664 | % |
---|
665 | % Arguments: (uint32 LENGTH) |
---|
666 | % Returns: none |
---|
667 | % |
---|
668 | % LENGTH: Number of samples over which RSSI is |
---|
669 | % averaged. |
---|
670 | % |
---|
671 | % Note: For all hardware versions, RSSI is sampled at |
---|
672 | % 10 MHz. Each sample is, therefore, 100 ns. |
---|
673 | % |
---|
674 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ENERGY_AVG_LEN)); |
---|
675 | |
---|
676 | avgLen = varargin{1}; |
---|
677 | |
---|
678 | myCmd.addArgs(avgLen); |
---|
679 | node.sendCmd(myCmd); |
---|
680 | |
---|
681 | %--------------------------------------------------------- |
---|
682 | case 'energy_config_busy_minlength' |
---|
683 | % Average RSSI samples must exceed the busy threshold |
---|
684 | % for a minimum number of samples before the trigger is |
---|
685 | % activated. This command sets this minimum value. |
---|
686 | % |
---|
687 | % Arguments: (uint32 LENGTH) |
---|
688 | % Returns: none |
---|
689 | % |
---|
690 | % LENGTH: Minimum number of samples that RSSI must |
---|
691 | % be busy before trigger is raised. |
---|
692 | % |
---|
693 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ENERGY_BUSY_MIN_LEN)); |
---|
694 | |
---|
695 | minLen = varargin{1}; |
---|
696 | |
---|
697 | myCmd.addArgs(minLen); |
---|
698 | node.sendCmd(myCmd); |
---|
699 | |
---|
700 | %--------------------------------------------------------- |
---|
701 | case 'energy_config_interface_selection' |
---|
702 | % Selects the interfaces from which energy detection |
---|
703 | % should base its decision |
---|
704 | % |
---|
705 | % Arguments: (uint32 IFCSELECTION) |
---|
706 | % Returns: none |
---|
707 | % |
---|
708 | % IFCSELECTION: One or more interfaces that the |
---|
709 | % energy detector system should |
---|
710 | % monitor |
---|
711 | % |
---|
712 | % Note: IFCSELECTION is intended to be used with the |
---|
713 | % return values from the wl_getInterfaceIDs method. |
---|
714 | % |
---|
715 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ENERGY_IFC_SELECTION)); |
---|
716 | |
---|
717 | ifcSel = varargin{1}; |
---|
718 | |
---|
719 | myCmd.addArgs(ifcSel); |
---|
720 | node.sendCmd(myCmd); |
---|
721 | |
---|
722 | %--------------------------------------------------------- |
---|
723 | case 'input_config_idelay' |
---|
724 | % Configures the IDELAY values for specified input triggers. |
---|
725 | % |
---|
726 | % Arguments: (uint32 INPUTS), (string TYPE), (uint32 VALUES) |
---|
727 | % Returns: none |
---|
728 | % |
---|
729 | % INPUTS: Vector of input trigger IDs, provided by wl_getTriggerInputIDs |
---|
730 | % |
---|
731 | % TYPE: 'ext_pin' or 'cm_pll' - Can modify the IDELAY for the path |
---|
732 | % from the external pin independent of the CM-PLL input path |
---|
733 | % |
---|
734 | % VALUES: Scaler value in [0, 31] or Vector of values equal in length |
---|
735 | % to the INPUTS vector |
---|
736 | % |
---|
737 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_IDELAY)); |
---|
738 | |
---|
739 | % Check arguments |
---|
740 | if(length(varargin) ~= 3) |
---|
741 | error('%s: Requires three arguments: Input Trigger ID(s), Type, Value(s)', cmdStr); |
---|
742 | end |
---|
743 | |
---|
744 | INPUTS = varargin{1}; |
---|
745 | type = varargin{2}; |
---|
746 | VALUES = varargin{3}; |
---|
747 | input_ids = node.wl_getTriggerInputIDs(); |
---|
748 | |
---|
749 | % Convert type and add it to the command arguments |
---|
750 | if(strcmp(lower(type), 'ext_pin')) |
---|
751 | type = 0; |
---|
752 | elseif(strcmp(lower(type), 'cm_pll')) |
---|
753 | type = 1; |
---|
754 | else |
---|
755 | error('TYPE selection must be ''ext_pin'' or ''cm_pll''') |
---|
756 | end |
---|
757 | |
---|
758 | myCmd.addArgs(type); |
---|
759 | |
---|
760 | % Check inputs |
---|
761 | for k = 1:length(INPUTS) |
---|
762 | if ((INPUTS(k) == input_ids.ETH_A) || (INPUTS(k) == input_ids.ETH_B) || (INPUTS(k) == input_ids.ENERGY_DET) || (INPUTS(k) == input_ids.AGC_DONE) || (INPUTS(k) == input_ids.SW_REG)) |
---|
763 | error('One or more selected inputs do not have IDELAY circuitry.') |
---|
764 | end |
---|
765 | end |
---|
766 | |
---|
767 | % Check values |
---|
768 | if ((length(VALUES) ~= 1) && (length(VALUES) ~= length(INPUTS))) |
---|
769 | error('VALUES must either be a scalar or a vector of the same length as the input trigger IDs.') |
---|
770 | end |
---|
771 | |
---|
772 | for k = 1:length(VALUES) |
---|
773 | if ((VALUES(k) < 0) || (VALUES(k) > 31)) |
---|
774 | error('Values must be in [0, 31]') |
---|
775 | end |
---|
776 | end |
---|
777 | |
---|
778 | % Check IDs |
---|
779 | if (~obj.isInputID(INPUTS)) |
---|
780 | error('Input trigger ID invalid') |
---|
781 | else |
---|
782 | INPUTS = INPUTS - obj.TRIGGER_INPUT_FLAG; % Strip flag to pass value to node |
---|
783 | end |
---|
784 | |
---|
785 | % Add input trigger IDs to the command |
---|
786 | if(~isempty(INPUTS)) |
---|
787 | myCmd.addArgs(uint32(length(INPUTS))); |
---|
788 | myCmd.addArgs(uint32(INPUTS)); |
---|
789 | else |
---|
790 | error('Input trigger ID argument must be non-empty') |
---|
791 | end |
---|
792 | |
---|
793 | % Add values to the command |
---|
794 | if (length(VALUES) == 1) |
---|
795 | for k = 1:length(INPUTS) |
---|
796 | myCmd.addArgs(uint32(VALUES)); |
---|
797 | end |
---|
798 | else |
---|
799 | myCmd.addArgs(uint32(VALUES)); |
---|
800 | end |
---|
801 | |
---|
802 | % Send the command to the node |
---|
803 | node.sendCmd(myCmd); |
---|
804 | |
---|
805 | %--------------------------------------------------------- |
---|
806 | case 'output_config_odelay' |
---|
807 | % Configures the ODELAY values for specified output triggers. |
---|
808 | % |
---|
809 | % Arguments: (uint32 OUTPUTS), (string TYPE), (uint32 VALUES) |
---|
810 | % Returns: none |
---|
811 | % |
---|
812 | % OUTPUTS: Vector of output trigger IDs, provided by wl_getTriggerOutputIDs |
---|
813 | % |
---|
814 | % TYPE: 'ext_pin' or 'cm_pll' - Can modify the IDELAY for the path |
---|
815 | % from the external pin independent of the CM-PLL input path |
---|
816 | % |
---|
817 | % VALUES: Scaler value in [0, 31] or Vector of values equal in length |
---|
818 | % to the OUTPUTS vector |
---|
819 | % |
---|
820 | myCmd = wl_cmd(node.calcCmd(obj.GRP, obj.CMD_ODELAY)); |
---|
821 | |
---|
822 | % Check arguments |
---|
823 | if(length(varargin) ~= 3) |
---|
824 | error('%s: Requires three arguments: Output Trigger ID(s), Type, Value(s)', cmdStr); |
---|
825 | end |
---|
826 | |
---|
827 | OUTPUTS = varargin{1}; |
---|
828 | type = varargin{2}; |
---|
829 | VALUES = varargin{3}; |
---|
830 | output_ids = node.wl_getTriggerOutputIDs(); |
---|
831 | |
---|
832 | % Convert type and add it to the command arguments |
---|
833 | if(strcmp(lower(type), 'ext_pin')) |
---|
834 | type = 0; |
---|
835 | elseif(strcmp(lower(type), 'cm_pll')) |
---|
836 | type = 1; |
---|
837 | else |
---|
838 | error('TYPE selection must be ''ext_pin'' or ''cm_pll''') |
---|
839 | end |
---|
840 | |
---|
841 | myCmd.addArgs(type); |
---|
842 | |
---|
843 | % Check outputs |
---|
844 | for k = 1:length(OUTPUTS) |
---|
845 | if ((OUTPUTS(k) == output_ids.BASEBAND) || (OUTPUTS(k) == output_ids.AGC)) |
---|
846 | error('One or more selected outputs do not have ODELAY circuitry.') |
---|
847 | end |
---|
848 | end |
---|
849 | |
---|
850 | % Check values |
---|
851 | if ((length(VALUES) ~= 1) && (length(VALUES) ~= length(OUTPUTS))) |
---|
852 | error('VALUES must either be a scalar or a vector of the same length as the output trigger IDs.') |
---|
853 | end |
---|
854 | |
---|
855 | for k = 1:length(VALUES) |
---|
856 | if ((VALUES(k) < 0) || (VALUES(k) > 31)) |
---|
857 | error('Values must be in [0, 31]') |
---|
858 | end |
---|
859 | end |
---|
860 | |
---|
861 | % Check IDs |
---|
862 | if (~obj.isOutputID(OUTPUTS)) |
---|
863 | error('Output trigger ID invalid') |
---|
864 | end |
---|
865 | |
---|
866 | % Add output trigger IDs to the command |
---|
867 | if(~isempty(OUTPUTS)) |
---|
868 | myCmd.addArgs(uint32(length(OUTPUTS))); |
---|
869 | myCmd.addArgs(uint32(OUTPUTS)); |
---|
870 | else |
---|
871 | error('Output trigger ID argument must be non-empty') |
---|
872 | end |
---|
873 | |
---|
874 | % Add values to the command |
---|
875 | if (length(VALUES) == 1) |
---|
876 | for k = 1:length(OUTPUTS) |
---|
877 | myCmd.addArgs(uint32(VALUES)); |
---|
878 | end |
---|
879 | else |
---|
880 | myCmd.addArgs(uint32(VALUES)); |
---|
881 | end |
---|
882 | |
---|
883 | % Send the command to the node |
---|
884 | node.sendCmd(myCmd); |
---|
885 | |
---|
886 | %--------------------------------------------------------- |
---|
887 | case 'test_trigger' |
---|
888 | % Sends a test trigger |
---|
889 | % |
---|
890 | % Arguments: none |
---|
891 | % Returns: none |
---|
892 | |
---|
893 | myCmd = wl_cmd(node.calcCmd(obj.GRP,obj.CMD_TEST_TRIGGER)); |
---|
894 | resp = node.sendCmd(myCmd); |
---|
895 | out = resp.getArgs(); |
---|
896 | |
---|
897 | otherwise |
---|
898 | error('unknown command ''%s''',cmdStr); |
---|
899 | end |
---|
900 | |
---|
901 | % Set the outputs |
---|
902 | if(iscell(out)==0 && numel(out)~=1) |
---|
903 | out = {out}; |
---|
904 | end |
---|
905 | end |
---|
906 | end |
---|
907 | end |
---|