Noise figure measurements of rtl-sdr dongles

29.03.2015 19:53

Noise figure is a measure of how much noise a component introduces into a signal that passes through it. For a radio receiver, it defines how weak a radio signal it is capable of receiving before the signal is drowned in the receiver's own noise. For instance, in spectrum sensing, having a low noise figure receiver helps a lot when trying to detect hidden transmitters. To have some reference to compare my own receiver design with, I recently performed some noise figure measurements on an Ezcap DVB-T dongle.

Ezcap DVB-T dongle and a R&S SMBV signal generator.

Principles of noise measurements are nicely detailed in an application note from Agilent. Unfortunately I don't have access to specialized noise measurement equipment. I do however have a calibrated Rohde & Schwarz SMBV vector signal generator at work. It can be used as both a continuous wave and a somewhat decent noise source, so I chose to measure the noise figure using both the Y-factor method and the generator twice-power methods.

Both methods require measuring the power of the signal exiting the receiver. I implemented a power meter in GNU Radio using the flow graph shown below (GRC file). It measures true (RMS) signal power in a 200 kHz wide band that is offset by -500 kHz from the center frequency of the tuner. This is to exclude low-frequency noise from the measurement. High level of noise around the DC is characteristic of the direct conversion tuner used by the Ezcap dongle.

rtl-sdr power detector GRC flow graph

The settings used for the RTL-SDR source block are:

  • Sample rate 2.048 Msample/s,
  • LO frequency 700.5 MHz (which puts the center of the 200 kHz measured band at 700 MHz)

I used GNU Radio release 3.7.5.1.

RTL-SDR source block settings.

For twice-power method, I set the signal generator to unmodulated sine wave at 700 MHz and manually found the output power setting that caused a 3 dB change in the power meter reading. This is the minimum discernible signal MDS:

MDS = -104 \mathrm{dBm}
NF_{tp} = -104\mathrm{dB} + 174 \mathrm{dB} - 10\log{\frac{200 \mathrm{kHz}}{1\mathrm{Hz}}} = 17.0 \mathrm{dB}

For the Y-factor method, I used the arbitrary waveform function on the generator to produce Gaussian noise in a 50 MHz band centered on 700 MHz. Total power on the generator was 80 dBm. For such a setup, the excess noise ratio is:

ENR = \frac{P_{gen}}{BW_{gen}\cdot k\cdot T_0} - 1

With the noise generator turned off, the power detector showed -41.5 dB. With the noise generator turned on, the power detector showed -36.5 dB. This gives the following noise figure:

Y = \frac{P_{on}}{P_{off}}
NF_{yf} = 10\log{\frac{ENR}{Y-1}} = 10\log{\frac{49.0}{3.16 - 1}} = 13.6 \mathrm{dB}

These results are curious for several reasons.

First of all, the two methods should produce the same result, but in fact the resulting noise figures differ by 3.4 dB (a factor of around 2). My first suspect was an error in my calculations somewhere. The twice-power method, for example, is sensitive to the measurement bandwidth and this is a common source of errors in my experience. However I have repeated these exact same measurements using a completely simulated receiver in GNU Radio and the same power meter (and hence the same 200 kHz filter). In simulation the two methods agree perfectly, which makes me think the error is not in my calculations.

Another suspect was the quality of the noise for the Y-factor method. This method is typically used with specialized (analog) noise sources, not a pseudo-random vector loaded into an arbitrary waveform generator. However, repeated measurements with different signal powers, pseudo-random cycle lengths and sampling rates are in very good agreement (less than 0.5 dB difference in resulting noise figure). I have also measured the spectral power density used in the ENR calculation (Pgen/BWgen) with a spectrum analyzer and that measurement agrees with the calculated figure to within 0.1 dB.

Above makes me think that both measurements are correct and that there is some physical process in the receiver that is causing this difference. There may be some automatic gain control somewhere that behaves differently. Crest factor for instance is significantly different between noise and constant-wave inputs.

