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

Last change on this file was 4983, checked in by chunter, 9 years ago

added comment explaining trigger delay

File size: 9.7 KB
Line 
1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2% wl_example_8x2_array.m
3%
4% Description:
5%     See warpproject.org/trac/wiki/WARPLab/Examples/8x2Array
6%
7%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8clear;
9figure(1);clf;
10
11USE_AGC = true;
12RUN_CONTINOUSLY = false;
13
14MAX_TX_LEN = 32768;
15
16%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
17% Set up the WARPLab experiment
18%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
19
20% Create a vector of node objects
21%     
22% This experiment uses 3 nodes: 2 will act as a transmitter and 1 will act as a receiver:
23%     nodes(1): Primary transmitter
24%     nodes(2): Secondary transmitter (receives clocks and triggers from primary transmitter)
25%     nodes(3): Receiver
26%
27nodes    = wl_initNodes(3);
28
29node_tx1 = nodes(1);
30node_tx2 = nodes(2);
31node_rx  = nodes(3);
32
33
34% Create a UDP broadcast trigger and tell each node to be ready for it
35eth_trig = wl_trigger_eth_udp_broadcast;
36wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', [eth_trig]);
37
38% Read Trigger IDs into workspace
39trig_in_ids  = wl_getTriggerInputIDs(node_tx1);
40trig_out_ids = wl_getTriggerOutputIDs(node_tx1);
41
42% For the primary transmit node, we will allow Ethernet to trigger the baseband buffers,
43% the AGC, and external output pin 0 (which is mapped to pin 8 on the debug header). We
44% also will allow Ethernet to trigger the same signals for the receiving node.
45%
46wl_triggerManagerCmd([node_tx1, node_rx], 'output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC, trig_out_ids.EXT_OUT_P0], [trig_in_ids.ETH_A]);
47
48% For the secondary transmit node, we will allow external input pin 3 (mapped to pin 15
49% on the debug header) to trigger the baseband buffers, and the AGC
50%
51% Note that the below line selects both P0 and P3. This will allow the
52% script to work with either the CM-PLL (where output P0 directly
53% connects to input P0) or the CM-MMCX (where output P0 is usually
54% connected to input P3 since both neighbor ground pins).
55wl_triggerManagerCmd(node_tx2, 'output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.EXT_IN_P0, trig_in_ids.EXT_IN_P3]);
56
57% For the secondary transmit node, we enable the debounce circuity on the external input
58% pin 3 to guard against any noise in the trigger signal.
59%
60wl_triggerManagerCmd(node_tx2, 'input_config_debounce_mode', [trig_in_ids.EXT_IN_P0, trig_in_ids.EXT_IN_P3], false); 
61
62% To better align the transmitters, we artificially delay the primary
63% transmitter's trigger outputs that drive the baseband buffers. An
64% external trigger output on the primary transmitter will appear as a
65% trigger input at the secondary transmitter a minimum of 5 clock cycles
66% later (31.25ns). It will appear a minimum of 9 clock cycles later
67% (56.25ns) when the debounce circuitry is enabled.
68%
69wl_triggerManagerCmd(node_tx1, 'output_config_delay', [trig_out_ids.BASEBAND, trig_out_ids.AGC], 31.25);      % 31.25ns delay
70
71% Also, we need to delay the AGC on the receiver so that the transmitted waveform has time
72% to begin and propagate to the receiver so it can be sampled appropriately.
73%
74wl_triggerManagerCmd(node_rx, 'output_config_delay', [trig_out_ids.AGC], 3000);                               % 3000ns delay
75
76% Get IDs for the interfaces on the boards
77%     NOTE:  This example assumes each board has the same interface capabilities, we only
78%         need to get the IDs from one of the boards
79%
80ifc_ids_4RF = wl_getInterfaceIDs(node_tx1);
81ifc_ids_2RF = wl_getInterfaceIDs(node_rx);
82
83% Set up the interface for the experiment
84wl_interfaceCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_gains', 3, 30);
85
86% Set the channel
87%     NOTE:  Due to the different number of interfaces, we need to issue
88%     multiple commands to the differnt types of nodes
89%
90wl_interfaceCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'channel', 2.4, 1);
91wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'channel', 2.4, 1);
92
93if(USE_AGC)
94    wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_gain_mode', 'automatic');
95    wl_basebandCmd(node_rx,'agc_target',-8);
96else
97    RxGainRF = 1; % Rx RF Gain in [1:3]
98    RxGainBB = 4; % Rx Baseband Gain in [0:31]
99   
100    wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_gain_mode', 'manual');
101    wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_gains', RxGainRF, RxGainBB);
102end
103
104wl_interfaceCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_lpf_corn_freq', 2);  % Configure Tx for 36MHz of bandwidth
105wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_lpf_corn_freq', 3);               % Configure Rx for 36MHz of bandwidth
106
107% Read the transmitter's maximum I/Q buffer length
108maximum_buffer_len = wl_basebandCmd(node_tx1, ifc_ids_4RF.RF_A, 'tx_buff_max_num_samples');
109
110% Our transmission length for this example does not need to fill the entire transmit buffer,
111% so we will use the smaller of two values: the maximum buffer length the board can support
112% or an arbitrary value defined by this script.
113%
114txLength = min(MAX_TX_LEN, maximum_buffer_len);
115
116% Set up the baseband for the experiment
117wl_basebandCmd(nodes, 'tx_delay', 0);
118wl_basebandCmd(nodes, 'tx_length', txLength);
119wl_basebandCmd(nodes, 'rx_length', txLength);
120
121
122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123% Signal processing to generate transmit signal
124%
125% NOTE:  We can send any signal we want out of each of the 8 transmit antennas.
126%     For visualization, we'll send "pink" noise of 1MHz out of each, but centered
127%     at different parts of the 40MHz band.
128%
129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130
131% First generate the preamble for AGC
132%     NOTE:  The preamble corresponds to the short symbols from the 802.11a PHY standard
133%
134shortSymbol_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].';
135shortSymbol_freq = [zeros(32,1);shortSymbol_freq;zeros(32,1)];
136shortSymbol_time = ifft(fftshift(shortSymbol_freq));
137shortSymbol_time = (shortSymbol_time(1:32).')./max(abs(shortSymbol_time));
138shortsyms_rep    = repmat(shortSymbol_time,1,30);
139preamble_single  = shortsyms_rep;
140preamble_single  = preamble_single(:);
141
142shifts = floor(linspace(0,31,8));
143for k = 1:8
144   % Shift preamble for each antenna so we don't have accidental beamforming
145   preamble(:,k) = circshift(preamble_single,shifts(k));
146end
147
148% Constants for generating the payload
149Ts                 = 1 / (wl_basebandCmd(node_tx1, 'tx_buff_clk_freq'));
150BW                 = 1; %MHz
151
152% Generate the payload
153payload            = complex(randn(txLength-length(preamble),8),randn(txLength-length(preamble),8));
154payload_freq       = fftshift(fft(payload));
155freqVec            = linspace(-((1/Ts)/2e6),((1/Ts)/2e6), txLength - length(preamble));
156noise_centerFreqs  = linspace(-12,12,8);
157
158for k = 1:8
159    payload_freq((freqVec < (noise_centerFreqs(k) - BW/2)) | (freqVec > (noise_centerFreqs(k) + BW/2)),k)=0;
160end
161
162payload            = ifft(fftshift(payload_freq));
163txData             = [preamble;payload];
164
165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166% Transmit and receive signal using WARPLab
167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168
169wl_basebandCmd(node_tx1, ifc_ids_4RF.RF_ALL_VEC, 'write_IQ', txData(:,1:4));  % First 4 columns of txData is for primary tx
170wl_basebandCmd(node_tx2, ifc_ids_4RF.RF_ALL_VEC, 'write_IQ', txData(:,5:8));  % Second 4 columns of txData is for secondary tx
171
172wl_basebandCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_buff_en');
173wl_basebandCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_buff_en');
174
175wl_interfaceCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_en');
176wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'rx_en');
177
178
179set(gcf, 'KeyPressFcn','RUN_CONTINOUSLY=0;');
180fprintf('Press any key to halt experiment\n')
181
182while(1)
183    eth_trig.send();
184
185    rx_IQ = wl_basebandCmd(node_rx, ifc_ids_2RF.RF_ALL_VEC, 'read_IQ', 0, txLength);
186
187    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188    % Visualize results
189    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
190    t = [0:Ts:(txLength-1)*Ts].';
191    figure(1);
192    ax(1) = subplot(2,2,1);
193    plot(t,real(rx_IQ(:,1)))
194    title('Re\{rx\_IQ_{RFA}\}')
195    xlabel('Time (s)')
196    axis([0, max(t),-1,1])
197    ax(2) = subplot(2,2,2);
198    plot(t,real(rx_IQ(:,2)))
199    title('Re\{rx\_IQ_{RFB}\}')
200    xlabel('Time (s)')
201    %linkaxes(ax,'x')
202    axis([0, max(t),-1,1])
203
204    FFTSIZE = 1024;
205
206    ax(1) = subplot(2,2,3);
207    rx_IQ_slice = rx_IQ(2049:end,1);
208    rx_IQ_rs = reshape(rx_IQ_slice,FFTSIZE,length(rx_IQ_slice)/FFTSIZE);
209    f = linspace(-20,20,FFTSIZE);
210    fft_mag = abs(fftshift(fft(rx_IQ_rs)));
211    plot(f,20*log10(mean(fft_mag,2)))
212    title('FFT Magnitude of rx\_IQ_{RFA}')
213    xlabel('Frequency (MHz)')
214    axis([-20, 20,-20,40])
215   
216    ax(2) = subplot(2,2,4);
217    rx_IQ_slice = rx_IQ(2049:end,2);
218    rx_IQ_rs = reshape(rx_IQ_slice,FFTSIZE,length(rx_IQ_slice)/FFTSIZE);
219    f = linspace(-20,20,FFTSIZE);
220    fft_mag = abs(fftshift(fft(rx_IQ_rs)));
221    plot(f,20*log10(mean(fft_mag,2)))
222    title('FFT Magnitude of rx\_IQ_{RFB}')
223    xlabel('Frequency (MHz)')
224    %linkaxes(ax,'x')
225    axis([-20, 20,-20,40])
226   
227
228    drawnow
229
230    if (~RUN_CONTINOUSLY)
231       break 
232    end
233
234end
235
236% Disable the TX / RX on all nodes
237wl_basebandCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_rx_buff_dis');
238wl_basebandCmd(node_rx, ifc_ids_2RF.RF_ALL, 'tx_rx_buff_dis');
239
240wl_interfaceCmd([node_tx1, node_tx2], ifc_ids_4RF.RF_ALL, 'tx_rx_dis');
241wl_interfaceCmd(node_rx, ifc_ids_2RF.RF_ALL, 'tx_rx_dis');
242
243
Note: See TracBrowser for help on using the repository browser.