| 55 | |
| 56 | == WiFi Packet Generation == |
| 57 | \\ |
| 58 | {{{#!matlab |
| 59 | % Ryan Davis |
| 60 | |
| 61 | PAYLOAD = 1500; % bytes |
| 62 | PATH = ""; |
| 63 | |
| 64 | for i = 0:7 |
| 65 | filename = "WiFi_802.11n_" + i + "MCS_int16.dat"; |
| 66 | ht = wlanHTConfig("MCS", i, "ChannelBandwidth", "CBW20"); |
| 67 | |
| 68 | payload = randi([0 1], [1 PAYLOAD*8]); |
| 69 | txSig = wlanWaveformGenerator(payload,ht); |
| 70 | |
| 71 | output_txSig = formatOutput(txSig); |
| 72 | |
| 73 | fid = fopen(PATH + filename, "w"); |
| 74 | fwrite(fid, output_txSig, "int16"); |
| 75 | fclose(fid); |
| 76 | end |
| 77 | clear; |
| 78 | |
| 79 | function arr = formatOutput(txSig) |
| 80 | arr = zeros(size(txSig)*2); |
| 81 | j = 1; |
| 82 | for i = 1:size(txSig) |
| 83 | arr(j) = cast(real(txSig(i)), "int16"); |
| 84 | arr(j+1) = cast(imag(txSig(i)), "int16"); |
| 85 | j=j+2; |
| 86 | end |
| 87 | end |
| 88 | }}} |
| 89 | == Experiment Automation == |
| 90 | \\ |
| 91 | {{{#!ruby |
| 92 | # Ryan Davis |
| 93 | # Adapted from code by Ivan Seskar |
| 94 | |
| 95 | Experiment.name = "Artificial_WiFi" |
| 96 | Experiment.project = "Artificial_WiFi" |
| 97 | |
| 98 | consoleExec("omf tell -t all -a offh") |
| 99 | consoleExec("omf load -i usrpcal_2020-02-24.ndz -t node3-2,node3-19,node8-7,node8-14,node13-7,node13-14,node18-2,node18-19,node3-1,node3-20,node18-1,node18-20 -r 0") |
| 100 | consoleExec("omf tell -t node3-2,node3-19,node8-7,node8-14,node13-7,node13-14,node18-2,node18-19,node3-1,node3-20,node18-1,node18-20 -a on") |
| 101 | |
| 102 | freqs = ["2412e6", "2437e6", "2462e6", "5180e6", "5240e6", "5745e6", "5825e6"] |
| 103 | mcss = ["0", "1", "2", "3", "4", "5", "6", "7"] |
| 104 | |
| 105 | topos = {"3" => [["node18-1", "node18-2"], ["node3-1", "node3-2"], ["node18-19", "node18-20"], ["node3-19", "node3-20"]], # format: dist => [["txnode_A", "rxnode_A"], ["txnode_B", "rxnode_B"] ... ] |
| 106 | "15" => [["node13-7", "node8-7"], ["node13-14","node8-14"]], |
| 107 | "45" => [["node18-1", "node3-1"], ["node18-2", "node3-2"], ["node18-19", "node3-19"], ["node18-20", "node3-20"]], |
| 108 | "72" => [["node18-20", "node3-1"], ["node18-1", "node3-20"]] } |
| 109 | |
| 110 | defApplication('tx', 'tx_samples_from_file') { |a| |
| 111 | a.version(1, 0, 0) |
| 112 | a.shortDescription = "" |
| 113 | a.description = "" |
| 114 | a.path = "export LC_ALL=C;/usr/local/lib/uhd/examples/tx_samples_from_file" |
| 115 | a.defProperty('freq', "center frequency in Hz", '--freq', |
| 116 | {:dynamic => false, :type => :string}) |
| 117 | a.defProperty('ant', "antenna to be used", '--subdev', |
| 118 | {:dynamic => false, :type => :string}) |
| 119 | a.defProperty('rate', "baseband rate in Hz", '--rate', |
| 120 | {:dynamic => false, :type => :string}) |
| 121 | a.defProperty('gain', "receiver gain in dB", '--gain', |
| 122 | {:dynamic => false, :type => :string}) |
| 123 | a.defProperty('file', "reveived baseband waveform file name", '--file', |
| 124 | {:dynamic => false, :type => :string}) |
| 125 | a.defProperty('type', "sample types", '--type', |
| 126 | {:dynamic => false, :type => :string}) |
| 127 | a.defProperty('repeat', "continuously repeat", '--repeat', |
| 128 | {:dynamic => false, :type => :string}) |
| 129 | } |
| 130 | |
| 131 | defApplication('rx', 'rx_samples_to_file') { |a| |
| 132 | a.version(1, 0, 0) |
| 133 | a.shortDescription = "" |
| 134 | a.description = "" |
| 135 | a.path = "export LC_ALL=C;/usr/local/lib/uhd/examples/rx_samples_to_file" |
| 136 | a.defProperty('freq', "center frequency in Hz", '--freq', |
| 137 | {:dynamic => false, :type => :string}) |
| 138 | a.defProperty('rate', "baseband rate in Hz", '--rate', |
| 139 | {:dynamic => false, :type => :string}) |
| 140 | a.defProperty('gain', "receiver gain in dB", '--gain', |
| 141 | {:dynamic => false, :type => :string}) |
| 142 | a.defProperty('nsamps', "number of samples", '--nsamps', |
| 143 | {:dynamic => false, :type => :string}) |
| 144 | a.defProperty('file', "reveived baseband waveform file name", '--file', |
| 145 | {:dynamic => false, :type => :string}) |
| 146 | a.defProperty('type', "sample types", '--type', |
| 147 | {:dynamic => false, :type => :string}) |
| 148 | a.defProperty('discardtime', "time at which storing samples starts", '--discardtime', |
| 149 | {:dynamic => false, :type => :string}) |
| 150 | } |
| 151 | |
| 152 | topos.each { |dist, topo| |
| 153 | topo.each { |node_pair| |
| 154 | freqs.each { |freq| |
| 155 | mcss.each { |mcs| |
| 156 | infilename = "WiFi_802.11n_"+mcs+"_int16.dat" |
| 157 | exptag = dist+"ft_"+freq+"Hz_"+mcs+"MCS_"+node_pair[0]+","+node_pair[1] |
| 158 | outfilename = "/root/rx_"+exptag+"_int16.dat" |
| 159 | info("Setting up group for experiment: " + exptag) |
| 160 | |
| 161 | rxGroup = node_pair[1]+"@"+exptag |
| 162 | txGroup = node_pair[0]+"@"+exptag |
| 163 | |
| 164 | defGroup(txGroup, node_pair[0]) { |n| |
| 165 | n.addApplication('tx') { |app| |
| 166 | app.setProperty('freq', freq) |
| 167 | app.setProperty('ant', "A:0") |
| 168 | app.setProperty('gain', "30") |
| 169 | app.setProperty('type', "short") |
| 170 | app.setProperty('file', infilename) |
| 171 | app.setProperty('rate', "20e6") |
| 172 | app.setProperty('repeat'," ") |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | defGroup(rxGroup, node_pair[1]) { |n| |
| 177 | n.addApplication('rx') { |app| |
| 178 | app.setProperty('freq',freq) |
| 179 | app.setProperty('gain', "30") |
| 180 | app.setProperty('type',"short") |
| 181 | app.setProperty('nsamps',"40000000") |
| 182 | app.setProperty('file',outfilename) |
| 183 | app.setProperty('rate',"40e6") |
| 184 | } |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | trap("INT") { |
| 191 | allGroups.stopApplications |
| 192 | allGroups.exec("/usr/bin/pkill -9 -f rx_samples") |
| 193 | allGroups.exec("/usr/bin/pkill -9 -f tx_samples") |
| 194 | exit! |
| 195 | } |
| 196 | |
| 197 | onEvent(:ALL_UP_AND_INSTALLED) { |event| |
| 198 | # Wait for nodes to associate and give it an extra 5 sec just in case... |
| 199 | sleep 5 |
| 200 | |
| 201 | # scp IQ binary file to transmitters |
| 202 | txfiles = "txfiles/WiFi*" |
| 203 | topos.each { |dist, topo| |
| 204 | topo.each { |node_pair| |
| 205 | consoleExec("ssh root@" + node_pair[0] + " rm -f /root/*.dat") |
| 206 | consoleExec("ssh root@" + node_pair[1] + " rm -f /root/*.dat") |
| 207 | |
| 208 | consoleExec("scp -o StrictHostKeyChecking=no " + txfiles + " root@"+node_pair[0]+":"); |
| 209 | consoleExec("scp -o StrictHostKeyChecking=no test.sh root@"+node_pair[0]+":"); # TODO temp for debugging |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | topos.each { |dist, topo| |
| 214 | topo.each { |node_pair| |
| 215 | freqs.each { |freq| |
| 216 | mcss.each { |mcs| |
| 217 | exptag = dist+"ft_"+freq+"Hz_"+mcs+"MCS_"+node_pair[0]+","+node_pair[1] |
| 218 | info ("\nStarting experiment: " + exptag) |
| 219 | rxGroup = node_pair[1]+"@"+exptag |
| 220 | txGroup = node_pair[0]+"@"+exptag |
| 221 | |
| 222 | group(rxGroup).startApplications # start receiver (captures for 1 sec) |
| 223 | sleep 1 # make sure we do not start transmitting before receiving |
| 224 | group(txGroup).startApplications # start transmitter |
| 225 | |
| 226 | sleep 5 # wait for applications to hopefully finish |
| 227 | |
| 228 | group(txGroup).stopApplications |
| 229 | group(rxGroup).stopApplications |
| 230 | |
| 231 | outfilename = "/root/rx_"+exptag+"_int16.dat" |
| 232 | consoleExec("scp -o StrictHostKeyChecking=no root@" + node_pair[1] + ":" + outfilename + " /spare/spectrum/Artificial_WiFi/") #copy recved data to archive |
| 233 | consoleExec("ssh root@" + node_pair[1] + " rm -f " +outfilename) |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | allGroups.stopApplications |
| 240 | Experiment.done |
| 241 | } |
| 242 | }}} |
| 243 | |