Update: Based on my later discovery that the noise power and ENR was not correct in my Y-factor calculation, it is likely that the 17.0 dB result is more accurate.

The second weird thing is the unusually large value. The noise figure is largely determined by the first stage, which is the low-noise amplifier in the Elonics E4000 tuner integrated circuit in this case. The datasheet specifies a noise figure around 4 dB, which is significantly lower than what I saw. It's not that far fetched though that a cheap design like this would perform worse than the best-case promoted in the datasheet. There might be a noisy power supply and interference from the USB bus for instance.

The most elaborate existing characterization of the rtl-sdr DVB-T dongles I'm aware of was done in 2013 by HB9AJG. Among other things, it also includes measurements of the minimum discernible signal. For the E4000 tuner at 700 MHz, that document states a noise figure of 11.0 dB, which is also somewhat lower than both my measurements. However, I believe HB9AJG made several errors in their article and in fact after accounting for them, their results nicely match mine for the twice-power method (I plan to write a bit more on that in a future post).


In conclusion, even though the results look unusual, I can't find any concrete reason to doubt their accuracy. The noise figure for this particular receiver seems to be between 17.0 and 13.6 dB, which is not particularly good. It depends on what you want to do, of course, but in general these dongles do not work very well with weak signals.

Posted by Tomaž | Categories: Analog | Comments »

Notes on M&M clock recovery

12.03.2015 8:48

M&M (Mueller and Müller) clock recovery is the name of one of the signal processing blocks in GNU Radio. Its task is to recover samples from a signal with the same frequency and phase as those used by the transmitter. This is necessary, for instance, when you want to extract symbols from an asynchronous digital signal. It allows you to synchronize your receiver with centers of ones and zeros present in the signal.

Searching the internet, the way this block works seems to be mostly regarded as black magic by users of GNU Radio. There's very little concrete information on how it works and more importantly, how to make it work in your particular use case since the block takes several parameters. The best I could find were some guesses and some suggestions on which values to try.

This is my attempt to clarify things a bit. I don't claim to completely understand the algorithm though. What's written bellow is my current understanding that I got foremost from studying the source. The academic paper that is cited by GNU Radio source points you to a trail of citations that leads all the way to the original 1976 paper describing the method. I have only read a small part of this literature. As it usually happens, it turned out to be a quite poor substitute for proper software documentation.

M&M Clock Recovery block from GNU Radio

The meat of the implementation is the following loop in general_work() method in clock_recovery_mm_ff_impl.cc. Note that I'm talking about the floating point implementation. There is also a complex number implementation, which should work in a very similar fashion, but I haven't looked into it.

while(oo < noutput_items && ii < ni ) {
  // produce output sample
  out[oo] = d_interp->interpolate(&in[ii], d_mu);
  mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample;
  d_last_sample = out[oo];

  d_omega = d_omega + d_gain_omega * mm_val;
  d_omega = d_omega_mid + gr::branchless_clip(d_omega-d_omega_mid, d_omega_lim);
  d_mu = d_mu + d_omega + d_gain_mu * mm_val;

  ii += (int)floor(d_mu);
  d_mu = d_mu - floor(d_mu);
  oo++;
}

First of all, this code immediately shows some general characteristics of the algorithm, as it is implemented in GNU Radio. All this might seem very obvious to some, but none of it is clearly stated anywhere in the documentation:

  • This is a decimation block. It will output one sample per one or more input samples. Specifically, it will output a sample that it thinks is the center of the symbol. This can be the first source of confusion, since nothing in the name of the block suggests decimation.

  • The decimation rate is not constant. It varies with what the block thinks the current symbol clock is. This is important in context of GNU Radio since many things start behaving weirdly with streams that do not have a constant sample rate (like for instance the Scope instrument with multiple inputs).

  • The signal must have zero mean. The algorithm works by observing sign changes on the signal (the slice() method is basically a signum function).

  • There is some sample interpolation involved. d_interp->interpolate() is a FIR interpolator with 8 taps. This means that output can contain values not strictly present in the input.

