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
RevLine 
[2046]1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[2047]2% wl_example_siso_txrx_nodeSync.m
[2046]3%
[2047]4% This example illustrates how to synchronize multiple WARP v3 nodes
5% to eliminate all frequency and timing offsets.
[2046]6%
[4689]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
[2050]15%
[4689]16% More details on using this example are available on the WARP site:
17%     http://warpproject.org/w/WARPLab/Examples
18%
[2046]19%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[2050]20
[2046]21%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[4689]22% Top Level Control Variables
[2046]23%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24
[4689]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)
[4485]27%
[4689]28USE_EXTERNAL_TRIGGER = true;
[2046]29
[4689]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%
[4819]37BYPASS_INIT_NODES = false;
[4485]38
39% RX variables
[4373]40USE_AGC        = true;
[4485]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)
[4373]43
[4689]44%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45% Set up the WARPLab experiment
46%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47
[4373]48% Create a vector of node objects
[4689]49if ( ~BYPASS_INIT_NODES )
[2046]50
[4689]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
[4485]68% Assign roles to the nodes (ie transmitter / receiver)
[4336]69node_tx = nodes(1);
70node_rx = nodes(2);
71
[4689]72
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74% Set up Trigger Manager
75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76
[4373]77% Create a UDP broadcast trigger and primary node to be ready for it
[2046]78eth_trig = wl_trigger_eth_udp_broadcast;
[4478]79nodes.wl_triggerManagerCmd('add_ethernet_trigger', [eth_trig]);
[2046]80
[4373]81% Read Trigger IDs into workspace
[4689]82trig_in_ids  = wl_getTriggerInputIDs(node_tx);
83trig_out_ids = wl_getTriggerOutputIDs(node_tx);
[2046]84
[4689]85% For the transmit node, we will allow Ethernet to trigger the buffer baseband, the AGC, and debug0
[4373]86% (which is mapped to pin 8 on the debug header)
[4689]87node_tx.wl_triggerManagerCmd('output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.EXT_OUT_P0], [trig_in_ids.ETH_A]);
[2046]88
89if(USE_EXTERNAL_TRIGGER)
[4373]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
[4702]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]);
[2046]97else
[4689]98    node_rx.wl_triggerManagerCmd('output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.ETH_A]);
[2046]99end
[2047]100
[4373]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.
[4984]103node_rx.wl_triggerManagerCmd('input_config_debounce_mode', [trig_in_ids.EXT_IN_P0, trig_in_ids.EXT_IN_P3], true); 
[2046]104
[4373]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.
[4702]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
[4689]111node_rx.wl_triggerManagerCmd('output_config_delay', [trig_out_ids.AGC], 3000);          % 3000ns delay
[2046]112
113
[4689]114%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115% Set up the Interface parameters
116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[4336]117
[4689]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);
[2046]124
[4689]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%
[2046]148if(USE_AGC)
[4689]149    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'automatic');
[4373]150    wl_basebandCmd(nodes, 'agc_target', -10);
[2046]151else
[4689]152    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'manual');
153    wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gains', ManualRxGainRF, ManualRxGainBB);
[2046]154end
155
[4689]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%
[4336]179maximum_buffer_len = wl_basebandCmd(node_tx, RF_TX, 'tx_buff_max_num_samples');
180
[4689]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;
[4336]187
[4689]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
[2046]192
[4689]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);
[4373]196
[4689]197
[2046]198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199% Signal processing to generate transmit signal
200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201
[4689]202% First generate the preamble for AGC.
203%     NOTE:  The preamble corresponds to the short symbols from the 802.11a PHY standard
204%
[2046]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));
[4689]209shortsyms_rep    = repmat(shortSymbol_time,1,30);
210preamble         = shortsyms_rep;
211preamble         = preamble(:);
[2046]212
213
[4689]214t = [0:ts:((tx_length - length(preamble) - 1))*ts].';      % Create time vector(Sample Frequency is ts (Hz))
[2046]215
[4689]216sinusoid  = 0.6 * exp(j*2*pi * 2e6 * t);                   % Create 2 MHz sinusoid
[2046]217
[4689]218tx_data   = [preamble; sinusoid];
[2046]219
[4373]220
[2046]221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222% Transmit and receive signal using WARPLab
223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224
[4485]225% Transmit IQ data to the TX node
[4689]226wl_basebandCmd(node_tx, RF_TX_VEC, 'write_IQ', tx_data(:));
[4485]227
228% Enabled the RF interfaces for TX / RX
[4373]229wl_interfaceCmd(node_tx, RF_TX, 'tx_en');
230wl_interfaceCmd(node_rx, RF_RX, 'rx_en');
[2046]231
[4485]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');
[2046]235
[4485]236% Send the Ethernet trigger to start the TX
[2047]237eth_trig.send();
[4336]238
[4485]239% Read the IQ data from the RX node
[4689]240rx_IQ    = wl_basebandCmd(node_rx, RF_RX_VEC, 'read_IQ', 0, rx_length);
[4485]241
242% Disable the buffers and RF interfaces for TX / RX
[4689]243wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis');
244wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis');
[2046]245
246%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247% Visualize results
248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[4689]249tVec = [0:ts:((tx_length -1 )*ts)]*1e6;
[2046]250
251sampStart = 5000;
[4689]252sampEnd = tx_length;
[2047]253htxt = [];
[2046]254
255figure(1);clf;
256subplot(3,1,1)
[4689]257plot(tVec(sampStart:sampEnd),real(tx_data(sampStart:sampEnd)),'b')
[2047]258htxt(end+1) = ylabel('Amplitude');
259htxt(end+1) = title('Transmitted I Waveform');
260axis([tVec(sampStart) tVec(sampEnd) -1 1]);
261grid on;
[2046]262
263subplot(3,1,2)
[2047]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;
[2046]269
270subplot(3,1,3)
[4689]271phase_diff = unwrap(angle(rx_IQ(sampStart:sampEnd))) - unwrap(angle(tx_data(sampStart:sampEnd)));
[2047]272plot(tVec(sampStart:sampEnd), phase_diff)
[4340]273axis tight
[4343]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
[2047]282grid on;
[4336]283htxt(end+1) = title('Tx-Rx Phase Offset');
[2047]284htxt(end+1) = ylabel('Phase Difference (radians)');
285htxt(end+1) = xlabel('Time (us)');
[2046]286
[2047]287set(htxt, 'FontWeight', 'bold');
Note: See TracBrowser for help on using the repository browser.