source: ResearchApps/PHY/WARPLAB/WARPLab7/M_Code_Examples/wl_example_siso_txrx_nodeSync.m

Last change on this file was 4984, checked in by welsh, 8 years ago

Fixing deprecated syntax warning.

File size: 11.7 KB
Line 
1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2% wl_example_siso_txrx_nodeSync.m
3%
4% This example illustrates how to synchronize multiple WARP v3 nodes
5% to eliminate all frequency and timing offsets.
6%
7% Requirements:
8%     - 2 WARP nodes (same hardware generation); 1 RF interface each
9%     - Ether:
10%         - 2 CM-MMCX modules; MMCX coax cable assemblies to connect the CM-MMCX I/O
11%           and a 2-pin twisted pair cable assembly to route the inter-node trigger
12%         - 2 CM-PLL modules; CM-PLL connector
13%           (see:  http://warpproject.org/trac/wiki/HardwareUsersGuides/CM-PLL/Connectors#Cables )
14%     - WARPLab 7.6.0 and higher
15%
16% More details on using this example are available on the WARP site:
17%     http://warpproject.org/w/WARPLab/Examples
18%
19%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
20
21%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
22% Top Level Control Variables
23%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24
25% External trigger mode requires a connection from the trigger output EXT_OUT_P0 on node 0
26% to EXT_IN_P3 on node 1 (see http://warpproject.org/w/WARPLab/Examples for details)
27%
28USE_EXTERNAL_TRIGGER = true;
29
30% To maintain constant phase offsets among nodes sharing an RF reference clock, bypass
31% wl_initNodes() which executes a reset of the MAX2829 transceivers that forces a re-tune
32% of the PLL that changes the inter-node phases.
33%
34% NOTE:  This has to be false the first time this script is run otherwise, the script will
35%     not have the "nodes" variable populated.
36%
37BYPASS_INIT_NODES = false;
38
39% RX variables
40USE_AGC        = true;
41ManualRxGainRF = 1;                    % Rx RF Gain in [1:3] (ignored if USE_AGC is true)
42ManualRxGainBB = 15;                   % Rx Baseband Gain in [0:31] (ignored if USE_AGC is true)
43
44%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45% Set up the WARPLab experiment
46%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47
48% Create a vector of node objects
49if ( ~BYPASS_INIT_NODES )
50
51    nodes = wl_initNodes(2);
52
53else 
54    % This example assumes that the node is in the state from which it exits initNodes.
55    % If the example does not run initNodes to keep the phase offsets constant, then we need
56    % to issue a couple of commands to put the node in a known state.
57    %
58
59    % Set the transmit delay to zero
60    wl_basebandCmd(nodes, 'tx_delay', 0);
61
62    % Disable the buffers and RF interfaces for TX / RX
63    wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis');
64    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis');
65end
66
67
68% Assign roles to the nodes (ie transmitter / receiver)
69node_tx = nodes(1);
70node_rx = nodes(2);
71
72
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74% Set up Trigger Manager
75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76
77% Create a UDP broadcast trigger and primary node to be ready for it
78eth_trig = wl_trigger_eth_udp_broadcast;
79nodes.wl_triggerManagerCmd('add_ethernet_trigger', [eth_trig]);
80
81% Read Trigger IDs into workspace
82trig_in_ids  = wl_getTriggerInputIDs(node_tx);
83trig_out_ids = wl_getTriggerOutputIDs(node_tx);
84
85% For the transmit node, we will allow Ethernet to trigger the buffer baseband, the AGC, and debug0
86% (which is mapped to pin 8 on the debug header)
87node_tx.wl_triggerManagerCmd('output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.EXT_OUT_P0], [trig_in_ids.ETH_A]);
88
89if(USE_EXTERNAL_TRIGGER)
90    % For the receive node, we will allow debug3 (mapped to pin 15 on the
91    % debug header) to trigger the buffer baseband, and the AGC
92    % Note that the below line selects both P0 and P3. This will allow the
93    % script to work with either the CM-PLL (where output P0 directly
94    % connects to input P0) or the CM-MMCX (where output P0 is usually
95    % connected to input P3 since both neighbor ground pins).
96    node_rx.wl_triggerManagerCmd('output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.EXT_IN_P0, trig_in_ids.EXT_IN_P3]);
97else
98    node_rx.wl_triggerManagerCmd('output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.ETH_A]);
99end
100
101% For the receive node, we enable the debounce circuity on the debug 3 input
102% to deal with the fact that the signal may be noisy.
103node_rx.wl_triggerManagerCmd('input_config_debounce_mode', [trig_in_ids.EXT_IN_P0, trig_in_ids.EXT_IN_P3], true); 
104
105% Since the debounce circuitry is enabled, there will be a delay at the
106% receiver node for its input trigger. To better align the transmitter and
107% receiver, we can artifically delay the transmitters trigger outputs that
108% drive the buffer baseband and the AGC.
109node_tx.wl_triggerManagerCmd('output_config_delay', [trig_out_ids.EXT_OUT_P0], 0);
110node_tx.wl_triggerManagerCmd('output_config_delay', [trig_out_ids.BASEBAND], 62.5);     % 62.5ns delay
111node_rx.wl_triggerManagerCmd('output_config_delay', [trig_out_ids.AGC], 3000);          % 3000ns delay
112
113
114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115% Set up the Interface parameters
116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
118% Get IDs for the interfaces on the boards. 
119%
120% NOTE:  This example assumes each board has the same interface capabilities (ie 2 RF
121%   interfaces; RFA and RFB).  Therefore, we only need to get the IDs from one of the boards.
122%
123ifc_ids = wl_getInterfaceIDs(node_tx);
124
125% Set the Transmit and Receive interfaces
126%     Transmit from RFA of one node to RFA of the other node
127%
128% NOTE:  Variables are used to make it easier to change interfaces.
129%
130RF_TX         = ifc_ids.RF_A;                    % Transmit RF interface
131RF_RX         = ifc_ids.RF_A;                    % Receive RF interface
132
133RF_RX_VEC     = ifc_ids.RF_A;                    % Vector version of transmit RF interface
134RF_TX_VEC     = ifc_ids.RF_A;                    % Vector version of receive RF interface
135
136% Set the RF center frequency on all interfaces
137%     - Frequency Band  :  Must be 2.4 or 5, to select 2.4GHz or 5GHz channels
138%     - Channel         :  Must be an integer in [1,11] for BAND = 2.4; [1,23] for BAND = 5
139%
140wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'channel', 2.4, 11);
141
142% Set the RX gains on all interfaces or use AGC
143%     - Rx RF Gain      :  Must be an integer in [1:3]
144%     - Rx Baseband Gain:  Must be an integer in [0:31]
145%
146% NOTE:  The gains may need to be modified depending on your experimental setup
147%
148if(USE_AGC)
149    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'automatic');
150    wl_basebandCmd(nodes, 'agc_target', -10);
151else
152    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'manual');
153    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gains', ManualRxGainRF, ManualRxGainBB);
154end
155
156% Set the TX gains on all interfaces
157%     - Tx Baseband Gain:  Must be an integer in [0:3] for approx [-5, -3, -1.5, 0]dB baseband gain
158%     - Tx RF Gain      :  Must be an integer in [0:63] for approx [0:31]dB RF gain
159%
160% NOTE:  The gains may need to be modified depending on your experimental setup
161%
162wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_gains', 3, 30);
163
164
165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166% Set up the Baseband parameters
167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169% Get the sample frequency from the board
170ts      = 1 / (wl_basebandCmd(nodes(1), 'tx_buff_clk_freq'));
171
172% Read the maximum I/Q buffer length. 
173%
174% NOTE:  This example assumes that each board has the same baseband capabilities (ie both nodes are
175%   the same WARP hardware version, for example WARP v3).  This example also assumes that each RF
176%   interface has the same baseband capabilities (ie the max number of TX samples is the same as the
177%   max number of RF samples). Therefore, we only need to read the max I/Q buffer length of node_tx RFA.
178%
179maximum_buffer_len = wl_basebandCmd(node_tx, RF_TX, 'tx_buff_max_num_samples');
180
181% Set the transmission / receptions lengths (in samples)
182%     See WARPLab user guide for maximum length supported by WARP hardware
183%     versions and different WARPLab versions.
184%
185tx_length    = 2^15;
186rx_length    = tx_length;
187
188% Check the transmission length
189if (tx_length > maximum_buffer_len) 
190    error('Node supports max transmission length of %d samples.  Requested %d samples.', maximum_buffer_len, tx_length); 
191end
192
193% Set the length for the transmit and receive buffers based on the transmission length
194wl_basebandCmd(nodes, 'tx_length', tx_length);
195wl_basebandCmd(nodes, 'rx_length', rx_length);
196
197
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199% Signal processing to generate transmit signal
200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201
202% First generate the preamble for AGC.
203%     NOTE:  The preamble corresponds to the short symbols from the 802.11a PHY standard
204%
205shortSymbol_freq = [0 0 0 0 0 0 0 0 1+i 0 0 0 -1+i 0 0 0 -1-i 0 0 0 1-i 0 0 0 -1-i 0 0 0 1-i 0 0 0 0 0 0 0 1-i 0 0 0 -1-i 0 0 0 1-i 0 0 0 -1-i 0 0 0 -1+i 0 0 0 1+i 0 0 0 0 0 0 0].';
206shortSymbol_freq = [zeros(32,1);shortSymbol_freq;zeros(32,1)];
207shortSymbol_time = ifft(fftshift(shortSymbol_freq));
208shortSymbol_time = (shortSymbol_time(1:32).')./max(abs(shortSymbol_time));
209shortsyms_rep    = repmat(shortSymbol_time,1,30);
210preamble         = shortsyms_rep;
211preamble         = preamble(:);
212
213
214t = [0:ts:((tx_length - length(preamble) - 1))*ts].';      % Create time vector(Sample Frequency is ts (Hz))
215
216sinusoid  = 0.6 * exp(j*2*pi * 2e6 * t);                   % Create 2 MHz sinusoid
217
218tx_data   = [preamble; sinusoid];
219
220
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222% Transmit and receive signal using WARPLab
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224
225% Transmit IQ data to the TX node
226wl_basebandCmd(node_tx, RF_TX_VEC, 'write_IQ', tx_data(:));
227
228% Enabled the RF interfaces for TX / RX
229wl_interfaceCmd(node_tx, RF_TX, 'tx_en');
230wl_interfaceCmd(node_rx, RF_RX, 'rx_en');
231
232% Enable the buffers for TX / RX
233wl_basebandCmd(node_tx, RF_TX, 'tx_buff_en');
234wl_basebandCmd(node_rx, RF_RX, 'rx_buff_en');
235
236% Send the Ethernet trigger to start the TX
237eth_trig.send();
238
239% Read the IQ data from the RX node
240rx_IQ    = wl_basebandCmd(node_rx, RF_RX_VEC, 'read_IQ', 0, rx_length);
241
242% Disable the buffers and RF interfaces for TX / RX
243wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis');
244wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis');
245
246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247% Visualize results
248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249tVec = [0:ts:((tx_length -1 )*ts)]*1e6;
250
251sampStart = 5000;
252sampEnd = tx_length;
253htxt = [];
254
255figure(1);clf;
256subplot(3,1,1)
257plot(tVec(sampStart:sampEnd),real(tx_data(sampStart:sampEnd)),'b')
258htxt(end+1) = ylabel('Amplitude');
259htxt(end+1) = title('Transmitted I Waveform');
260axis([tVec(sampStart) tVec(sampEnd) -1 1]);
261grid on;
262
263subplot(3,1,2)
264plot(tVec(sampStart:sampEnd),real(rx_IQ(sampStart:sampEnd,:)), 'r')
265htxt(end+1) = ylabel('Amplitude');
266htxt(end+1) = title('Received I Waveform');
267axis([tVec(sampStart) tVec(sampEnd) -1 1]);
268grid on;
269
270subplot(3,1,3)
271phase_diff = unwrap(angle(rx_IQ(sampStart:sampEnd))) - unwrap(angle(tx_data(sampStart:sampEnd)));
272plot(tVec(sampStart:sampEnd), phase_diff)
273axis tight
274myAxis = axis;
275
276if(myAxis(4)-myAxis(3) < 2*pi)
277    %Zoom out to at least a 2*pi range of angles
278    axis([myAxis(1), myAxis(2), mean(myAxis(3:4))-pi, mean(myAxis(3:4))+pi]);
279
280end
281
282grid on;
283htxt(end+1) = title('Tx-Rx Phase Offset');
284htxt(end+1) = ylabel('Phase Difference (radians)');
285htxt(end+1) = xlabel('Time (us)');
286
287set(htxt, 'FontWeight', 'bold');
Note: See TracBrowser for help on using the repository browser.