The code also gives some insights into the meanings of the somewhat cryptically named parameters:

  • Omega is symbol period in samples per symbol. In other words, it is the inverse of the symbol rate or clock frequency. The value given as the block parameter is the initial guess.

  • The limits within which the omega can change during run time depend on the initial omega and the relative limit parameter. For instance, with omega = 10 and omega_relative_limit = 0.1, the block will allow the omega to change between 9 and 11. Note that until version 3.7.5.1, relative limit was actually absolute due to a bug.

  • Mu is the detected phase shift in samples between the receiver and transmitter. The initial value given as the block parameter doesn't matter in practice, since it's usually impossible to guess the phase in advance. Internally, phase is tracked between 0 to omega (corresponding to 0 and 2π). However, because of the way the code is implemented, you can only set the fractional part of the initial value (i.e. up to 1.0)

  • Mu gain and omega gain are gains in two feedback loops that adjust frequency and phase during run time. Their effect varies with the amplitude of the input signal. Values that are optimal for a signal that goes from -1 to +1 will not work for an identical signal that goes from -10 to +10.

Based on the code above, this is how the M&M clock recovery block samples the input signal. You can imagine that a sine wave on the picture below represents a digital signal of a series of binary ones (>0) and zeros (<0) that has been filtered through a filter. Mu is the distance between the first sample and time zero. Omega is the distance between two consecutive samples:

Illustration of M&M clock recovery algorithm variables.

Finally, if you look at how the code adjusts the omega and mu during run time (through the mm_val value), you can see that:

  • Feedback loop doesn't work on square signals. The method depends on the fact that the center of the symbol is the crest. With a square signal there is no difference between the edge of a symbol and its center and hence the feedback loop has no means of positioning the sampling point.

  • The algorithm will not track phase on perfectly symmetrical input. Consider the sine input above: if the frequency (omega) is perfectly adjusted, the error term will always be zero, regardless of the sampling phase (mu). This is important for instance when constructing artificial test cases for debugging, but it might also cause problems for cases where you want to synchronize on a periodic header (e.g. many packet-based transmissions prefix data with such a synchronization header).

In conclusion, this block is tricky to get right. In fact, after a lot of experimenting, I have failed to make it consistently work better than a straight-forward blind decimator. Note that with an accurate enough estimate of the symbol rate and a low-pass filter in front that matches the symbol rate, an ordinary non-synchronized decimator will do reasonably well. For instance in short packet-based transmissions, you might lose some packets if they arrive with a particularly unfavorable phase difference, but overall the results will look passable.

I suspect many reports of successful usage of the M&M clock recovery block are due to this fact and not because the algorithm worked particularly well. In my experience, a heuristical approach to clock recovery works better (for instance like the one implemented in the capture process in am433 and ec3k receivers). While not as scientific and more computationally complex, its performance is more consistent and hence easier to debug and write unit tests against.

Finally, I also suspect the algorithm in GNU Radio is plagued by some practical implementation problems. It looks very much like the interpolator doesn't work as it should (there was no answer yet to my my question on discuss-gnuradio regarding that). While I haven't investigated it thoroughly, I also think that the code might lose phase tracking between consecutive calls to the general_work() method (only fractional part of the phase is retained between calls). These might happen more or less often depending on how the block is placed in the flow chart and might cause intermittent desynchronizations.

Posted by Tomaž | Categories: Code | Comments »

Comment spam and HTTPS

09.03.2015 21:15

Moving this site to HTTPS-only back in November had one unexpected side effect: the amount of attempted comment spam fell significantly.

The graph below shows the number of submitted comments on this blog that were caught by different spam filters over time. Majority of submissions are blocked by the simple textual captcha that is shown by the orange line. The sharp drop on the graph corresponds exactly with the date I reconfigured the site to be served through HTTPS.

Blog comment submissions versus time.

