We release the basic component of 802.11+: interference nulling. To make it easy to understand the code, we stripe down the code to its most basic functionalities, including BPSK modulation, channel estimation feedback via the backend Ethernet, and offline OFDM decoding. The code has been tested to be able to work properly in Ubuntu Lucid (10.04) and Ubuntu Maverick (10.10).

.: Download :.

NOTE: There is a typo in the old version of the package. If you downloaded the package before 2011/10/13, please re-download it again. If you have already installed the package, you can download the new one, replace the file "gnuradio/usrp2/host/apps/mimo_zf_tx2.cc", and rebuild under the folder "gnuradio/usrp2/host/apps/".

To run our example, you need to install gnuradio and our module 'gr-mimo'. We made some modifications in gnuradio, so please download gnuradio from the links below.

The package includes four folders.

  • gnuradio: modified based on gnuradio version 3.3.0
  • gr-mimo: including the python decoding modules of our examples
  • matlab: including files used for offline decoding
  • source: including the files for USRP2 to read transmitted sapmles from files


.: Build :.

To run our code, you need to build and install gnuradio and gr-mimo in order.

    1. Install gnuradio $ cd gnuradio Build gnuradio based on the instructions at BuildGuide

    2. Install gr-mimo $ cd gr-mimo
      $ ./bootstrap
      $ ./configure
      $ make
      $ make check
      $ sudo make install


.: Burn Firmware and FPGA :.

To connect USRP2 to an external clock, you need to change the firmware and FPGA code on the SD Card

    1. Insert the SD card into the card reader
    2. Use "dmesg" command to check which interface is in use. The following is an example output in my machine, where the SC card is installed in /dev/sdc
    3. $ dmesg
      sd 4:0:0:1: [sdc] 3878912 512-byte logical blocks: (1.98 GB/1.84 GiB)
      sd 4:0:0:1: [sdc] Assuming drive cache: write through
      sd 4:0:0:1: [sdc] Assuming drive cache: write through
      sdc: unknown partition table
    4. Run $ cd gnuratio/usrp2/firmware/
      $ sudo ./u2_flash_tool --dev=/dev/XXXX -t s/w txrx.bin -w
      $ sudo ./u2_flash_tool --dev=/dev/XXXX -t fpga u2_rev3-20100603.bin -w
      Be careful: /dev/XXXX has to be replaced with the device for the SD card reader.
    5. Insert the SD card to USRP2 and reboot USRP2. If your SD card is upgraded successfully, you should see all 6 LEDs flash, and LED 'D' and 'F' will remain on. If not, the card is not upgraded properly.

NOTE: Note that these firmware and FPGA codes work only when the external clock is in use. Otherwise, the USRPs behavior is unpredictable.

.: Create MIMO Nodes :.

Since USRP2s do not support multiple daughterboards, you need to build a MIMO node by connecting multiple USRP2s to an external clock. For example, we use RFX2400 daughterboard, which can only install one antenna on the TX/RX port. Thus, we build a MIMO node using the external clock produced by Jackson Lab (shown on the right). However, you can also use other brands of clocks.

The following figure on the left shows our testbed where a 2x2 MIMO node is built by connecting two USRP2s to an external clock. The pps port on USRP2 should be connected to the pps port on the external clock, while the reference clock port on USRP2 should be connected to the SINE port on the clock. The port on USRP2 is SMA female. The port on the Jackson Lab clock is BNC female. Therefore, to connect USRP2 to the clock, you might need a SMA-Male-to-BNC-Female cable, shown in the right figure. To connect a clock to multiple USRP2s, you need a BNC-Male-to-Dual-BNC-Female splitter (T splitter) to split one BNC-Female port to two BNC-Female ports. If you want to build a node with more than two antennas, you might need to combine multiple T splitters or buy a multi-port power splitter.


.: Run the Examples :.

We provide four examples shown as follows.

