[4682] | 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 2 | % wl_example_continuous_tx.m |
---|
| 3 | % |
---|
| 4 | % This example demonstrates continuous transmit feature of WARP nodes. |
---|
| 5 | % |
---|
| 6 | % Requirements: |
---|
| 7 | % 2 WARP nodes (same hardware generation); 1 RF interface each |
---|
| 8 | % WARPLab 7.6.0 and higher |
---|
| 9 | % |
---|
| 10 | % |
---|
| 11 | % NOTE: This example will not work with WARPLab 7.5.x because nodes have the |
---|
| 12 | % restriction that Read IQ / Write IQ cannot occur while transmitting or |
---|
| 13 | % receiving. |
---|
| 14 | % |
---|
| 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 16 | |
---|
[4689] | 17 | clear; |
---|
| 18 | |
---|
[4682] | 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 20 | % Top Level Control Variables |
---|
| 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 22 | |
---|
| 23 | NUM_RECEPTIONS = 4; % Number of times to capture and plot the Tx waveform |
---|
| 24 | |
---|
| 25 | TX_LEN = 400; % Transmission length (in samples). |
---|
| 26 | % See documentation for 'continuous_tx' in the baseband buffers documentation for |
---|
| 27 | % more information on the restrictions on transmission length: |
---|
| 28 | % http://warpproject.org/trac/wiki/WARPLab/Reference/Baseband/Buffers#continuous_tx |
---|
| 29 | |
---|
| 30 | RX_LEN = TX_LEN * 4; % Reception length (in samples). |
---|
| 31 | % Setting this to a default of 4x the transmission length so that it is easy to see the |
---|
| 32 | % repetition of the TX waveform when using continuous tx mode. |
---|
| 33 | % |
---|
| 34 | % NOTE: Be careful to not exceed the maximum number of samples when using larger |
---|
| 35 | % transmission lengths. |
---|
| 36 | |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 40 | % Set up the WARPLab experiment |
---|
| 41 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 42 | |
---|
| 43 | % Create a vector of node objects |
---|
| 44 | nodes = wl_initNodes(2); |
---|
| 45 | |
---|
| 46 | % Set up transmit and receive nodes |
---|
| 47 | % Transmit from nodes(1) to nodes(2) |
---|
| 48 | node_tx = nodes(1); |
---|
| 49 | node_rx = nodes(2); |
---|
| 50 | |
---|
| 51 | |
---|
| 52 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 53 | % Set up Trigger Manager |
---|
| 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 55 | |
---|
| 56 | % Create a UDP broadcast trigger and tell each node to be ready for it |
---|
| 57 | eth_trig = wl_trigger_eth_udp_broadcast; |
---|
| 58 | wl_triggerManagerCmd(nodes, 'add_ethernet_trigger', [eth_trig]); |
---|
| 59 | |
---|
| 60 | % Read Trigger IDs into workspace |
---|
| 61 | trig_in_ids = wl_getTriggerInputIDs(nodes(1)); |
---|
| 62 | trig_out_ids = wl_getTriggerOutputIDs(nodes(1)); |
---|
| 63 | |
---|
| 64 | % For both nodes, we will allow Ethernet to trigger the baseband buffers |
---|
| 65 | wl_triggerManagerCmd(nodes, 'output_config_input_selection', [trig_out_ids.BASEBAND], [trig_in_ids.ETH_A]); |
---|
| 66 | |
---|
| 67 | |
---|
| 68 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 69 | % Set up the Interface parameters |
---|
| 70 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 71 | |
---|
| 72 | % Get IDs for the interfaces on the boards. |
---|
| 73 | % |
---|
| 74 | % NOTE: This example assumes each board has the same interface capabilities (ie 2 RF |
---|
| 75 | % interfaces; RFA and RFB). Therefore, we only need to get the IDs from one of the boards. |
---|
| 76 | % |
---|
| 77 | ifc_ids = wl_getInterfaceIDs(nodes(1)); |
---|
| 78 | |
---|
| 79 | % Set the Transmit and Receive interfaces |
---|
| 80 | % Transmit from RFA of one node to RFA of the other node |
---|
| 81 | % |
---|
| 82 | % NOTE: Variables are used to make it easier to change interfaces. |
---|
| 83 | % |
---|
| 84 | rf_tx = ifc_ids.RF_A; % Transmit RF interface |
---|
| 85 | rf_rx = ifc_ids.RF_A; % Receive RF interface |
---|
| 86 | rf_rx_name = 'RFA'; % RF interface string used for plots |
---|
| 87 | |
---|
[4753] | 88 | rf_tx_vec = ifc_ids.RF_A; % Vector version of transmit RF interface |
---|
| 89 | rf_rx_vec = ifc_ids.RF_A; % Vector version of receive RF interface |
---|
[4682] | 90 | |
---|
| 91 | % Set the RF center frequency on all interfaces |
---|
| 92 | % - Frequency Band : Must be 2.4 or 5, to select 2.4GHz or 5GHz channels |
---|
| 93 | % - Channel : Must be an integer in [1,11] for BAND = 2.4; [1,23] for BAND = 5 |
---|
| 94 | % |
---|
| 95 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'channel', 2.4, 11); |
---|
| 96 | |
---|
| 97 | % Set the RX gains on all interfaces |
---|
| 98 | % - Rx RF Gain : Must be an integer in [1:3] |
---|
| 99 | % - Rx Baseband Gain: Must be an integer in [0:31] |
---|
| 100 | % |
---|
| 101 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
| 102 | % |
---|
| 103 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gain_mode', 'manual'); |
---|
| 104 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'rx_gains', 1, 15); |
---|
| 105 | |
---|
| 106 | % Set the TX gains on all interfaces |
---|
| 107 | % - Tx Baseband Gain: Must be an integer in [0:3] for approx [-5, -3, -1.5, 0]dB baseband gain |
---|
| 108 | % - Tx RF Gain : Must be an integer in [0:63] for approx [0:31]dB RF gain |
---|
| 109 | % |
---|
| 110 | % NOTE: The gains may need to be modified depending on your experimental setup |
---|
| 111 | % |
---|
| 112 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_gains', 3, 30); |
---|
| 113 | |
---|
| 114 | |
---|
| 115 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 116 | % Set up the Baseband parameters |
---|
| 117 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 118 | |
---|
| 119 | % Get the sample frequency from the board |
---|
| 120 | ts = 1 / (wl_basebandCmd(nodes(1), 'tx_buff_clk_freq')); |
---|
| 121 | |
---|
| 122 | % Read the maximum I/Q buffer length. |
---|
| 123 | % |
---|
| 124 | % NOTE: This example assumes that each board has the same baseband capabilities (ie both nodes are |
---|
| 125 | % the same WARP hardware version, for example WARP v3). This example also assumes that each RF |
---|
| 126 | % interface has the same baseband capabilities (ie the max number of TX samples is the same as the |
---|
| 127 | % max number of RF samples). Therefore, we only need to read the max I/Q buffer length of node_tx RFA. |
---|
| 128 | % |
---|
| 129 | maximum_buffer_len = wl_basebandCmd(node_tx, rf_tx, 'tx_buff_max_num_samples'); |
---|
| 130 | |
---|
| 131 | % Set the transmission / receptions lengths (in samples) |
---|
| 132 | % See WARPLab user guide for maximum length supported by WARP hardware |
---|
| 133 | % versions and different WARPLab versions. |
---|
| 134 | tx_length = TX_LEN; |
---|
| 135 | rx_length = RX_LEN; |
---|
| 136 | |
---|
| 137 | % Check the transmission length |
---|
| 138 | if (tx_length > maximum_buffer_len) |
---|
| 139 | error('Node supports max transmission length of %d samples. Requested %d samples.', maximum_buffer_len, tx_length); |
---|
| 140 | end |
---|
| 141 | |
---|
| 142 | % Check the reception length |
---|
| 143 | if (rx_length > maximum_buffer_len) |
---|
| 144 | error('Node supports max transmission length of %d samples. Requested %d samples.', maximum_buffer_len, rx_length); |
---|
| 145 | end |
---|
| 146 | |
---|
| 147 | % Set the length for the transmit and receive buffers based on the transmission length |
---|
| 148 | wl_basebandCmd(nodes, 'tx_length', tx_length); |
---|
| 149 | wl_basebandCmd(nodes, 'rx_length', rx_length); |
---|
| 150 | |
---|
| 151 | |
---|
| 152 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 153 | % Signal processing to generate transmit signal |
---|
| 154 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 155 | |
---|
| 156 | % Create the payload |
---|
| 157 | t = [0:ts:((tx_length - 1) * ts)].'; % Create time vector(Sample Frequency is ts (Hz)) |
---|
| 158 | |
---|
| 159 | envelope = (((tx_length - 1) * ts) - t) ./ ((tx_length - 1) * ts); % Create a linear envelope from 1 to 0 over the sample length |
---|
| 160 | |
---|
| 161 | payload = envelope .* exp(j*2*pi * 5e6 * t); % Waveform: 1 MHz sinusoid multiplied by the envelope |
---|
| 162 | |
---|
| 163 | txData = [payload]; % Create the transmit data |
---|
| 164 | |
---|
| 165 | |
---|
| 166 | |
---|
| 167 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 168 | % Transmit and receive signal using WARPLab |
---|
| 169 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 170 | |
---|
| 171 | % Set continuous transmit mode |
---|
| 172 | % NOTE: Change this condition to 'false' to see the same example without continuous transmit mode |
---|
| 173 | % |
---|
| 174 | if (true) |
---|
| 175 | wl_basebandCmd(node_tx, 'continuous_tx', true); |
---|
| 176 | else |
---|
| 177 | wl_basebandCmd(node_tx, 'continuous_tx', false); |
---|
| 178 | end |
---|
| 179 | |
---|
| 180 | % Transmit IQ data to the TX node |
---|
| 181 | wl_basebandCmd(node_tx, rf_tx_vec, 'write_IQ', txData); |
---|
| 182 | |
---|
| 183 | % Enabled the RF interfaces for TX / RX |
---|
| 184 | wl_interfaceCmd(node_tx, rf_tx, 'tx_en'); |
---|
| 185 | wl_interfaceCmd(node_rx, rf_rx, 'rx_en'); |
---|
| 186 | |
---|
| 187 | % Enable the buffers for TX / RX |
---|
| 188 | wl_basebandCmd(node_tx, rf_tx, 'tx_buff_en'); |
---|
| 189 | wl_basebandCmd(node_rx, rf_rx, 'rx_buff_en'); |
---|
| 190 | |
---|
| 191 | % Send the Ethernet trigger to start the TX / RX |
---|
| 192 | eth_trig.send(); |
---|
| 193 | |
---|
| 194 | % Get the waveform NUM_RECEPTIONS times |
---|
| 195 | for ii = 1:NUM_RECEPTIONS |
---|
| 196 | % Read the IQ data from the RX node |
---|
| 197 | rx_iq(:, ii) = wl_basebandCmd(node_rx, rf_rx_vec, 'read_IQ', 0, rx_length); |
---|
| 198 | |
---|
| 199 | % Send the Ethernet trigger to re-start the RX |
---|
| 200 | eth_trig.send(); |
---|
| 201 | |
---|
| 202 | % Pause for a moment to let the node continue to transmit |
---|
| 203 | pause(0.11); |
---|
| 204 | end |
---|
| 205 | |
---|
| 206 | % Disable the buffers and RF interfaces for TX / RX |
---|
| 207 | wl_basebandCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_buff_dis'); |
---|
| 208 | wl_interfaceCmd(nodes, ifc_ids.RF_ALL, 'tx_rx_dis'); |
---|
| 209 | |
---|
| 210 | |
---|
| 211 | |
---|
| 212 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 213 | % Visualize results |
---|
| 214 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 215 | |
---|
| 216 | % Plotting variables |
---|
| 217 | iq_range = 1; % Plots IQ values in the range: [-iq_range, iq_range] |
---|
| 218 | |
---|
| 219 | |
---|
| 220 | figure(1);clf; |
---|
| 221 | |
---|
| 222 | for ii = 1:NUM_RECEPTIONS |
---|
| 223 | sprintf('Run %d', ii); |
---|
| 224 | |
---|
| 225 | % Plot IQ Data |
---|
| 226 | % |
---|
| 227 | ax(2 * ii - 1) = subplot(NUM_RECEPTIONS, 2, (2 * ii - 1)); |
---|
| 228 | plot(0:(length(rx_iq) - 1), real(rx_iq(:, ii))) |
---|
| 229 | xlabel('Sample Index') |
---|
| 230 | title(sprintf('Run %d - %s: Received I', ii, rf_rx_name)) |
---|
| 231 | axis([1 rx_length -iq_range iq_range]) |
---|
[4700] | 232 | grid on |
---|
[4682] | 233 | |
---|
| 234 | ax(2 * ii) = subplot(NUM_RECEPTIONS, 2, (2 * ii)); |
---|
| 235 | plot(0:(length(rx_iq) - 1), imag(rx_iq(:, ii))) |
---|
| 236 | xlabel('Sample Index') |
---|
| 237 | title(sprintf('Run %d - %s: Received Q', ii, rf_rx_name)) |
---|
| 238 | axis([1 rx_length -iq_range iq_range]) |
---|
[4700] | 239 | grid on |
---|
[4682] | 240 | end |
---|
| 241 | |
---|
| 242 | |
---|
| 243 | |
---|
| 244 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 245 | % END |
---|
| 246 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|