Immediately after I noticed this change I had two theories: either most spam bots do not implement HTTP 301 redirects that I send on the old HTTP URLs or they in fact skip HTTPS sites. If the first theory was correct, I was expecting the spam to quickly ramp up again as bots rediscover my blog on the new, HTTPS URL through crawlers or what ever other process they use to find victims. However, as you can see, the spam rate shows no sign of increasing after four months.

I don't think lack of support for encryption could be the reason. I'm pretty sure all reasonably modern HTTP libraries transparently support HTTPS as well. My server is also setup in a relatively backwards-compatible fashion as far as SSL ciphers are concerned. It is probably more likely that secure sites are simply not considered a worthy target at the moment. Not that I'm complaining.

Anyway, if you run a website, this might be another reason you might want to switch to HTTPS-only.

Posted by Tomaž | Categories: Code | Comments »

On cyclostationary detectors in literature

01.03.2015 21:50

Recently, I've been studying cyclostationary detectors. These methods of detecting the presence of a radio transmission seem to be quite popular in academic literature. On the other hand, I kind of glossed over them in my seminar on spectrum sensing. There were several reasons for that: one of them was certainly that I find the theory of cyclostationary signals and statistical spectral analysis hard to wrap my head around. Another reason was however that I couldn't find any papers that would describe a practical cyclostationary detector to sufficient enough detail to allow reproduction of published results. At the very least I wanted to compare its performance against other (non-cyclostationary) detectors in a laboratory experiment before writing about it in any depth.

Here are some of the problems I stumbled upon when trying to understand and reproduce results from scientific papers published on this topic. I don't want to point to any particular work. The example below is just a recent one that crossed my desktop (and happens to nicely illustrate all of the problems I write about). I encountered similar difficulties when reading many other research papers.

Example of unreadable mathematical typesetting.

(from Wireless Microphone Sensing Using Cyclostationary Detector presented at the INCT 2012 conference)

Perhaps the most trivial thing that makes reading unnecessary hard is bad mathematical typesetting. It's sometimes bad enough that it is impossible to follow derivations without first rewriting them to a more consistent form. A part of the blame here goes to the publishers who are preferring manuscripts in Word. I have seen some beautiful articles produced in Word, but the fact is that it is much harder to mess up formatting in LaTeX. Not that it is impossible though. I have had to deal with my share of buggy LaTeX styles.

Another common problem that is simple to fix is inconsistent mathematical notation. For instance the constant Ac2/4 gets dropped somewhere in the middle of the derivation above. Also, x might (or might not) mean two different things. I've heard people argue strongly that such trivial errors are of no concern, since obviously everyone in the field knows what is meant by the author. The problem is that mathematical sloppiness creates confusion for readers that are not intimately familiar with the topic. Why even have a theoretical overview section in the paper then, if the assumption is that it the reader already knows it by heart?

After you manage to bite your way through the theoretical sections to the practical evaluation, it is surprisingly common that various parameters necessary to reproduce the results are left out. For instance, a lot of cyclostationary detectors use a method of estimating the cyclic spectrum called the FFT accumulation method. This method takes several parameters, for instance the sizes of two Fourier transforms that determine its time and frequency resolution. These are often omitted. Another omission is the exact waveform used to test the detector. The paper above gives only frequency deviation used by the wireless microphone, but not the nature of the modulation signal.

Having such difficulty reproducing results from papers based on pure numerical simulations is especially frustrating. I imagine the results are based on a few hundred lines of Matlab code which, if published, would quickly remove any doubts on how the results were obtained. However publishing source together with an article is still a rare exception.


Some of the difficulties I've been having are definitely due to my unfamiliarity with the field. As I keep studying the topic, some of the line of thoughts from the authors who wrote these papers become clearer and some mysteries on how they managed to come up with their results deepen. Undoubtedly some of my own writings aren't as clear, or error free, as I liked them to be. However there are literally hundreds of articles written on the topic of cyclostationary detectors and I'm continuously surprised how much time it is taking me to find a single reproducible example.

Posted by Tomaž | Categories: Life | Comments »