Bit Error Rate Testing in GNU Radio

When testing modems, its often a good idea to make sure the bit error rate (BER) of your receiver lines up with what you might expect from theory.  To this end, GNU Radio has long needed a handful of blocks which make this easy.  Test equipment often has built in psuedo-random test bit sequence (PRBS) modes which can produce known long strings of whitened bits for this sort of testing, but we’ve not had handy blocks to do this in a nice way without manually using the lfsr block, xor block, and something to count bit errors.

Today I added prbs_source_b and prbs_sink_b to the gr-mapper OOT module which provide ready made blocks for this purpose.  An example flowgraph application has been provided in gr-mapper called “prbs_test.grc” which provides a QPSK loopback test of these BER calculation blocks.  For the moment its just printing statistics to screen and averaging them linearly from startup to the current time, at some point these could output async messages if they needed to be incorporated into a larger suite or some downstream logic, and in the case of wanting a recent-rolling BER rather than an absolute BER over the entire run, we could implement some kind of IIR based averaging in the update.  Regardless, these blocks aren’t super exciting, but they are perhaps useful tools that others can use in modem verification!  Screenshot below –

These same blocks should work equally well over the air — or with other modulations, so long as your framing/sync keeps them properly aligned!

ber_testing

Learning to Synchronize with Attention Models

Synchronization is often one of the most involved tasks to get right when building, testing, and deploying a radio system.  In this work, we look at treating synchronization as a learned attention model in a deep neural network to provide a canonical form signal for classification.  We use the same discriminative network as used in prior work and obtain slightly better classification performance.  We introduce a handful of new layers into Keras to build a domain specific set of radio transforms to supplement those used in imagery and described in this paper on Spatial Transformer Networks.

RTN

Classification is perhaps not the most interesting task to apply an attention model for synchronization.  Due to the extremely low SNR of much of the data-set, good synchronization is hard to achieve on short data samples with learned or expert synchronization metrics, and many of the learned discriminative features seem to be relatively robust to synchronization error.  We plan to revisit this attention model more in future work, potentially for other sorts of tasks for which it may be more beneficial, regardless, plotting a color-coded distribution over the density of constellation points before an after the transform on the QPSK subset of the data-set, we can definitely see some qualitative improvements in orderly signal structure.

density_plots

Checkout the paper on arXiv for more details!

Unsupervised Radio Signal Representation Learning