Fig. 1(a)Fig. 1(b)
Fig. 1(c)Fig. 1(d)

    1. The first example shown in Fig. 1(a) is an 1x1 link scenario. This example tells you how to perform basic OFDM decoding, including packet Each antenna transmits three access codes, and t detection, CFO correction, phase tracking, and demodulation. (detailed instructions)

    2. The second example shown in Fig. 1(b) helps you test whether you have built a 2-antenna node correctly. The 2-antenna transmitter uses each of its two antennas to transmit access codes. The single-antenna receiver estimates the channels h1 and h2 from two antennas at the transmitter. (detailed instructions)

    3. In the third example shown in Fig. 1(c), a 2-antenna transmitter cancels its signals at a single-antenna receiver. This example allows you to test whether the 2-antenna transmitter can cancel the signals from its two antennas properly. (detailed instructions)

    4. The example shown in Fig. 1(d) is the nulling example presented in our paper. The single-antenna receiver decodes its packet from the single-antenna transmitter in the presence of a two-antenna transmitter that performs interference nulling. (detailed instructions)

NOTE: It is preferable to run the tx and rx on different machines.
NOTE: To run examples 2, 3 and 4, you have to build a tx node by connecting two USRP2s using an external clock.


.: Write Your Own Module :.

To create your own python module, you will need to write the python script (.py files), C library (.cc files), and the swig file (.i file). The simplest way to create a new module is to copy the existing module and modify it to what you want. We suggest modifying the 'mimo_ofdm_siso' module because it provides the most basic functionality so that you can build your own functions on top of it. In the following, we use modifying 'mimo_ofdm_siso' as the example to demonstrate how to create a new module, called 'mimo_ofdm_new'.

    1. Create python files $ cd gr-mimo/python/
      $ cp mimo_usrp2_ofdm_receiver_siso.py mimo_usrp2_ofdm_receiver_new.py
      $ ln -sf mimo_usrp2_ofdm_receiver_new.py mimo_usrp2_ofdm_receiver.py
      Edit 'mimo_usrp2_ofdm_receiver_new.py' and replace all strings "_siso" with "_new". You might need to make other modifications if you want to create a module with a different number of input ports and output ports.

    2. Create C library $ cd ../lib/
      $ cp mimo_ofdm_siso.cc mimo_ofdm_new.cc
      $ cp mimo_ofdm_siso.h mimo_ofdm_new.h
      Edit 'mimo_ofdm_new.cc' and 'mimo_ofdm_new.h', and replace all strings "_siso" and "_SISO" to "_new" and "_NEW", respectively. Modify the makefile 'Makefile.am'. Add "mimo_ofdm_new.h" under the tag "modinclude_HEADERS =", and add "mimo_ofdm_new.cc" under the tag "libgnuradio_mimo_la_SOURCES =".

    3. Create .i file $ cd ../swig/
      $ cp mimo_ofdm_siso.i mimo_ofdm_new.i
      Edit 'mimo_ofdm_new.i', and replace all strings "_siso" with "_new".

      Add the following two lines in 'mimo.i'. #include "mimo_ofdm_new.h"
      %include "mimo_ofdm_new.i"
      Modify the makefile 'Makefile.am'. Add "mimo_ofdm_new.i" under the tag "mimo_swiginclude_headers =".

    4. Re-build $ cd ../
      $ make; sudo make install

    5. Create the new transmitter code $ cd gnuradio/usrp2/host/apps/
      $ cp mimo_siso_tx1.cc mimo_new.cc
      Add "mimo_new.cc" in 'Makefile.am', and reinstall $ make; sudo make install

    6. Run the example
      In the receiver, $ cd gr-mimo/python
      $ sudo ./mimo_usrp2_rx.py -f 2.45G -d 64 -e eth0 --rx_ant_num 1 -v
      In the transmitter, $ cd source/
      $ sudo mimo_new -f 2.45G -i 64 -e eth1 -v