Software

__**Software **__

This section examples the inner works of the software. For download, build, and usage information, see the Getting Started page.

The software can be broken down into three main sections: a libusb driver, the GUI frontend, and the GNU Radio backend. The libusb driver is responsible for getting data off the USB bus and into userland. The GUI front end displays information to the user, and controls the flow of the data. The GNU Radio backend uses the GNU Radio framework to do all the signal processing work.

There is also custom firmware on the USB transceiver chip on the Nexys2 board. This firmware sets the chip up to communicate to the USB host PC in the correct way. The chip on the Nexys2 board is the Cypress FX2LP. The firmware makes heavy use of the FX2Lib project, and the CyStream program. FX2Lib can be found here:

[]

CyStream can be found here: []

Fx2Lib provides many library functions to access the features of the chip, and CyStream is a data stream application for the chip which provides many interfaces for streaming data to or from a host. This chip gets set up using alternative interface 3. This sets up a single isochronous IN endpoint on endpoint #2. This endpoint transmits 3 packets per microframe, with 1024 bytes per packet (3072 bytes per microframe). Isochronous mode was used because it provides the best environment for streaming data. In isochronous mode, data is sent at a guaranteed rate, but there is no error correction mechanism. The firmware sets the FX2 up in slave FIFO mode. This means data is clocked into the FX2 from the FPGA. It is set up to clock 8 bits of data in per cycle of the IFCLK line. The FPGA clocks data in at a rate of 20MHz. Since there are 16 bits per data point in both the I and Q components of the output stream, and each stream is sampled at 5MHz, 8 bits of data must enter the FX2 at a rate of 20MHz.

The data is sent in the following format:

I[0:7] Q[0:7] I[8:15] Q[8:15]

The 8 least significant bits of the I component are sent first, followed by the 8 least significant bits of the Q component. Then, the 8 most significant bits of the I component are sent, followed by the 8 most significant bits of the Q component. Seeing the following application notes on streaming data from an FPGA to the FX2:

Cypress AN4053: Streaming Data Through Isochronous/Bulk Endpoints on EZ-USB FX2™ and EZ-USB FX2LP™ http://www.cypress.com/?docID=20041 Cypress AN61345: Implementing an FX2LP-FPGA Interface <span style="font-family: 'Times New Roman',Times,serif; font-size: 120%;">http://www.cypress.com/?docID=27660

<span style="font-family: 'Times New Roman',Times,serif; font-size: 120%;">The LibUSB driver is responsible for communicating with the Linux kernel to get data off the USB bus and into userland, where it can be sent to GNU Radio for processing. The driver uses the asynchronous LibUSB 1.0 API. It creates 8 transfer request structures and submits them to the kernel. The driver then waits until data is ready, during which a callback function is called. While in this callback function, the driver examines the data in 64-byte chunks. To help determine whether the data received is valid, the FPGA writes four bytes of packet data for every 64 bytes. The packet data consists of the data string “NYAN”. If this string is located every 68 bytes (64 data bytes, 4 packet bytes), the driver knows the previous 64 bytes of data are correct. The driver then arranges the bytes so that the positions of the most and least significant bits are in the correct order, and interleaves the I and Q streams. Finally, it writes the interleaved data to a named pipe. The filename of the named pipe is passed to the driver in a command line argument. It is typically given a random name ending with the extension “.sdrjove”. This random name is generated by the GUI at startup. This file is removed when the GUI is closed.

<span style="font-family: 'Times New Roman',Times,serif; font-size: 120%;">The driver is loaded automatically by the GUI when I mode is selected which requires new data (Radio Astronomy mode, Real Time mode, and Full Record mode). Once it is loaded, the driver will claim the device, and then make a pause system call. This system call causes the driver to wait until it receives a signal from the kernel. The driver registers signal handlers for SIGUSR1, SIGUSR2, and SIGINT. When the driver receives a SIGUSR2, it will again call pause, thus halting the driver from getting new data. When it receives a SIGUSR1, it will continue getting new data. When the driver receives a SIGINT, it will exit gracefully, making sure to cancel any existing transfer requests and freeing any data allocated by malloc.

<span style="font-family: 'Times New Roman',Times,serif; font-size: 120%;">When the “Start” button is selected in the GUI, an instance of a GNU Radio top block object is created and executed. If live data is being used, the GNU Radio object will read incoming data from the named pipe. GNU Radio deinterleaves the I and Q streams. It then converts each stream of bytes into a stream of floating point numbers, which is further converted into a complex signal. This complex signal is what all the signal processing functions use. The general flow of the GNU Radio signal processing blocks can be seen using the GNU Radio Companion program, provided by GNU Radio. This program uses flow/graph diagrams to generate GNU Radio Python files which can be executed. While some aspects of the Python files have been modified, the general flow of the data can be seen by examining the .grc files inside the /gui/gnu_radio directory with the GNU Radio Companion. For example, to view the flow diagram for real time mode, change directories to /SDR_JOVE/gui/gnu_radio and execute:

<span style="font-family: 'Times New Roman',Times,serif; font-size: 120%;"> gnuradio-companion live_mode.grc