We’ve just posted a brief new arXiv article (https://arxiv.org/abs/1604.07078) on learning to represent modulated radio signals using unsupervised learning.  We employ a small autoencoder network with convolutional and fully connected layers to fit a sparse signal representation with no expert knowledge or supervision.  Mean squared error reconstruction distance and regularization are used during training.

net (1)

One example of a noisy test set example, its compressed representation, and its reconstruction is shown below for a QPSK signal, additional details are available in the arXiv paper!  We achieve a 16x compression in information density (2x88x4->1×44), and 128x in storage space (2x88x32->1×44)!  We’re looking forward to doing many more things with these ideas!

recon1 (1)

As a side note, since drawing hundreds of neural network connection lines in diagramming tools manually is really not fun, I’ve posted a small tool called NNPlot on github which attempts to make generating high level conceptual neural network diagrams much easier.  Hopefully someone else will find this of use some day, the network diagram above is the first example in it.

Dynamic GNU Radio Channel Model Enhancements

In an attempt to test modem performance deterministically through dropout conditions and partial fades selective, we added the fading model and selective fading model to GNU Radio a few years ago.   Recently Bastian Bloessl pointed out that the auto-correlation properties of these channel responses were degrading over time and did a great write up on it here.

Flat Fader Corrections

After looking into the issue we now have stable auto-correlation properties not degrading with the phase accumulation and large non-dense floating point representation that occurred after very long runs of the original channel model.   Here we see the autocorrelation at the beginning of a run, and 500 MSamples into a run both follow the analytically expected ACF closely with the patch introduced here.   Soon to be squashed and merged in a cleaner fashion.

ac5 ac1

Selective Fading Model 2

The selective fading model in GNU Radio takes N flat fading models at fixed fractional delays measured in samples to define a power delay profile [PDP].  For instance delays of [0,1,1.5] and amplitude of [1,1,0.5] would introduce three flat fading components to a PDP at 0 samples delay, 1 sample delay, and 1.5 samples delay, with magnitudes of 1,1, and 0.5 respectively.   This is a standard way to form a frequency-selective fading channel out of a small number of flat fading components.    However, this is a rather contrived fading channel because the PDP components are a fixed delays in time which don’t change during the simulation!   In the real world, we are moving around, reflectors are moving around, direct and indirect path lengths change over time, and so the delays corresponding to these paths shift earlier or later in time.

In an attempt to simulate this effect, we’ve introduced the selective fading model 2, which adds a delay_std and delay_maxdev parameter to each PDP component.   The delay_std, defines a standard deviation of a gaussian random walk in time per sample, measured in samples, while the delay_maxdev defines a maximum distance in time to deviate from the initial delay value.   Experimentally, this significantly helps to reduce repetitious behavior and create a more realistic seeming fading environment for some scenarios.

Using gr-fosphor, we can see a brief excerpt of white noise sent through a fading channel using selective model 2 below.

new_sel_Fader2

Improved Channel Diagnostics and Visualization

A useful step in the validation of this or any other channel model is that of inspecting the impulse response of the channel.   To enable this we add a message output port to the selective_model2 block which passes the complex channel taps at the end of every work function forward.   For now we can simply plot these complex vector messages so that we can visually see the effect of the channel on the time domain while observing the effect on the spectrogram.   These could of course also be used to cheat in an equalizer or other channel estimation algorithm and use channel state information, CSI, that would otherwise not be available in a real system.   This could be very useful for validation or performance measurement of such algorithms in the future.

The graph implementing this simulation and a still from it are shown below …

graph_plot

fader_resp_plots

Finally, running the simulation, we put together a short video clip to show flat white noise through a Rayleigh/NLOS channel simulation.

[wpvideo et6wj0y1]

Convolutional Radio Modulation Recognition Networks

In an arxiv pre-publication report out today, Johnathan Corgan and I study the adaptation of convolutional neural networks to the task of modulation recognition in wireless systems.   We use a relatively simple two layer convolutional network followed by two dense layers, a much smaller network than required for tasks such as ImageNet/ILVC.

net2

We demonstrate that blind time domain feature learning can perform extremely well at the task of modulation classification, achieving a very high accuracy rate on both clean and noisy data sets.

conf_conv_18

As we compare the classifier performance across a wide range of signal to noise ratios, we demonstrate that it outperforms a number of more traditional expert classifiers using zero-delay cumulant features by a large margin.

modreq_snr

While this is preliminary work, we think the results are exciting and that many additional promising results will come from the marriage of software radio and deep learning fields.

For much more detail on these results, please see our paper!  http://arxiv.org/abs/1602.04105

3D Printing a USRP B200 Mini Case

2016-02-10

[edit] Download or Order this model here

USRPs are incredibly handy devices, they let us play all over the spectrum with the signal processing algorithms and software of the day.  The USRP B210 was an awesome step in practicality requiring only USB3 for I/O and power, minimizing the number of cables required to haul around.   However, it’s size and chunky case options have been a source of frustration.   It’s a nice thing to always keep with you, but when packing bags and conserving space, it just can’t always make the cut.

The Ettus Research USRP B200 Mini recently changed all that by releasing a very compact version of the B200 which takes up virtually no space, but frustratingly doesn’t ship with a case to protect it from abuse!   Carrying around padded electrostatic wrap bags isn’t particularly appealing or protective, so I set about to put together a functional case for the device that would at least protect it from physical abuse.

The top and bottom case renderings of the resulting design are shown below, about the size of a stack of business cards. As long as a GPS-DO isn’t needed, this is now pretty much the perfect compact carrying companion for GNU Radio.

case_bottom case_top

The first print, on a pretty low end 3D printer is shown below.   After a few tweaks, fitment around the SMA plugs is very tight, the board fitment into the case is snug otherwise, a bit of space was added around the USB port to allow various sized plugs to clear it.

2016-02-09 (1)

For scale, we show it here next to a full size B210 + case.   While much of the design of the underlying board is the same here, the size reduction, and more tightly fitted case, and resulting hauling size of this device step is pretty amazing!

2016-02-10 (1)

The fit isn’t completely perfect, it could use a little bit more clearance in a few spots, but it shouldn’t be putting too much tension on any overly fragile areas, and seems like it could take quite a bit of beating.   We’ll see how long this one survives!

For anyone interested in having one of these, the STL Case Models have been made available for purchase, or download on shapeways at https://www.shapeways.com/shops/osh

A bit more eye candy below …

the micro-shibu

case3

case4

case2

Note: I would suggest using something like a #4-40 thread and 3/8″length screw size for securing this, see links below.

Black #4-40, 3/8″ Machine Screws   Black #4-40 Hex Nut

 

GNU Radio TensorFlow Blocks

TensorFlow is a powerful python-numpy expression compiler which supports concurrent GPP and GPU offload of large algorithms.  It has been used largely in the machine learning community, but has implications for the rapid and efficient implementation of numerous algorithms in software.   For GNU Radio, it matches up wonderfully with GNU Radio’s python blocks, which pass signal processing data around as numpy ndarrays which can be directly passed to and from TensorFlow compiled functions.   This is very very similar to what I did with gr-theano, but with the caveat that TensorFlow has native complex64 support without any additional patching!  This makes it a great candidate for dropping in highly computationally complex blocks for prototyping and leveraging highly concurrent GPUs when there is gross data parallelism that can easily be leveraged by the compiler.

A quick example of dropping TensorFlow into a python block might look something like this

class add(gr.sync_block):
 x = tensorflow.placeholder("complex64")
 y = tensorflow.placeholder("complex64")
 def __init__(self):
   gr.sync_block.__init__(self,
     name="tf_add",
     in_sig=[numpy.complex64, numpy.complex64],
     out_sig=[numpy.complex64])
   self.sess = tensorflow.Session()
   self.op = tensorflow.add( self.x, self.y)
 def work(self, input_items, output_items):
   rv = self.sess.run([self.op], feed_dict={self.x:input_items[0], self.y:input_items[1]})
   output_items[0][:] = rv[0]
   return len(rv[0])

We simply define self.op as an algorithmic expression we want to compute at run time, and TensorFlow will compile the kernel down to the GPP or GPU depending on available resources, and handle all of the data I/O behind the scenes after we simply pass ndarrays in and out of the work function.

grtfplot

Dropping this block into a new gr-tf out of tree module, we can rapidly plug it into a working GNU Radio flowgraph stream! Clearly there are algorithms which make a lot more sense to offload than “add_cc”.  Things like streaming CAF or MTI computations with lots of concurrent integration come to mind and would be pretty trivial to add.  For now this is just a proof of concept, but it seems like a great way to prototype such things in the future!

The module is available on github @ https://github.com/osh/gr-tf/

Such Samples 2

Recently Tom Rondeau did a bunch of work to add message passing support to GNU Radio’s Qt based plotters.  This is really cool because now there’s not a whole lot of need for the gr-pyqt (pyqwt based) message plotters anymore other than prototyping custom plotting things.   The obvious thing to do was update Such Samples to switch over to the more efficient, portable, stable, feature filled, and well supported plotters from the main GNU Radio distribution.

Building the Graph

Now that the Qt Gui message plotters have complex PDU message port input, we can simply hook them up to the pyqt file message source and everything works as expected!   To make wandering around recordings easier, there is now an open dialog which passes messages into the message source, and a drop down for file type would be nice to add too.  Overall the flowgraph is super simple and all message based, shown below.

ss2_graph

Graphical Interface

Running the graph, the new plotters look quite a bit cleaner and better than the old ones!  The spectrogram/waterfall plot now supports messages as well, so we include that in addition to the time/frequency plots.   Below you can see a wideband look at the 2.4 GHz ISM band which can be easily explored and intuited in each plot dimension.

ss2

This flowgraph is available on github @ such_samples2.grc

 

 

 

Building a Burst FSK Modem in GNU Radio with Message Lambda Blocks and Eventstream

Lots of cheap electronics tend to use burst FSK modems for wireless communications. GNU Radio has long been able to work with these sorts of communications, but typically it has done so by running an FSK demodulator continuously and then correlating the output for a known preamble sequence such as a with the correlate access code block, and then adding some kind of monolithic special purpose block. This article proposes a slightly different approach to building such a burst FSK waveform to inter-operate with many wireless devices of this style and to be a bit more modular, flexible, simple and intuitive to work with.

Building the Transmitter

In most communications systems, the transmitter is computationally less demanding than the receiver, additionally many FSK burst modems are low baud rate and not particularly demanding from a computational complexity standpoint. I use these two facts as motivation to justify an exceedingly lazy modem design which boils a burst FSK transmitter block down to three simple message lambda blocks as shown below.

fsk_tx.grc

Since they aren’t visible in the screenshot above, the block expression used for the three message lambda blocks are:

Map [0,1] bits to symbols [-1.0,+1.0]
 * lambda x: numpy.array(x, dtype=numpy.float32)*2-1
Interp to Samps per Sym
 * lambda x: numpy.tile(x,[sps,1]).T.reshape([1,len(x)*sps])
FSK Modulate
 * lambda x: numpy.array(numpy.exp(1j*2*numpy.pi*((dev*x*numpy.arange(len(x)))/samp_rate)),dtype="complex64")

We generate random packets of bits, prepend an arbitrary known preamble, map bits to symbols, interpolate to N samples per symbol, and finally modulate our symbols up by a complex sinusoid at plus or minus some FSK deviation frequency. At this point, the modulated bursts can simply be dropped into a transmit sample stream using an eventstream source block whose output is then throttled and run through a simple channel model.

burst_tx_plots

Plotting our FSK burst transmit waveform’s output through the pulse shaping filter, we get a reasonable looking time and frequency profile of the transmitted output signal. This is kind of a fun example to show the power of lamda blocks, in this case we’ve been able to basically write an entire waveform from a couple python expressions all from within GRC with really minimal effort, for a nominal performance penalty, which in this case doesn’t really matter.   If performance was at some point deemed to be important here, blocks could easily be ported one by one to optimized C++ based equivalents.

Building the Receiver

We can take a similar approach to building a burst FSK receiver waveform with stream blocks, message blocks, and event detection. We simply run the received samples through a standard quadrature demodulator block matched roughly to the FSK deviation magnitude. Since this FLL is essentially a random walk when no signal is on the air, and nominally tracking carrier tightly when locked to a burst, we use the variance of the FLL’s output as a detection statistic for bursts, triggering an event when the variance goes below 15 in this case. (or the negative variance rises above -15 in this case).   This can be seen in the graph below.

fsk_rx.grc

In this case at every event we latch in a maximum burst length’s worth of FM demodulated float values containing one burst every time this threshold is reached using the trigger rising edge and eventstream sink blocks. These FM demodulated samples are run through a burst FSK time sync, which performs symbol timing recovery and outputs one soft float value per symbol. Please note this synchronization block is by no means an optimal implementation, and represents only a very quick stab at the problem – but seems to perform well enough in initial test. (I would love to clean this up with more optimal ML synchronization algorithms but haven’t had a chance yet).   The output bits can then be sliced to bits, packed into 8 bit chars, and passed in an output PDU downstream to feed a PDU Socket or TUNTAP interface. A screenshot of the receive waveform is shown below.

burst_rx_plots

Our diagnostic output on the terminal shows that we are indeed recovering the inserted preamble bits correctly (0x036cf is consistently received in our output) Although sometimes with alignment slipping a bit or two in either direction and adjacent noise and data bits flipping randomly – A problem that could be easily taken care of with a MAC header search and framer.

creating event @ time 368183, length = 5000
sps = 8.000000
* MESSAGE DEBUG PRINT PDU VERBOSE *
((tau . 5) (meta . 8) (es::event_length . 5000) (es::event_time . 368183) (es::event_type . edge_event))
pdu_length = 78
contents = 
0000: 40 36 cf 02 c5 d2 b7 48 0c bd 22 44 5c d1 84 c3 
0010: 0b 2e 49 2f 29 7b 96 dd 74 61 88 82 83 47 db 0b 
0020: 2a 40 20 55 81 7d b4 29 36 0e 1d 9e 65 86 4b af 
0030: 3e b9 b1 65 b0 f9 a1 4a be f2 54 1a b2 41 bf 02 
0040: 94 a9 c3 44 3d b2 bb b6 db 6d 2b e4 b4 67 
***********************************
creating event @ time 421379, length = 5000
sps = 8.000000
* MESSAGE DEBUG PRINT PDU VERBOSE *
((tau . 3) (meta . 8) (es::event_length . 5000) (es::event_time . 421379) (es::event_type . edge_event))
pdu_length = 78
contents = 
0000: 00 36 cf 0a 59 29 cb 7b 83 67 5f ac 29 c7 87 d7 
0010: 2e 63 d4 c4 3e ff 68 d2 01 56 cc ba 09 aa 33 16 
0020: 00 7a c7 54 57 12 e3 7b 5a 72 d0 4c 80 aa 44 f1 
0030: cf 77 16 28 65 31 a4 11 f3 12 07 ef e0 42 cc 47 
0040: 57 90 be aa 15 02 89 19 91 f6 c9 83 8a dc 
***********************************

This waveform is available on github for your enjoyment.  Please send pull requests for any improvements you make!