1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
2 | % The MIMO LTE Uplink simulation based on Warplab |
---|
3 | % Composed by: Guohui Wang, Bei Yin, Michael Wu |
---|
4 | % Date: October 2009 |
---|
5 | % Configuration: 2x2 MIMO |
---|
6 | % 16QAM |
---|
7 | % Zero forcing/MMSE equalizer |
---|
8 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
9 | |
---|
10 | function [block_out] = demo_transmit_1user_mimo(block_in) |
---|
11 | % function descriiption: this function simulates the transmition of |
---|
12 | % LTE uplink, 2x2 MIMO, 16QAM modulation (configurable), ZF and MMSE |
---|
13 | % equalizer can be selected. |
---|
14 | |
---|
15 | num = 1; |
---|
16 | EbNo = 10000; |
---|
17 | sigma = 1/(10^(EbNo/10)); |
---|
18 | n_pack_err_max = floor(50/num); |
---|
19 | n_err_max = floor(100/num); |
---|
20 | n_pack_max = floor(100/num); |
---|
21 | |
---|
22 | %% Simulation parameters |
---|
23 | dft_size = 72; |
---|
24 | idft_size = 128; |
---|
25 | nsym_CP = 160-128; |
---|
26 | add_delay = 1; |
---|
27 | debugon = 1; |
---|
28 | filteron = 0; |
---|
29 | equalization_mode = 0; |
---|
30 | |
---|
31 | %Common between Warplab and Simulation |
---|
32 | M_T = 2; % Number of TX antennas |
---|
33 | M = 16; % Size of signal constellation |
---|
34 | k = log2(M); % Number of bits per symbol |
---|
35 | nsamp = 20; % Oversampling rate or Number of samples per symbol, 40Mhz/20 = 2Mhz wide band |
---|
36 | TxLength = 2^14-1; % Length of transmission. In [0:2^14-1-TxDelay] |
---|
37 | TX_gain = 40; |
---|
38 | BB_gain = 3; |
---|
39 | TxDelay = 0; |
---|
40 | CarrierChannel = 7; % Channel in the 2.4 GHz band. In [1:14] |
---|
41 | |
---|
42 | agc_trigger_nsamp_delay = 100; % in the air, decrease this |
---|
43 | |
---|
44 | %Modulation objects |
---|
45 | h_mod = modem.qammod('M', M, 'SymbolOrder', 'Gray'); |
---|
46 | h_demod = modem.qamdemod(h_mod); |
---|
47 | |
---|
48 | % Define parameters related to the pulse shaping filter and create the |
---|
49 | % pulse shaping filter(SRRC) filter |
---|
50 | filtorder = nsamp*8; % Filter order |
---|
51 | delay = filtorder/(nsamp*2); % Group delay (# of input samples). |
---|
52 | rolloff = 0.3; % Rolloff factor of filter |
---|
53 | rrcfilter = rcosine(1,nsamp,'fir/sqrt',rolloff,delay); % Create SRRC filter |
---|
54 | |
---|
55 | % 1.1. Generate short training symbols |
---|
56 | shortSymbol_freq = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1-i 0 0 0 0 0 0 0 1-i 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0].'; |
---|
57 | % Take IFFT of preamble and create short symbols as per 802.11 standard |
---|
58 | shortSymbol_time = ifft(fftshift(shortSymbol_freq)); |
---|
59 | shortSymbol_time = shortSymbol_time(1:16).'; |
---|
60 | shortsyms_10 = repmat(shortSymbol_time,1,10); |
---|
61 | preamble_I = real(shortsyms_10); |
---|
62 | preamble_Q = imag(shortsyms_10); |
---|
63 | |
---|
64 | % Upsample by 2 so the standard preamble occupies a bandwith of +-10MHz (if |
---|
65 | % the freq content of the preamble is as in the 802.11 standard) |
---|
66 | [preamble_I_up2] = interp(preamble_I, 2);%(2.85/(10*0.0313))*interp(preamble_I, 2); |
---|
67 | [preamble_Q_up2] = interp(preamble_Q, 2);%(2.85/(10*0.0313))*interp(preamble_Q, 2); |
---|
68 | |
---|
69 | % Scale to span -1,1 range of DAC |
---|
70 | scale_ShortSyms = max([ max(abs(preamble_I_up2)), max(abs(preamble_Q_up2)) ]); |
---|
71 | [preamble_I_up2] = (1/scale_ShortSyms)*preamble_I_up2; |
---|
72 | [preamble_Q_up2] = (1/scale_ShortSyms)*preamble_Q_up2; |
---|
73 | |
---|
74 | % Added division by sqrt(2) for unit power Tx: (normalized by sqrt(Num_Tx)) |
---|
75 | ShortTrainingSyms_up2 = (preamble_I_up2 + sqrt(-1)*preamble_Q_up2); |
---|
76 | ShortTrainingSyms_up2_norm = ShortTrainingSyms_up2/sqrt(M_T); |
---|
77 | |
---|
78 | % 1.2. Generate preamble |
---|
79 | [LongTrainingSyms_up2,LongSymbol_time_up2,LongSymbol_time,LongSymbol_freq,scale_LongTrainingSyms] = warplab_generateLongTrainSyms; |
---|
80 | preamble_upsamp = LongTrainingSyms_up2/sqrt(M_T); |
---|
81 | % preamble_conv = LongSymbol_time_up2; |
---|
82 | nsym_preamble = length(preamble_upsamp)/nsamp; |
---|
83 | |
---|
84 | % 1.3. Generate pilot tones |
---|
85 | %pilot_tone_freq = ones(1,idft_size).*exp(sqrt(-1)*rand(1,idft_size)*pi*2); %random phase |
---|
86 | r = 5; |
---|
87 | L = 128; |
---|
88 | q = 5; |
---|
89 | pilot_tone_freq = exp(-sqrt(-1)*2*pi*r/L*((0:1:L-1).^2/2+(0:1:L-1)*q)); |
---|
90 | |
---|
91 | pilot_tone = ifft(pilot_tone_freq); |
---|
92 | pilot_CP = pilot_tone(end-nsym_CP+1:end); |
---|
93 | pilot_tone = [pilot_CP pilot_tone]; |
---|
94 | |
---|
95 | training.tx1 = pilot_tone; |
---|
96 | training.tx2 = pilot_tone; |
---|
97 | nsym_per_pilot = length(training.tx1); |
---|
98 | |
---|
99 | % 1.4. Calculate the packet parameters |
---|
100 | sym_guard = 4; |
---|
101 | nsym = floor(TxLength/nsamp-delay*2); % Number or symbols to transmit |
---|
102 | nsym_header = nsym_preamble+M_T*(nsym_per_pilot)+sym_guard; % Number of symbols in header, 2 frame for channel estimation, |
---|
103 | nsym_payload = floor(nsym-nsym_header); % Number of payload bits |
---|
104 | nframe = floor(nsym_payload/(idft_size+nsym_CP)); % Number of SCFDMA frames per packet |
---|
105 | |
---|
106 | %% Start the simulation |
---|
107 | num_errs_total.ZF = 0; |
---|
108 | num_errs_total.SD = 0; |
---|
109 | num_bits_total = 0; |
---|
110 | |
---|
111 | % for packet_cntr = 1:1e7 |
---|
112 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
113 | % Transmitting and Receiving Data using WARPLab (Virtual MIMO Downlink) |
---|
114 | % 2x2 Transmitter, 2x2 Receiver |
---|
115 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
116 | |
---|
117 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
118 | % 0. Initializaton and definition of parameters |
---|
119 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
120 | warplab_defines; |
---|
121 | % Create Socket handles and intialize nodes |
---|
122 | [socketHandles, packetNum] = warplab_initialize; |
---|
123 | |
---|
124 | % Separate the socket handles for easier access |
---|
125 | udp_Sync = socketHandles(1); %magic SYNC |
---|
126 | udp_node1 = socketHandles(2); %transmitter |
---|
127 | udp_node2 = socketHandles(3); %receiver |
---|
128 | % continuous transmission: |
---|
129 | TxMode = 0; %1 for continuous transmission |
---|
130 | warplab_writeRegister(udp_node1,TX_MODE,TxMode); |
---|
131 | |
---|
132 | % Set transmitter and receiver gains |
---|
133 | % Node 1 can transmit and receive on both antenna, 2x2 setup |
---|
134 | Node1_Radio2_TxGain_BB = BB_gain; % Tx Baseband Gain. In [0:3] |
---|
135 | Node1_Radio2_TxGain_RF = TX_gain; % Tx RF Gain. In [0:63] |
---|
136 | Node1_Radio3_TxGain_BB = BB_gain; % Tx Baseband Gain. In [0:3] |
---|
137 | Node1_Radio3_TxGain_RF = TX_gain; % Tx RF Gain. In [0:63] |
---|
138 | |
---|
139 | % Node 2 can receive on both antennas |
---|
140 | Node2_Radio2_RxGain_BB = 15; % Rx Baseband Gain. In [0:31] |
---|
141 | Node2_Radio2_RxGain_RF = 1; % Rx RF Gain. In [1:3] |
---|
142 | Node2_Radio3_RxGain_BB = 15; % Rx Baseband Gain. In [0:31] |
---|
143 | Node2_Radio3_RxGain_RF = 1; % Rx RF Gain. In [1:3] |
---|
144 | |
---|
145 | Node2_TargetdBmAGC = -6; % AGC's target dBm |
---|
146 | Node2_NoiseEstdBmAGC = -95; % AGC's Noise Estimate in dBm |
---|
147 | % Download AGC parameters to node 2 |
---|
148 | warplab_setRadioAGCParameter(udp_node2,SET_AGC_TARGET_dBm,Node2_TargetdBmAGC); |
---|
149 | warplab_setRadioAGCParameter(udp_node2,SET_AGC_NOISEEST_dBm,Node2_NoiseEstdBmAGC); |
---|
150 | warplab_setRadioAGCParameter(udp_node2,SET_AGC_TRIG_DELAY,agc_trigger_nsamp_delay); |
---|
151 | DCOffset_FPGA_Enabled = 0; |
---|
152 | warplab_setRadioAGCParameter(udp_node2,AGC_DCO_EN,DCOffset_FPGA_Enabled); |
---|
153 | |
---|
154 | warplab_writeRegister(udp_node1,TX_DELAY,TxDelay); %Node1 can transmit |
---|
155 | warplab_writeRegister(udp_node1,TX_LENGTH,TxLength); |
---|
156 | warplab_writeRegister(udp_node1,TX_MODE,TxMode); |
---|
157 | |
---|
158 | % The CarrierChannel parameter must be downloaded to all nodes |
---|
159 | warplab_setRadioParameter(udp_node1,CARRIER_CHANNEL,CarrierChannel); |
---|
160 | warplab_setRadioParameter(udp_node2,CARRIER_CHANNEL,CarrierChannel); |
---|
161 | |
---|
162 | % Node 1 will be set as the transmitter so download Tx gains to node 1; |
---|
163 | warplab_setRadioParameter(udp_node1,RADIO2_TXGAINS,(Node1_Radio2_TxGain_RF + Node1_Radio2_TxGain_BB*2^16)); |
---|
164 | warplab_setRadioParameter(udp_node1,RADIO3_TXGAINS,(Node1_Radio3_TxGain_RF + Node1_Radio3_TxGain_BB*2^16)); |
---|
165 | |
---|
166 | % Node 2 will be set as the receiver so download Rx gains to node 2. |
---|
167 | warplab_setRadioParameter(udp_node2,RADIO2_RXGAINS,(Node2_Radio2_RxGain_BB + Node2_Radio2_RxGain_RF*2^16)); |
---|
168 | warplab_setRadioParameter(udp_node2,RADIO3_RXGAINS,(Node2_Radio3_RxGain_BB + Node2_Radio3_RxGain_RF*2^16)); |
---|
169 | |
---|
170 | %-------------------------------------------------------------------------% |
---|
171 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
172 | % Time Slot 1 |
---|
173 | % Step A: Generate two vectors of samples to transmit and send the samples to |
---|
174 | % the WARP board (Sample Frequency is 40MHz) |
---|
175 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
176 | |
---|
177 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
178 | % 2. Generate a random bit stream and map it to symbols |
---|
179 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
180 | % Create a random binary data stream as a column vector. |
---|
181 | % assign input block to two streams which are transmitted by two anttennas. |
---|
182 | block_size = length(block_in); |
---|
183 | block_in = block_in'; |
---|
184 | stream1 = block_in(1:block_size/2); |
---|
185 | stream2 = block_in(block_size/2+1:end); |
---|
186 | |
---|
187 | % Map bits in vector x into k-bit symbols |
---|
188 | tx1_xsym = bi2de(reshape(stream1,k,length(stream1)/k).','left-msb'); |
---|
189 | tx2_xsym = bi2de(reshape(stream2,k,length(stream2)/k).','left-msb'); |
---|
190 | |
---|
191 | % Modulate using M-QAM |
---|
192 | tx1_mod = modulate(h_mod, tx1_xsym); |
---|
193 | tx1_mod = tx1_mod/(sqrt(M)-1); |
---|
194 | tx2_mod = modulate(h_mod, tx2_xsym); |
---|
195 | tx2_mod = tx2_mod/(sqrt(M)-1); |
---|
196 | |
---|
197 | %Take the fft |
---|
198 | tx1_mod_freq = [fft(tx1_mod(1:dft_size));fft(tx1_mod(dft_size+1:end))]; |
---|
199 | tx2_mod_freq = [fft(tx2_mod(1:dft_size));fft(tx2_mod(dft_size+1:end))]; |
---|
200 | |
---|
201 | %Pad with 0 to ifft size |
---|
202 | padding_size = 0.5*(idft_size-dft_size); |
---|
203 | padding = zeros(padding_size,1); |
---|
204 | |
---|
205 | tx1_mod_freq = [padding; tx1_mod_freq(1:dft_size); padding; padding; tx1_mod_freq(dft_size+1:end); padding ]; |
---|
206 | tx2_mod_freq = [padding; tx2_mod_freq(1:dft_size); padding; padding; tx2_mod_freq(dft_size+1:end); padding ]; |
---|
207 | |
---|
208 | %Take the ifft; |
---|
209 | tx1_mod_time = [ifft(tx1_mod_freq(1:idft_size));ifft(tx1_mod_freq(idft_size+1:end))]; |
---|
210 | tx2_mod_time = [ifft(tx2_mod_freq(1:idft_size));ifft(tx2_mod_freq(idft_size+1:end))]; |
---|
211 | |
---|
212 | %Add cyclic prefix |
---|
213 | tx1_mod_time = [tx1_mod_time(idft_size-nsym_CP+1:idft_size); tx1_mod_time(1:idft_size);tx1_mod_time(end-nsym_CP+1:end); tx1_mod_time(idft_size+1:end)]; |
---|
214 | tx2_mod_time = [tx2_mod_time(idft_size-nsym_CP+1:idft_size); tx2_mod_time(1:idft_size);tx2_mod_time(end-nsym_CP+1:end); tx2_mod_time(idft_size+1:end)]; |
---|
215 | tic |
---|
216 | |
---|
217 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
218 | % 3. Upsample the modulated symbols with the appended preamble and filter |
---|
219 | % using a pulse shaping filter |
---|
220 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
221 | ytx1_mod = [training.tx1.'; zeros(length(training.tx1),1); tx1_mod_time ]; |
---|
222 | ytx2_mod = [zeros(length(training.tx2),1); training.tx2.'; tx2_mod_time ]; |
---|
223 | |
---|
224 | ytx1_mod_filt = [ShortTrainingSyms_up2_norm.';preamble_upsamp.'; zeros(1,sym_guard*nsamp).'; rcosflt(ytx1_mod,1,nsamp,'filter',rrcfilter)]; |
---|
225 | ytx2_mod_filt = [ShortTrainingSyms_up2_norm.';preamble_upsamp.'; zeros(1,sym_guard*nsamp).'; rcosflt(ytx2_mod,1,nsamp,'filter',rrcfilter)]; |
---|
226 | |
---|
227 | |
---|
228 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
229 | % 4. Upconvert from baseband to 5MHz to avoid radio DC attenuation |
---|
230 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
231 | time = [0:1:length(ytx1_mod_filt)-1]/40e6; % Sampling Freq. is 40MHz |
---|
232 | ytx1_mod_filt_up = ytx1_mod_filt .* exp(sqrt(-1)*2*pi*5e6*time).'; |
---|
233 | ytx2_mod_filt_up = ytx2_mod_filt .* exp(sqrt(-1)*2*pi*5e6*time).'; |
---|
234 | |
---|
235 | Node1_Radio2_TxData = ytx1_mod_filt_up.'; |
---|
236 | Node1_Radio3_TxData = ytx2_mod_filt_up.'; |
---|
237 | |
---|
238 | % Download the samples to be transmitted |
---|
239 | warplab_writeSMWO(udp_node1, RADIO2_TXDATA, Node1_Radio2_TxData); % Download samples to |
---|
240 | % radio 2 Tx Buffer |
---|
241 | warplab_writeSMWO(udp_node1, RADIO3_TXDATA, Node1_Radio3_TxData); % Download samples to |
---|
242 | % radio 3 Tx Buffer |
---|
243 | %-------------------------------------------------------------------------% |
---|
244 | % |
---|
245 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
246 | % Time Slot 1 |
---|
247 | % Step B: Prepare WARP boards for transmission and reception and send trigger to |
---|
248 | % start transmission and reception (trigger is the SYNC packet) |
---|
249 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
250 | |
---|
251 | % Enable transmitter radio path in radios 2 and 3 in node 1 (enable radio 2 |
---|
252 | % and radio 3 in node 1 as transmitters) |
---|
253 | warplab_sendCmd(udp_node1, [RADIO2_TXEN, RADIO3_TXEN], packetNum); |
---|
254 | |
---|
255 | % Enable transmission of node1's radio 2 and radio 3 Tx buffer (enable |
---|
256 | % transmission of samples stored in radio 2 Tx Buffer and in radio 3 Tx |
---|
257 | % Buffer in node 1) |
---|
258 | warplab_sendCmd(udp_node1, [RADIO2TXBUFF_TXEN, RADIO3TXBUFF_TXEN], packetNum); |
---|
259 | |
---|
260 | % Enable receiver radio path in radios 2 and 3 in node 2 (enable radios 2 |
---|
261 | % and 3 in node 2 as receivers) |
---|
262 | warplab_sendCmd(udp_node2, [RADIO2_RXEN, RADIO3_RXEN], packetNum); |
---|
263 | % Enable capture in node2's radio 2 and radio 3 Rx Buffer (enable radio 2 |
---|
264 | % Rx buffer and radio 3 Rx buffer in node 2 for storage of samples) |
---|
265 | warplab_sendCmd(udp_node2, [RADIO2RXBUFF_RXEN, RADIO3RXBUFF_RXEN], packetNum); |
---|
266 | |
---|
267 | % Prime transmitter state machine in node 1. Node 1 will be |
---|
268 | % waiting for the SYNC packet. Transmission from node 1 will be triggered |
---|
269 | % when node 1 receives the SYNC packet. |
---|
270 | warplab_sendCmd(udp_node1, TX_START, packetNum); |
---|
271 | |
---|
272 | % Prime receiver state machine in node 2. Node 2 will be waiting |
---|
273 | % for the SYNC packet. Capture at node 2 will be triggered when node 2 |
---|
274 | % receives the SYNC packet. |
---|
275 | warplab_sendCmd(udp_node2, RX_START, packetNum); |
---|
276 | |
---|
277 | % Send the SYNC packet |
---|
278 | warplab_sendSync(udp_Sync); |
---|
279 | |
---|
280 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
281 | % Time Slot 1 |
---|
282 | % Step C: Receiver reads the received samples from the Warp board (on one |
---|
283 | % antenna each. |
---|
284 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
285 | % Read back the received samples from radio 2, node 2 |
---|
286 | [Node2_Radio2_RawRxData] = warplab_readSMRO(udp_node2, RADIO2_RXDATA, TxLength+TxDelay); |
---|
287 | % Read back the received samples from radio 2, node 3 |
---|
288 | [Node2_Radio3_RawRxData] = warplab_readSMRO(udp_node2, RADIO3_RXDATA, TxLength+TxDelay); |
---|
289 | %-------------------------------------------------------------------------% |
---|
290 | |
---|
291 | % Process the received samples to obtain the meaningful data |
---|
292 | [Node2_Radio2_RxData_wDCO,Node2_Radio2_RxOTR] = warplab_processRawRxData(Node2_Radio2_RawRxData); |
---|
293 | [Node2_Radio3_RxData_wDCO,Node2_Radio3_RxOTR] = warplab_processRawRxData(Node2_Radio3_RawRxData); |
---|
294 | |
---|
295 | % Read the address where the AGC fixes the gains |
---|
296 | [AGC_Set_Address] = warplab_readRegister(udp_node2,AGC_DONE_ADDR); |
---|
297 | % Read the gains that were set by the AGC |
---|
298 | [GainsRF_Init,GainsBB_Init] = warplab_readAGCGains(udp_node2); |
---|
299 | % Remove DC Offset (DCO) from RxData |
---|
300 | [Node2_Radio2_RxData] = warplab_correctDCO(Node2_Radio2_RxData_wDCO,AGC_Set_Address); |
---|
301 | [Node2_Radio3_RxData] = warplab_correctDCO(Node2_Radio3_RxData_wDCO,AGC_Set_Address); |
---|
302 | % [Node2_Radio2_RxData] = Node2_Radio2_RxData_wDCO; |
---|
303 | % [Node2_Radio3_RxData] = Node2_Radio3_RxData_wDCO; |
---|
304 | |
---|
305 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
306 | % Time Slot 1 |
---|
307 | % Step D: Reset and disable the boards |
---|
308 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
309 | |
---|
310 | % Set radios 2 and 3 Tx buffer in node 1 back to Tx disabled mode |
---|
311 | warplab_sendCmd(udp_node1, [RADIO2TXBUFF_TXDIS RADIO3TXBUFF_TXDIS], packetNum); |
---|
312 | |
---|
313 | % Disable the transmitter radios |
---|
314 | warplab_sendCmd(udp_node1, [RADIO2_TXDIS, RADIO3_TXDIS], packetNum); |
---|
315 | |
---|
316 | % Let the receiver know that samples have been read and system is ready for |
---|
317 | % a new capture |
---|
318 | warplab_sendCmd(udp_node2, RX_DONEREADING, packetNum); |
---|
319 | |
---|
320 | % Set radios 2 and 3 Rx buffer in node 2 back to Rx disabled mode |
---|
321 | warplab_sendCmd(udp_node2, [RADIO2RXBUFF_RXDIS, RADIO3RXBUFF_RXDIS], packetNum); |
---|
322 | |
---|
323 | % Disable the receiver radios |
---|
324 | warplab_sendCmd(udp_node2, [RADIO2_RXDIS,RADIO3_RXDIS], packetNum); |
---|
325 | |
---|
326 | % Reset the AGC |
---|
327 | warplab_sendCmd(udp_node2, AGC_RESET, packetNum); |
---|
328 | |
---|
329 | %Close sockets |
---|
330 | pnet('closeall'); |
---|
331 | |
---|
332 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
333 | % 6. Downconvert from 5MHz to baseband |
---|
334 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
335 | time = [0:1:length(Node2_Radio2_RxData)-1]/40e6; % Sampling Freq. is 40MHz |
---|
336 | yrx1_bb = Node2_Radio2_RxData .* exp(-sqrt(-1)*2*pi*5e6*time); %Downconvert to baseband |
---|
337 | yrx2_bb = Node2_Radio3_RxData .* exp(-sqrt(-1)*2*pi*5e6*time); %Downconvert to baseband |
---|
338 | |
---|
339 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
340 | % 7. Filter the received signal with a Matched Filter (matched to the pulse |
---|
341 | % shaping filter), detect preamble, and downsample output of Matched Filter |
---|
342 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
343 | % Store received samples as a column vector |
---|
344 | yrx1_bb = yrx1_bb.'; |
---|
345 | yrx2_bb = yrx2_bb.'; |
---|
346 | |
---|
347 | % Matched filter: Filter received signal using the SRRC filter |
---|
348 | % [LongTrainingStart_2,ValidStart_2] = |
---|
349 | % warplab_findLongTrainingStart(RxData_2,LongSymbol_time_up2,AGC_Set_Address); |
---|
350 | |
---|
351 | % Correlate with the reference matrix to find preamble sequence |
---|
352 | % AGC_Set_Address = 0; |
---|
353 | |
---|
354 | AGC_Set_Address = AGC_Set_Address + 160; |
---|
355 | % Find start of the preamble |
---|
356 | [LongTrainingStart,ValidStart_1, Corr_1] = warplab_findLongTrainingStart(yrx1_bb,LongSymbol_time_up2,AGC_Set_Address); |
---|
357 | preamble_start_1 = LongTrainingStart-1; |
---|
358 | |
---|
359 | [LongTrainingStart,ValidStart_2, Corr_2] = warplab_findLongTrainingStart(yrx2_bb,LongSymbol_time_up2,AGC_Set_Address); |
---|
360 | preamble_start_2 = LongTrainingStart-1; |
---|
361 | |
---|
362 | if (~ValidStart_1&& ~ValidStart_2) |
---|
363 | 'error' |
---|
364 | else |
---|
365 | yrx1_bb_mf = rcosflt(yrx1_bb(preamble_start_1+nsym_preamble*nsamp+sym_guard*nsamp:end),1,nsamp,'Fs/filter',rrcfilter); |
---|
366 | yrx2_bb_mf = rcosflt(yrx2_bb(preamble_start_2+nsym_preamble*nsamp+sym_guard*nsamp:end),1,nsamp,'Fs/filter',rrcfilter); |
---|
367 | |
---|
368 | %Figure out where the first index is |
---|
369 | delay = filtorder/(nsamp*2); |
---|
370 | first_sample_index = 2;% 1+2*delay*nsamp; |
---|
371 | |
---|
372 | rx1 = downsample(yrx1_bb_mf(first_sample_index:end), nsamp); |
---|
373 | rx2 = downsample(yrx2_bb_mf(first_sample_index:end), nsamp); |
---|
374 | |
---|
375 | %estimate the channel |
---|
376 | chan.h11 = chan_est(rx1(1:length(training.tx1)),pilot_tone_freq, nsym_CP); |
---|
377 | chan.h21 = chan_est(rx1(length(training.tx1)+1:2*length(training.tx1)),pilot_tone_freq, nsym_CP); |
---|
378 | |
---|
379 | chan.h12 = chan_est(rx2(1:length(training.tx1)),pilot_tone_freq, nsym_CP); |
---|
380 | chan.h22 = chan_est(rx2(length(training.tx1)+1:2*length(training.tx1)),pilot_tone_freq, nsym_CP); |
---|
381 | |
---|
382 | if (filteron) |
---|
383 | L = 3; %please be even |
---|
384 | lowpass = [0.5 2 0.5]/L; |
---|
385 | chan.h11 = conv(lowpass, chan.h11); |
---|
386 | chan.h11 = chan.h11(ceil(L/2):end-floor(L/2)); |
---|
387 | |
---|
388 | chan.h12 = conv(lowpass, chan.h12); |
---|
389 | chan.h12 = chan.h12(ceil(L/2):end-floor(L/2)); |
---|
390 | |
---|
391 | chan.h21 = conv(lowpass, chan.h21); |
---|
392 | chan.h21 = chan.h21(ceil(L/2):end-floor(L/2)); |
---|
393 | |
---|
394 | chan.h22 = conv(lowpass, chan.h22); |
---|
395 | chan.h22 = chan.h22(ceil(L/2):end-floor(L/2)); |
---|
396 | end |
---|
397 | |
---|
398 | %Grab data frames |
---|
399 | %not generalized to n frames, make the vector larger |
---|
400 | data.rx1 = zeros(1,idft_size*2); |
---|
401 | data.rx2 = zeros(1,idft_size*2); |
---|
402 | |
---|
403 | start_index = 2*length(training.tx1)+1; |
---|
404 | end_index = start_index+idft_size*2+nsym_CP*2-1; |
---|
405 | |
---|
406 | for ii = 1:1:1 %not generalized to n frames, change index |
---|
407 | [start_index end_index]; |
---|
408 | |
---|
409 | temp = rx1(start_index:end_index); %grab data; |
---|
410 | |
---|
411 | data.rx1((ii-1)*idft_size+1:(ii+1)*idft_size) = [fft(temp(nsym_CP+1:nsym_CP+idft_size));fft(temp(nsym_CP*2+1+idft_size:end))]; %remove of cyclic prefix, take FFT; |
---|
412 | |
---|
413 | temp = rx2(start_index:end_index); %grab data; |
---|
414 | data.rx2((ii-1)*idft_size+1:(ii+1)*idft_size) = [fft(temp(nsym_CP+1:nsym_CP+idft_size));fft(temp(nsym_CP*2+1+idft_size:end))]; %remove of cyclic prefix, take FFT; |
---|
415 | |
---|
416 | start_index = end_index+1; |
---|
417 | end_index = end_index+idft_size*2+nsym_CP*2; |
---|
418 | end |
---|
419 | |
---|
420 | |
---|
421 | % grab actual symbols in freq: |
---|
422 | final.rx1 = [data.rx1(padding_size+1:padding_size+dft_size),data.rx1(idft_size+padding_size+1:idft_size+padding_size+dft_size)]; |
---|
423 | final.rx2 = [data.rx2(padding_size+1:padding_size+dft_size),data.rx2(idft_size+padding_size+1:idft_size+padding_size+dft_size)]; |
---|
424 | |
---|
425 | final.h11 = [chan.h11(padding_size+1:padding_size+dft_size);chan.h11(padding_size+1:padding_size+dft_size)]; |
---|
426 | final.h21 = [chan.h21(padding_size+1:padding_size+dft_size);chan.h21(padding_size+1:padding_size+dft_size)]; |
---|
427 | final.h12 = [chan.h12(padding_size+1:padding_size+dft_size);chan.h12(padding_size+1:padding_size+dft_size)]; |
---|
428 | final.h22 = [chan.h22(padding_size+1:padding_size+dft_size);chan.h22(padding_size+1:padding_size+dft_size)]; |
---|
429 | |
---|
430 | if (equalization_mode == 0) % Zero Forcing |
---|
431 | %%%% Zero forcing equalizer; |
---|
432 | %equalize symbol by symbol |
---|
433 | x = []; |
---|
434 | for ii = 1:length(final.rx1) |
---|
435 | h = [final.h11(ii) final.h21(ii); |
---|
436 | final.h12(ii) final.h22(ii)]; |
---|
437 | y = [final.rx1(ii); final.rx2(ii)]; |
---|
438 | x = [x inv(h)*y]; |
---|
439 | end |
---|
440 | else |
---|
441 | %%%% MMSE equalizer |
---|
442 | SP.NDFT_sub = dft_size*2; |
---|
443 | RxSymbolsMimo_fd = [final.rx1;final.rx2]; |
---|
444 | for ii = 1:length(final.rx1) |
---|
445 | H_fd(:,:,ii) = [final.h11(ii),final.h21(ii);final.h12(ii),final.h22(ii)]; |
---|
446 | end |
---|
447 | sigma_n = sigma; |
---|
448 | mmse; |
---|
449 | x=RxSymbolsMimo_eq_fd; |
---|
450 | end |
---|
451 | |
---|
452 | xsym1 = [ifft(x(1,1:dft_size)),ifft(x(1,1+dft_size:end))]*(sqrt(M)-1); |
---|
453 | xsym2 = [ifft(x(2,1:dft_size)),ifft(x(2,1+dft_size:end))]*(sqrt(M)-1); |
---|
454 | |
---|
455 | %% Demodulate and calculate error |
---|
456 | z1 = demodulate(h_demod, xsym1(1,:)); |
---|
457 | z2 = demodulate(h_demod, xsym2(1,:)); |
---|
458 | |
---|
459 | z1_ZF = de2bi( z1,'left-msb',4); % Convert integers to bits. |
---|
460 | z1_ZF = reshape(z1_ZF.',prod(size(z1_ZF)),1); |
---|
461 | |
---|
462 | z2_ZF = de2bi( z2,'left-msb',4); % Convert integers to bits. |
---|
463 | z2_ZF = reshape(z2_ZF.',prod(size(z2_ZF)),1); |
---|
464 | |
---|
465 | % display the intermidea results |
---|
466 | % [number_of_errors.tx1.ZF,bit_error_rate.tx1.ZF] = biterr(stream1,z1_ZF); |
---|
467 | % [number_of_errors.tx2.ZF,bit_error_rate.tx2.ZF] = biterr(stream2,z2_ZF); |
---|
468 | % disp('ber tx1 | tx2'); |
---|
469 | % disp([bit_error_rate.tx1.ZF bit_error_rate.tx2.ZF]); |
---|
470 | % disp('err number tx1 | tx2'); |
---|
471 | % disp([number_of_errors.tx1.ZF,number_of_errors.tx2.ZF]); |
---|
472 | end |
---|
473 | |
---|
474 | % t=toc; |
---|
475 | block_out = [z1_ZF' z2_ZF']; |
---|
476 | |
---|
477 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
478 | % !!! Plot the transmitted and received data!!! |
---|
479 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
480 | % figure; |
---|
481 | % subplot(4,1,1); plot(real(Node1_Radio2_TxData)); |
---|
482 | % subplot(4,1,2); plot(real(Node2_Radio2_RxData)); |
---|