[1915] | 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4675] | 2 | % wl_example_basic_txrx.m |
---|
[1915] | 3 | % |
---|
[4675] | 4 | % This example demonstrates basic transmission and reception of waveforms |
---|
[4678] | 5 | % between two WARP nodes. One node will transmit a simple sinusoid and the |
---|
| 6 | % other node will receive the sinusoid. |
---|
[4675] | 7 | % |
---|
[4677] | 8 | % Requirements: |
---|
| 9 | % 2 WARP nodes (same hardware generation); 2 RF interfaces each |
---|
| 10 | % |
---|
[1915] | 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4356] | 12 | |
---|
[4689] | 13 | clear; |
---|
| 14 | |
---|
[1915] | 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
[4675] | 16 | % Set up the WARPLab experiment |
---|
| 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 18 | |
---|
[4337] | 19 | % Create a vector of node objects |
---|
[4677] | 20 | nodes = wl_initNodes(2); |
---|
[1915] | 21 | |
---|
[4675] | 22 | % Set up transmit and receive nodes |
---|
[4677] | 23 | % NOTE: Transmit from nodes(1) to nodes(2) |
---|
| 24 | % |
---|
| 25 | node_tx = nodes(1); |
---|
| 26 | node_rx = nodes(2); |
---|
[4356] | 27 | |
---|
[4677] | 28 | |
---|
| 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 30 | % Set up Trigger Manager |
---|
| 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 32 | |
---|
[4337] | 33 | % Create a UDP broadcast trigger and tell each node to be ready for it |
---|
[4677] | 34 | % NOTE: This will allow us to trigger both nodes to begin transmission / reception of IQ data |
---|
| 35 | % |
---|
[2007] | 36 | eth_trig = wl_trigger_eth_udp_broadcast; |
---|
[4373] | 37 | wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', [eth_trig]); |
---|
[1915] | 38 | |
---|
[4385] | 39 | % Read Trigger IDs into workspace |
---|
[4677] | 40 | trig_in_ids = wl_getTriggerInputIDs(nodes(1)); |
---|
| 41 | trig_out_ids = wl_getTriggerOutputIDs(nodes(1)); |
---|
[4385] | 42 | |
---|
[4677] | 43 | % For both nodes, we will allow Ethernet A to trigger the baseband buffers |
---|
| 44 | wl_triggerManagerCmd(nodes, 'output_config_input_selection', [trig_out_ids.BASEBAND], [trig_in_ids.ETH_A]); |
---|
[4385] | 45 | |
---|
[4677] | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 47 | % Set up the Interface parameters |
---|
| 48 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 49 | |
---|
[4675] | 50 | % Get IDs for the interfaces on the boards. |
---|
| 51 | % |
---|
| 52 | % NOTE: This example assumes each board has the same interface capabilities (ie 2 RF |
---|
| 53 | % interfaces; RFA and RFB). Therefore, we only need to get the IDs from one of the boards. |
---|
| 54 | % |
---|
[4677] | 55 | ifc_ids = wl_getInterfaceIDs(nodes(1)); |
---|
[1915] | 56 | |
---|
[4678] | 57 | % Set the RF center frequency on all interfaces |
---|
| 58 | % - Frequency Band : Must be 2.4 or 5, to select 2.4GHz or 5GHz channels |
---|
| 59 | % - Channel : Must be an integer in [1,11] for BAND = 2.4; [1,23] for BAND = 5 |
---|
[4675] | 60 | % |
---|
[4678] | 61 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'channel', 2.4, 11); |
---|
| 62 | |
---|
| 63 | % Set the RX gains on all interfaces |
---|
| 64 | % - Rx RF Gain : Must be an integer in [1:3] |
---|
| 65 | % - Rx Baseband Gain: Must be an integer in [0:31] |
---|
| 66 | % |
---|
| 67 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
[4675] | 68 | % |
---|
[4677] | 69 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'manual'); |
---|
[4678] | 70 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gains', 1, 15); |
---|
[4677] | 71 | |
---|
[4678] | 72 | % Set the TX gains on all interfaces |
---|
| 73 | % - Tx Baseband Gain: Must be an integer in [0:3] for approx [-5, -3, -1.5, 0]dB baseband gain |
---|
| 74 | % - Tx RF Gain : Must be an integer in [0:63] for approx [0:31]dB RF gain |
---|
| 75 | % |
---|
| 76 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
| 77 | % |
---|
| 78 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_gains', 3, 30); |
---|
[4677] | 79 | |
---|
| 80 | |
---|
| 81 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 82 | % Set up the Baseband parameters |
---|
| 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 84 | |
---|
| 85 | % Get the baseband sampling frequencies from the board |
---|
| 86 | ts_tx = 1 / (wl_basebandCmd(nodes(1), 'tx_buff_clk_freq')); |
---|
| 87 | ts_rx = 1 / (wl_basebandCmd(nodes(1), 'rx_buff_clk_freq')); |
---|
| 88 | ts_rssi = 1 / (wl_basebandCmd(nodes(1), 'rx_rssi_clk_freq')); |
---|
| 89 | |
---|
[4678] | 90 | % Get the maximum I/Q buffer length |
---|
[4675] | 91 | % |
---|
| 92 | % NOTE: This example assumes that each board has the same baseband capabilities (ie both nodes are |
---|
[4677] | 93 | % the same WARP hardware version, for example WARP v3). This example also assumes that each RF |
---|
| 94 | % interface has the same baseband capabilities (ie the max number of TX samples is the same as the |
---|
[4678] | 95 | % max number of RF samples). Therefore, we only need to read the max I/Q buffer length of RF_A for |
---|
| 96 | % the transmitting node. |
---|
[4675] | 97 | % |
---|
[4678] | 98 | maximum_buffer_len = wl_basebandCmd(node_tx, ifc_ids.RF_A, 'tx_buff_max_num_samples'); |
---|
[1915] | 99 | |
---|
[4677] | 100 | % Set the transmission / receptions lengths (in samples) |
---|
[4678] | 101 | % See WARPLab user guide for maximum length supported by WARP hardware |
---|
| 102 | % versions and different WARPLab versions. |
---|
| 103 | tx_length = 2^12; |
---|
[4677] | 104 | rx_length = tx_length; |
---|
[5621] | 105 | rssi_length = floor(rx_length / (ts_rssi / ts_rx)); |
---|
[4677] | 106 | |
---|
[4678] | 107 | % Check the transmission length |
---|
| 108 | if (tx_length > maximum_buffer_len) |
---|
| 109 | error('Node supports max transmission length of %d samples. Requested %d samples.', maximum_buffer_len, tx_length); |
---|
| 110 | end |
---|
| 111 | |
---|
[4675] | 112 | % Set the length for the transmit and receive buffers based on the transmission length |
---|
[4677] | 113 | wl_basebandCmd(nodes, 'tx_length', tx_length); |
---|
| 114 | wl_basebandCmd(nodes, 'rx_length', rx_length); |
---|
[4356] | 115 | |
---|
[4675] | 116 | |
---|
| 117 | |
---|
[1915] | 118 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 119 | % Signal processing to generate transmit signal |
---|
| 120 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 121 | |
---|
[4677] | 122 | % Create the IQ data payload |
---|
| 123 | t = [0:ts_tx:((tx_length - 1) * ts_tx)].'; % Create time vector (Sample Frequency is ts_tx (Hz)) |
---|
[4675] | 124 | |
---|
[4678] | 125 | sinusoid_1 = 0.6 * exp(j*2*pi * 1e6 * t); % Create 1 MHz sinusoid |
---|
| 126 | % sinusoid_2 = 0.6 * exp(j*2*pi * 5e4 * t); % Create 50 kHz sinusoid to transmit on RF_B |
---|
[4675] | 127 | |
---|
[4678] | 128 | tx_data = [sinusoid_1]; % Create the data to transmit on RF_A |
---|
| 129 | % tx_data = [sinusoid_1, sinusoid_2]; % Create the data to transmit on both RF_A and RF_B |
---|
[4675] | 130 | |
---|
[4373] | 131 | |
---|
[1915] | 132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 133 | % Transmit and receive signal using WARPLab |
---|
| 134 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 135 | |
---|
[4479] | 136 | % Transmit IQ data to the TX node |
---|
[4678] | 137 | wl_basebandCmd(node_tx, [ifc_ids.RF_A], 'write_IQ', tx_data); |
---|
| 138 | % wl_basebandCmd(node_tx, [ifc_ids.RF_A, ifc_ids.RF_B], 'write_IQ', tx_data); % Write each sinusoid to a different interface |
---|
[4479] | 139 | |
---|
| 140 | % Enabled the RF interfaces for TX / RX |
---|
[4678] | 141 | wl_interfaceCmd(node_tx, ifc_ids.RF_A, 'tx_en'); |
---|
| 142 | wl_interfaceCmd(node_rx, ifc_ids.RF_A, 'rx_en'); |
---|
| 143 | % wl_interfaceCmd(node_tx, ifc_ids.RF_ON_BOARD, 'tx_en'); % Enable both RF_A and RF_B |
---|
| 144 | % wl_interfaceCmd(node_rx, ifc_ids.RF_ON_BOARD, 'rx_en'); % Enable both RF_A and RF_B |
---|
[1915] | 145 | |
---|
[4479] | 146 | % Enable the buffers for TX / RX |
---|
[4678] | 147 | wl_basebandCmd(node_tx, ifc_ids.RF_A, 'tx_buff_en'); |
---|
| 148 | wl_basebandCmd(node_rx, ifc_ids.RF_A, 'rx_buff_en'); |
---|
| 149 | % wl_basebandCmd(node_tx, ifc_ids.RF_ON_BOARD, 'tx_buff_en'); % Enable both RF_A and RF_B |
---|
| 150 | % wl_basebandCmd(node_rx, ifc_ids.RF_ON_BOARD, 'rx_buff_en'); % Enable both RF_A and RF_B |
---|
[1915] | 151 | |
---|
[4479] | 152 | % Send the Ethernet trigger to start the TX / RX |
---|
[2007] | 153 | eth_trig.send(); |
---|
[1915] | 154 | |
---|
[4479] | 155 | % Read the IQ and RSSI data from the RX node |
---|
[4678] | 156 | rx_iq = wl_basebandCmd(node_rx, [ifc_ids.RF_A], 'read_IQ', 0, rx_length); |
---|
| 157 | rx_rssi = wl_basebandCmd(node_rx, [ifc_ids.RF_A], 'read_RSSI', 0, rssi_length); |
---|
| 158 | % rx_iq = wl_basebandCmd(node_rx, [ifc_ids.RF_A, ifc_ids.RF_B], 'read_IQ', 0, rx_length); % Read IQ data from both RF_A and RF_B |
---|
| 159 | % rx_rssi = wl_basebandCmd(node_rx, [ifc_ids.RF_A, ifc_ids.RF_B], 'read_RSSI', 0, rssi_length); % Read RSSI data from both RF_A and RF_B |
---|
[1915] | 160 | |
---|
[4479] | 161 | % Disable the buffers and RF interfaces for TX / RX |
---|
[4678] | 162 | wl_basebandCmd(nodes, ifc_ids.RF_A, 'tx_rx_buff_dis'); |
---|
| 163 | wl_interfaceCmd(nodes, ifc_ids.RF_A, 'tx_rx_dis'); |
---|
| 164 | % wl_basebandCmd(nodes, ifc_ids.RF_ON_BOARD, 'tx_rx_buff_dis'); % Disable both RF_A and RF_B |
---|
| 165 | % wl_interfaceCmd(nodes, ifc_ids.RF_ON_BOARD, 'tx_rx_dis'); % Disable both RF_A and RF_B |
---|
[4373] | 166 | |
---|
[4675] | 167 | |
---|
| 168 | |
---|
[1915] | 169 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 170 | % Visualize results |
---|
| 171 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 172 | |
---|
| 173 | figure(1);clf; |
---|
[4675] | 174 | |
---|
| 175 | % Plot IQ Data |
---|
| 176 | % |
---|
[4678] | 177 | ax(1) = subplot(3, 2, 1); |
---|
[4677] | 178 | plot(0:(length(tx_data) - 1), real(tx_data(:, 1))) |
---|
[1915] | 179 | xlabel('Sample Index') |
---|
[4677] | 180 | title('Node 1 RFA: Transmitted I') |
---|
[4678] | 181 | axis([1 tx_length -1 1]) |
---|
[1915] | 182 | |
---|
[4678] | 183 | ax(2) = subplot(3, 2, 2); |
---|
[4677] | 184 | plot(0:(length(tx_data) - 1), imag(tx_data(:, 1))) |
---|
[1915] | 185 | xlabel('Sample Index') |
---|
[4677] | 186 | title('Node 1 RFA: Transmitted Q') |
---|
[4678] | 187 | axis([1 tx_length -1 1]) |
---|
[1915] | 188 | |
---|
[4678] | 189 | bx(1) = subplot(3, 2, 3); |
---|
[4677] | 190 | plot(0:(length(rx_iq) - 1), real(rx_iq(:, 1))) |
---|
| 191 | xlabel('Sample Index') |
---|
| 192 | title('Node 2 RFA: Received I') |
---|
[4678] | 193 | axis([1 rx_length -1 1]) |
---|
[1915] | 194 | |
---|
[4678] | 195 | bx(2) = subplot(3, 2, 4); |
---|
[4677] | 196 | plot(0:(length(rx_iq) - 1), imag(rx_iq(:, 1))) |
---|
| 197 | xlabel('Sample Index') |
---|
| 198 | title('Node 2 RFA: Received Q') |
---|
[4678] | 199 | axis([1 rx_length -1 1]) |
---|
[4675] | 200 | |
---|
[4677] | 201 | linkaxes([ax, bx], 'x') |
---|
| 202 | |
---|
| 203 | |
---|
[4675] | 204 | % Plot RSSI data |
---|
| 205 | % |
---|
[4677] | 206 | subplot(3, 1, 3) |
---|
[4678] | 207 | plot(0:(length(rx_rssi) - 1), rx_rssi(:, 1)) |
---|
[1915] | 208 | xlabel('Sample Index') |
---|
[4678] | 209 | title('Node 2 RFA: Received RSSI') |
---|
| 210 | axis([0 rssi_length 0 1024]) |
---|
[4479] | 211 | |
---|
[4675] | 212 | |
---|
[4678] | 213 | % |
---|
| 214 | % NOTE: It is left to the user to plot the IQ and RSSI data for RF_B in rx_iq(:, 2) |
---|
| 215 | % and rx_rssi(:, 2), respectively, if receiving on both RF_A and RF_B. |
---|
| 216 | % |
---|
[4677] | 217 | |
---|
[4675] | 218 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 219 | % END |
---|
| 220 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|