[2028] | 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 2 | % wl_example_siso_txrx_energyTrigger.m |
---|
| 3 | % |
---|
[4689] | 4 | % This example demonstrates energy trigger feature of WARP nodes. It sends |
---|
| 5 | % a waveform consisting of a simple sinusoidal payload. The trigger manager |
---|
| 6 | % uses the energy detector to trigger the receiving node instead of using an |
---|
| 7 | % Ethernet trigger. |
---|
[2028] | 8 | % |
---|
[4689] | 9 | % NOTE: It is a straight forward extension to use the automatic gain controller |
---|
| 10 | % with this example. |
---|
| 11 | % |
---|
| 12 | % Requirements: |
---|
| 13 | % 2 WARP nodes (same hardware generation); 1 RF interface each |
---|
| 14 | % WARPLab 7.6.0 and higher |
---|
| 15 | % |
---|
[2028] | 16 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4349] | 17 | |
---|
[4689] | 18 | clear; |
---|
| 19 | |
---|
[2028] | 20 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4689] | 21 | % Top Level Control Variables |
---|
[2028] | 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4485] | 23 | |
---|
[4689] | 24 | % Parameters for the energy trigger |
---|
| 25 | rssi_sum_len = 15; |
---|
| 26 | energy_detection_threshold = rssi_sum_len * 200; |
---|
| 27 | busy_minlength = 10; |
---|
[2028] | 28 | |
---|
[4984] | 29 | % Rx Gain |
---|
| 30 | rx_gain_rf = 1; % Value must be an integer in [1:3] |
---|
| 31 | rx_gain_bb = 15; % Value must be an integer in [0:31] |
---|
[4485] | 32 | |
---|
[4984] | 33 | % Tx Gain |
---|
| 34 | tx_gain_bb = 3; % Value must be an integer in [0:3] |
---|
| 35 | tx_gain_rf = 30; % Value must be an integer in [0:63] |
---|
[2028] | 36 | |
---|
[4689] | 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 38 | % Set up the WARPLab experiment |
---|
| 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4485] | 40 | |
---|
[4689] | 41 | % Create a vector of node objects |
---|
| 42 | nodes = wl_initNodes(2); |
---|
[4485] | 43 | |
---|
[4689] | 44 | % Set up transmit and receive nodes |
---|
| 45 | % Transmit from nodes(1) to nodes(2) |
---|
| 46 | node_tx = nodes(1); |
---|
| 47 | node_rx = nodes(2); |
---|
[2028] | 48 | |
---|
[4349] | 49 | |
---|
[4689] | 50 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 51 | % Set up Trigger Manager |
---|
| 52 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 53 | |
---|
| 54 | % Create a UDP broadcast trigger and tell each node to be ready for it |
---|
[2028] | 55 | eth_trig = wl_trigger_eth_udp_broadcast; |
---|
[4689] | 56 | wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', [eth_trig]); |
---|
[2028] | 57 | |
---|
[4373] | 58 | % Read Trigger IDs into workspace |
---|
[4689] | 59 | trig_in_ids = wl_getTriggerInputIDs(nodes(1)); |
---|
| 60 | trig_out_ids = wl_getTriggerOutputIDs(nodes(1)); |
---|
[2028] | 61 | |
---|
[4689] | 62 | % For the transmit node, we will allow Ethernet to trigger the baseband buffers |
---|
| 63 | wl_triggerManagerCmd(node_tx, 'output_config_input_selection', [trig_out_ids.BASEBAND], [trig_in_ids.ETH_A]); |
---|
[2028] | 64 | |
---|
[4689] | 65 | % For the receive node, we will allow the energy detector to trigger the baseband buffers |
---|
| 66 | wl_triggerManagerCmd(node_rx, 'output_config_input_selection', [trig_out_ids.BASEBAND], [trig_in_ids.ENERGY_DET]); |
---|
| 67 | % wl_triggerManagerCmd(node_rx, 'output_config_input_selection', [trig_out_ids.BASEBAND, trig_out_ids.AGC], [trig_in_ids.ENERGY_DET]); |
---|
[2028] | 68 | |
---|
[4385] | 69 | % Set the trigger output delays. |
---|
[4485] | 70 | % |
---|
| 71 | % NOTE: We are waiting 3000 ns before starting the AGC so that there is time for the inputs |
---|
[4689] | 72 | % to settle before sampling the waveform to calculate the RX gains. |
---|
| 73 | % |
---|
| 74 | % wl_triggerManagerCmd(node_rx, 'output_config_delay', [trig_out_ids.AGC], 3000); % 3000 ns delay before starting the AGC |
---|
[4385] | 75 | |
---|
[4689] | 76 | % Enable the hold mode for the triggers driven by energy detection. |
---|
| 77 | % |
---|
| 78 | % NOTE: This will prevent the buffer from being overwritten before we have a chance to read it. |
---|
| 79 | % |
---|
[4984] | 80 | wl_triggerManagerCmd(node_rx, 'output_config_hold_mode', [trig_out_ids.BASEBAND], true); |
---|
| 81 | % wl_triggerManagerCmd(node_rx, 'output_config_hold_mode', [trig_out_ids.BASEBAND, trig_out_ids.AGC], true); |
---|
[2028] | 82 | |
---|
[4689] | 83 | % Set parameters for the energy trigger |
---|
| 84 | wl_triggerManagerCmd(node_rx, 'energy_config_average_length', rssi_sum_len); |
---|
| 85 | wl_triggerManagerCmd(node_rx, 'energy_config_busy_threshold', energy_detection_threshold); |
---|
| 86 | wl_triggerManagerCmd(node_rx, 'energy_config_busy_minlength', busy_minlength); |
---|
[2028] | 87 | |
---|
[4349] | 88 | |
---|
[4689] | 89 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 90 | % Set up the Interface parameters |
---|
| 91 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[2028] | 92 | |
---|
[4689] | 93 | % Get IDs for the interfaces on the boards. |
---|
| 94 | % |
---|
| 95 | % NOTE: This example assumes each board has the same interface capabilities (ie 2 RF |
---|
| 96 | % interfaces; RFA and RFB). Therefore, we only need to get the IDs from one of the boards. |
---|
| 97 | % |
---|
| 98 | ifc_ids = wl_getInterfaceIDs(nodes(1)); |
---|
[2028] | 99 | |
---|
[4689] | 100 | % Set the Transmit and Receive interfaces |
---|
| 101 | % Transmit from RFA of one node to RFA of the other node |
---|
| 102 | % |
---|
| 103 | % NOTE: Variables are used to make it easier to change interfaces. |
---|
| 104 | % |
---|
| 105 | rf_tx = ifc_ids.RF_A; % Transmit RF interface |
---|
| 106 | rf_rx = ifc_ids.RF_A; % Receive RF interface |
---|
[2028] | 107 | |
---|
[4689] | 108 | rf_rx_vec = ifc_ids.RF_A; % Vector version of transmit RF interface |
---|
| 109 | rf_tx_vec = ifc_ids.RF_A; % Vector version of receive RF interface |
---|
[4349] | 110 | |
---|
[4689] | 111 | % Set the RF center frequency on all interfaces |
---|
| 112 | % - Frequency Band : Must be 2.4 or 5, to select 2.4GHz or 5GHz channels |
---|
| 113 | % - Channel : Must be an integer in [1,11] for BAND = 2.4; [1,23] for BAND = 5 |
---|
| 114 | % |
---|
| 115 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'channel', 2.4, 11); |
---|
[4349] | 116 | |
---|
[4689] | 117 | % Set the RX gains on all interfaces |
---|
| 118 | % - Rx RF Gain : Must be an integer in [1:3] |
---|
| 119 | % - Rx Baseband Gain: Must be an integer in [0:31] |
---|
| 120 | % |
---|
| 121 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
| 122 | % |
---|
| 123 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'manual'); |
---|
[4984] | 124 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gains', rx_gain_rf, rx_gain_bb); |
---|
[4689] | 125 | % wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'automatic'); |
---|
| 126 | % wl_basebandCmd(nodes, 'agc_target', -10); |
---|
[2028] | 127 | |
---|
[4689] | 128 | % Set the TX gains on all interfaces |
---|
| 129 | % - Tx Baseband Gain: Must be an integer in [0:3] for approx [-5, -3, -1.5, 0]dB baseband gain |
---|
| 130 | % - Tx RF Gain : Must be an integer in [0:63] for approx [0:31]dB RF gain |
---|
| 131 | % |
---|
| 132 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
| 133 | % |
---|
[4984] | 134 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_gains', tx_gain_bb, tx_gain_rf); |
---|
[4373] | 135 | |
---|
[4689] | 136 | % Set interface parameters for the energy trigger |
---|
| 137 | wl_triggerManagerCmd(node_rx, 'energy_config_interface_selection', ifc_ids.RF_ON_BOARD); |
---|
| 138 | |
---|
| 139 | |
---|
| 140 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 141 | % Set up the Baseband parameters |
---|
| 142 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 143 | |
---|
| 144 | % Get the sample frequency from the board |
---|
| 145 | ts = 1 / (wl_basebandCmd(nodes(1), 'tx_buff_clk_freq')); |
---|
| 146 | ts_rx = 1 / (wl_basebandCmd(nodes(1), 'rx_buff_clk_freq')); |
---|
| 147 | ts_rssi = 1 / (wl_basebandCmd(nodes(1), 'rx_rssi_clk_freq')); |
---|
| 148 | |
---|
| 149 | % Read the maximum I/Q buffer length. |
---|
| 150 | % |
---|
| 151 | % NOTE: This example assumes that each board has the same baseband capabilities (ie both nodes are |
---|
| 152 | % the same WARP hardware version, for example WARP v3). This example also assumes that each RF |
---|
| 153 | % interface has the same baseband capabilities (ie the max number of TX samples is the same as the |
---|
| 154 | % max number of RF samples). Therefore, we only need to read the max I/Q buffer length of node_tx RFA. |
---|
| 155 | % |
---|
| 156 | maximum_buffer_len = wl_basebandCmd(node_tx, rf_tx, 'tx_buff_max_num_samples'); |
---|
| 157 | |
---|
| 158 | % Set the transmission / receptions lengths (in samples) |
---|
| 159 | % See WARPLab user guide for maximum length supported by WARP hardware |
---|
| 160 | % versions and different WARPLab versions. |
---|
| 161 | % |
---|
| 162 | tx_length = 2^15; |
---|
| 163 | rx_length = tx_length; |
---|
[5621] | 164 | rssi_length = floor(rx_length / (ts_rssi / ts_rx)); |
---|
[4689] | 165 | |
---|
| 166 | % Check the transmission length |
---|
| 167 | if (tx_length > maximum_buffer_len) |
---|
| 168 | error('Node supports max transmission length of %d samples. Requested %d samples.', maximum_buffer_len, tx_length); |
---|
| 169 | end |
---|
| 170 | |
---|
| 171 | % Set the length for the transmit and receive buffers based on the transmission length |
---|
| 172 | wl_basebandCmd(nodes, 'tx_length', tx_length); |
---|
| 173 | wl_basebandCmd(nodes, 'rx_length', rx_length); |
---|
| 174 | |
---|
| 175 | |
---|
[2028] | 176 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 177 | % Signal processing to generate transmit signal |
---|
| 178 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 179 | |
---|
[4689] | 180 | % First generate the preamble for AGC. |
---|
| 181 | % NOTE: The preamble corresponds to the short symbols from the 802.11a PHY standard |
---|
| 182 | % |
---|
| 183 | % shortSymbol_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].'; |
---|
| 184 | % shortSymbol_freq = [zeros(32,1);shortSymbol_freq;zeros(32,1)]; |
---|
| 185 | % shortSymbol_time = ifft(fftshift(shortSymbol_freq)); |
---|
| 186 | % shortSymbol_time = (shortSymbol_time(1:32).')./max(abs(shortSymbol_time)); |
---|
| 187 | % shortsyms_rep = repmat(shortSymbol_time,1,30); |
---|
| 188 | % preamble = shortsyms_rep; |
---|
| 189 | % preamble = preamble(:); |
---|
[4373] | 190 | |
---|
[4689] | 191 | t = [0:ts:((tx_length - 1))*ts].'; % Create time vector(Sample Frequency is ts (Hz)) |
---|
| 192 | % t = [0:ts:((tx_length - length(preamble) - 1))*ts].'; % Create time vector(Sample Frequency is ts (Hz)) |
---|
[2028] | 193 | |
---|
[4689] | 194 | sinusoid = 0.6 * exp(j*2*pi * 5e6 * t); % Create 5 MHz sinusoid |
---|
[2028] | 195 | |
---|
[4689] | 196 | tx_data = [sinusoid]; |
---|
| 197 | % tx_data = [preamble; sinusoid]; |
---|
[2028] | 198 | |
---|
| 199 | |
---|
| 200 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 201 | % Transmit and receive signal using WARPLab |
---|
| 202 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 203 | |
---|
[4485] | 204 | % Transmit IQ data to the TX node |
---|
[4689] | 205 | wl_basebandCmd(node_tx, rf_tx_vec, 'write_IQ', tx_data(:)); |
---|
[4485] | 206 | |
---|
| 207 | % Enabled the RF interfaces for TX / RX |
---|
[4689] | 208 | wl_interfaceCmd(node_tx, rf_tx, 'tx_en'); |
---|
| 209 | wl_interfaceCmd(node_rx, rf_rx, 'rx_en'); |
---|
[2028] | 210 | |
---|
[4485] | 211 | % Enable the buffers for TX / RX |
---|
[4689] | 212 | wl_basebandCmd(node_tx, rf_tx, 'tx_buff_en'); |
---|
| 213 | wl_basebandCmd(node_rx, rf_rx, 'rx_buff_en'); |
---|
[2028] | 214 | |
---|
[4485] | 215 | % Send the Ethernet trigger to start the TX |
---|
[2028] | 216 | eth_trig.send(); |
---|
| 217 | |
---|
[4689] | 218 | % Check that the energy trigger asserted the BASEBAND output trigger to the WARPLab buffers core. |
---|
| 219 | % NOTE: This will prevent users from reading stale IQ data in the node. |
---|
| 220 | % |
---|
| 221 | trigger_asserted = node_rx.wl_triggerManagerCmd('output_state_read', [trig_out_ids.BASEBAND]); |
---|
[2028] | 222 | |
---|
[4485] | 223 | if (trigger_asserted) |
---|
| 224 | % Read the IQ and RSSI data from the RX node |
---|
[4689] | 225 | rx_iq = wl_basebandCmd(node_rx, rf_rx_vec, 'read_IQ', 0, rx_length); |
---|
| 226 | rx_rssi = wl_basebandCmd(node_rx, rf_rx_vec, 'read_RSSI', 0, rssi_length); |
---|
[4373] | 227 | |
---|
[4485] | 228 | % Disable the buffers and RF interfaces for TX / RX |
---|
[4689] | 229 | wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis'); |
---|
| 230 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis'); |
---|
[4373] | 231 | |
---|
[4476] | 232 | % Clear the held energy detection trigger at our receiver |
---|
[4689] | 233 | wl_triggerManagerCmd(node_rx, 'output_state_clear', [trig_out_ids.BASEBAND]); |
---|
| 234 | % wl_triggerManagerCmd(node_rx, 'output_state_clear', [trig_out_ids.BASEBAND, trig_out_ids.AGC]); |
---|
[4476] | 235 | else |
---|
[5621] | 236 | % Disable the buffers and RF interfaces for TX / RX |
---|
| 237 | wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis'); |
---|
| 238 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis'); |
---|
[4984] | 239 | error('Energy Trigger did not assert. Please try lowering the energy detection threshold or changing the Tx/Rx gains.'); |
---|
[4476] | 240 | end |
---|
| 241 | |
---|
[4689] | 242 | |
---|
[2028] | 243 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 244 | % Visualize results |
---|
| 245 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 246 | |
---|
| 247 | figure(1);clf; |
---|
[4689] | 248 | |
---|
| 249 | % Plot IQ data |
---|
[2028] | 250 | ax(1) = subplot(2,2,1); |
---|
[4689] | 251 | plot(0:(length(rx_iq)-1),real(rx_iq)) |
---|
[2028] | 252 | xlabel('Sample Index') |
---|
| 253 | title('Received I') |
---|
[4689] | 254 | axis([1 rx_length -1 1]) |
---|
[2028] | 255 | |
---|
| 256 | ax(2) = subplot(2,2,2); |
---|
[4689] | 257 | plot(0:(length(rx_iq)-1),imag(rx_iq)) |
---|
[2028] | 258 | xlabel('Sample Index') |
---|
| 259 | title('Received Q') |
---|
[4689] | 260 | axis([1 rx_length -1 1]) |
---|
[2028] | 261 | |
---|
| 262 | linkaxes(ax,'xy') |
---|
| 263 | |
---|
[4689] | 264 | % Plot RSSI data |
---|
[2028] | 265 | subplot(2,1,2) |
---|
[4689] | 266 | plot(0:(length(rx_rssi)-1),rx_rssi) |
---|
[2028] | 267 | xlabel('Sample Index') |
---|
[4689] | 268 | title('Received RSSI') |
---|
| 269 | axis([0 rssi_length 0 1024]) |
---|
[4485] | 270 | |
---|
| 271 | |
---|
[4689] | 272 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 273 | % END |
---|
| 274 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|