| 3 | Here is an example of a Quick and Dirty Radio (QDR) to transfer low data rate packets over the air using USRPs. For simplicity this QDR does not utilize any form of correction techniques or feedback for packet retransmission. |
| 4 | |
| 5 | We'll use two nodes on the grid: node14-7 as the transmitter and node1-20 as the receiver. Load the nodes with 'baseline-sdr-uhd-003.009.003.ndz'. |
| 6 | |
| 7 | Two applications are being utilized: |
| 8 | 1) rf_hw_intf - configures radio, sets frequency channel, samples rate, gain, reads / writes samples to / from radio front end to circular buffer. |
| 9 | 2) qdr - the sample processing application accesses circular buffer for processing sample data to / from packets. |
| 10 | |
| 11 | |
| 12 | === Part 1: Run the applications for file transfer === |
| 13 | On node1-20, run the following commands to start the receiving process. |
| 14 | |
| 15 | node1-20> taskset 0x1 (rf_hw_intf --freq 950e6 --gain 0 --rx-only &) |
| 16 | |
| 17 | node1-20> taskset 0x2 qdr --func rx --ftp-data file |
| 18 | |
| 19 | {{{ |
| 20 | linux; GNU C++ version 4.8.4; Boost_105400; UHD_003.009.004-0-unknown |
| 21 | |
| 22 | Creating the usrp device with: addr=192.168.10.2... |
| 23 | -- Opening a USRP2/N-Series device... |
| 24 | -- Current recv frame size: 1472 bytes |
| 25 | -- Current send frame size: 1472 bytes |
| 26 | Using Device: Single USRP: |
| 27 | Device: USRP2 / N-Series Device |
| 28 | Mboard 0: N210r4 |
| 29 | RX Channel: 0 |
| 30 | RX DSP: 0 |
| 31 | RX Dboard: A |
| 32 | RX Subdev: SBXv3 RX |
| 33 | TX Channel: 0 |
| 34 | TX DSP: 0 |
| 35 | TX Dboard: A |
| 36 | TX Subdev: SBXv3 TX |
| 37 | |
| 38 | Setting RX Rate: 5.000000 Msps... |
| 39 | Actual RX Rate: 5.000000 Msps... |
| 40 | |
| 41 | Setting RX Freq: 950.000000 MHz... |
| 42 | Actual RX Freq: 950.000000 MHz... |
| 43 | |
| 44 | Setting RX Gain: 0.000000 dB... |
| 45 | Actual RX Gain: 0.000000 dB... |
| 46 | |
| 47 | waiting for ready signal... |
| 48 | Checking RX: LO: locked ... |
| 49 | Setting TX Rate: 5.000000 Msps... |
| 50 | Actual TX Rate: 5.000000 Msps... |
| 51 | |
| 52 | Setting TX Freq: 950.000000 MHz... |
| 53 | Actual TX Freq: 950.000000 MHz... |
| 54 | |
| 55 | Setting TX Gain: 0.000000 dB... |
| 56 | Actual TX Gain: 0.000000 dB... |
| 57 | |
| 58 | Checking TX: LO: locked ... |
| 59 | Recv proc started... |
| 60 | |
| 61 | Preamble: 1 |
| 62 | Feedback: 0 |
| 63 | Return Acks: 0 |
| 64 | FEC: 0 |
| 65 | BC: 0 CC: 0 TC: 0 |
| 66 | Fast Walsh: 0 |
| 67 | Interleave: 0 |
| 68 | waiting for ready signal... |
| 69 | SPB(SHM) = 256 |
| 70 | [3175.03] 0 0 |
| 71 | nf - - - - - - - - - - - - - - - |
| 72 | }}} |
| 73 | |
| 74 | Similarly on node14-7, start the transmitting process to send an audio file. |
| 75 | |
| 76 | node14-7> taskset 0x1 (rf_hw_intf --freq 950e6 --gain 20 --tx-only &) |
| 77 | |
| 78 | node14-7> taskset 0x2 qdr --func tx --ftp-data SimpleMinds.wav --intv 1000 |
| 79 | |
| 80 | {{{ |
| 81 | Creating the usrp device with: addr=192.168.10.2... |
| 82 | -- Opening a USRP2/N-Series device... |
| 83 | -- Current recv frame size: 1472 bytes |
| 84 | -- Current send frame size: 1472 bytes |
| 85 | Using Device: Single USRP: |
| 86 | Device: USRP2 / N-Series Device |
| 87 | Mboard 0: N210r4 |
| 88 | RX Channel: 0 |
| 89 | RX DSP: 0 |
| 90 | RX Dboard: A |
| 91 | RX Subdev: SBXv3 RX |
| 92 | TX Channel: 0 |
| 93 | TX DSP: 0 |
| 94 | TX Dboard: A |
| 95 | TX Subdev: SBXv3 TX |
| 96 | |
| 97 | Setting RX Rate: 5.000000 Msps... |
| 98 | Actual RX Rate: 5.000000 Msps... |
| 99 | |
| 100 | Setting RX Freq: 950.000000 MHz... |
| 101 | Actual RX Freq: 950.000000 MHz... |
| 102 | |
| 103 | Setting RX Gain: 20.000000 dB... |
| 104 | Actual RX Gain: 20.000000 dB... |
| 105 | |
| 106 | Checking RX: LO: locked ... |
| 107 | Setting TX Rate: 5.000000 Msps... |
| 108 | Actual TX Rate: 5.000000 Msps... |
| 109 | |
| 110 | Setting TX Freq: 950.000000 MHz... |
| 111 | Actual TX Freq: 950.000000 MHz... |
| 112 | |
| 113 | Setting TX Gain: 20.000000 dB... |
| 114 | Actual TX Gain: 20.000000 dB... |
| 115 | |
| 116 | Checking TX: LO: locked ... |
| 117 | Xmit proc started... |
| 118 | UDP receive proc started |
| 119 | Receiver ready on port: 1339 |
| 120 | L |
| 121 | |
| 122 | Preamble: 1 |
| 123 | Feedback: 0 |
| 124 | Return Acks: 0 |
| 125 | FEC: 0 |
| 126 | BC: 0 CC: 0 TC: 0 |
| 127 | Fast Walsh: 0 |
| 128 | Interleave: 0 |
| 129 | SPB(SHM) = 256 |
| 130 | root@node14-7:~/RTX_LOOPBACK# |
| 131 | }}} |
| 132 | |
| 133 | While the file is being received, verify that the file size is incrementing. The receiving file name should be the original file name (from the transmitter side) prefixed with "rx_". So look for the file name 'rx_SimpleMinds.wav' |
| 134 | |
| 135 | Since the file is a .wav audio format we should able to listen to the file as it is downloaded. Start a simple http file server on the receiving node (tunneling is required) |
| 136 | |
| 137 | node1-20> python -m SimpleHTTPServer 7000 |
| 138 | |
| 139 | Use Chrome to access the server and click on the .wav file being received for playback. |
| 140 | |
| 141 | Once the transfer is complete, compare the file checksum. |
| 142 | |
| 143 | node14-7> sum SimpleMinds.wav |
| 144 | 03167 10205 |
| 145 | |
| 146 | node1-20> sum rx_SimpleMinds.wav |
| 147 | 03167 10205 |
| 148 | |
| 149 | If the check sums are different then at least some packets were demodulated incorrectly. The incorrect packets will result in distortion in the audio playback. |
| 150 | |
| 151 | === Part 2: View signal before demodulation === |
| 152 | Let's slow down the transfer process and look at the signals as they are being received. In order for packet demodulation, the receiver must know where the signal starts. The signal detection starts with the detection of a known sequence of patterns; in this case it is a dual tone signal. On possible detection a simple FFT based correlation is performed to find a start offset. |
| 153 | The sample processing application can send a few buffers to octave for viewing pleasure, debugging or verification. |
| 154 | |
| 155 | Demodulation is carried on from this offset to convert the signal into formatted packets. |
| 156 | |
| 157 | Rerun the qdr application for raw data processing: |
| 158 | node1-20> qdr --func rx --pdu-data --port 1337 --addr 10.10.0.10 |
| 159 | node14-7> qdr --func tx --pdu-data --intv 2000000 |
| 160 | |
| 161 | From the grid console, run the script below to view signaling: |
| 162 | {{{ |
| 163 | if (exist("rcv_sck","var") == 0) |
| 164 | rcv_port = 1337; |
| 165 | rcv_sck = fUDP_open_rx(rcv_port); |
| 166 | printf("Recv UDP pkts on port %i\n", rcv_port) |
| 167 | endif |
| 168 | |
| 169 | |
| 170 | while(1), |
| 171 | [recv_data, recv_count]=recv(rcv_sck,4000,MSG_WAITALL); y1 = typecast(uint8(recv_data), 'single complex'); |
| 172 | sleep(0.1) |
| 173 | [recv_data, recv_count]=recv(rcv_sck,4000,MSG_DONTWAIT); y2 = typecast(uint8(recv_data), 'single complex'); |
| 174 | sleep(0.1) |
| 175 | [recv_data, recv_count]=recv(rcv_sck,4000,MSG_DONTWAIT); y3 = typecast(uint8(recv_data), 'single complex'); |
| 176 | sleep(0.1) |
| 177 | [recv_data, recv_count]=recv(rcv_sck,4000,MSG_DONTWAIT); y4 = typecast(uint8(recv_data), 'single complex'); |
| 178 | sleep(0.1) |
| 179 | |
| 180 | S1 = fft(y1); |
| 181 | S2 = fft(y2); |
| 182 | S3 = fft(y3); |
| 183 | S4 = fft(y4); |
| 184 | plot( [abs(S1) abs(S2) abs(S3) abs(S4)] ) |
| 185 | endwhile |
| 186 | }}} |
| 187 | |
| 188 | |
| 189 | === Part 3: Select receiver by preamble === |