Overview of the E4000 RTL SDR Tuner's IF stage 🎚️
Paul Tagliamonte 2020-11-03 deviceThis post is all about the E4000 (e4k) RTL-SDR Tuner, commonly found in the Nooelec RTL-SDR. It’s one of my favorite RTL-SDR tuners, but it can be incredibly frustrating to work with if it’s not left on AGC.
Specifically, this post covers a quirk of e4k rtlsdr dongles, the addition of an IF gain stage.
What is the IF stage?
The IF (or intermediate frequency) stage is where the input signal has been shifted to a common frequency. This allows internal components to be designed to work at one frequency (such as a single oscillator that works on a specific frequency), and have a single component that takes any frequency and shifts it to the common frequency before processing that signal. Transceivers that convert signals to an IF for processing are sometimes called “Superheterodyne” transceivers.
How does gain work on the e4k rtl-sdr?
e4k based rtl-sdr devices have two gain stages, the first is the tuner gain stage,
which can be set using rtlsdr_set_tuner_gain
. Valid gain values
for the connected
rtl-sdr device can be queried via rtlsdr_get_tuner_gains
.
The second gain stage is the IF gain, which preforms amplification on the
signal after it’s been converted to a single intermediate frequency.
Unfortunately, setting and creating value IF gain configurations is not quite
as easy as working with tuner gain. There’s no way to get the supported
if_tuner_gains, and confusingly, rtlsdr_set_tuner_if_gain
takes an
extra argument — stage!
Without a bit of deeper knowledge about the e4k, It’s not super clear what stage should be set to, nor what gain range or gain values are supported, and documentation on this is very lacking if you’re searching for RTL-SDR documentation. Don’t panic!
Internally, the IF Gain on the e4k is made up of 6 stages, each of which can be set to a specific set of values, but in practice (and as a user) you generally set all 6 gains together.
Each stage has a set number of gain values that are supported (which differ per-stage), and can be a bit confusing to understand at first glace.
Stage 1 | -3dB | 6db | |||
Stage 2 | 0dB | 3dB | 6dB | 9dB | |
Stage 3 | 0dB | 3dB | 6dB | 9dB | |
Stage 4 | 0dB | 1db | 2dB | ||
Stage 5 | 3dB | 6db | 9dB | 12dB | 15dB |
Stage 6 | 3dB | 6db | 9dB | 12dB | 15dB |
Each of these gain stages can be added together to determine the total gain of the IF stage. As an example, if we used the 0th values of the table above, the final gain would be -3 + 0 + 0 + 0 + 3 + 3, giving us a final gain of 3dB. You can set any valid values for each gain stage, and it should provide you the right output gain amount.
However, the e4k datasheet provides two tables, one optimized for linearity, and one optimized for sensitivity. I’ve converted those tables into Go for use in my SDR library. You can find the Sensitivity Table and Linerarity Table in the bottom of this post.
The reason why those tables are different (and have different performance profiles) is that although the total gain is simply additive as shown above, doing large gains at the early stage results in a different signal than doing large gains at the final stages. Neither are wrong - but if you’re doing something like FM, FSK, or OFDM, linerarity matters a lot less than if you’re processing AM. Neither is a more correct configuration, but there are trade-offs, so do make a conscious decision as to which table you use!
Do RLT-SDR tuners other than the e4k have an IF gain control?
Not that I’m aware of! This scheme is only supported with the E4000 as far as I understand. Other SDRs (like the HackRF) do have IF gain controls, but that’s out of scope for this post.
Tables
The following are two tables that have been transcribed from the elonics e4000 datasheet into Go. If you’re using another language, you may need to translate these values to a different format.
Each table stores values in the same way RTL-SDR Tuner gains are stored, which is in tenths of a DB. When you see -30, that’s really -3dB. Be careful when computing total gain!
The gain values in the comment are a bit confusing (even to me now) - they’re taken from the E4000 documentation directly, but they don’t align with the provided stage values. Here, the -3 + 3 + 3 is computed as 6dB, which doesn’t match up the table values. I’ll update this post if I ever figure out why the -3 dB attenuation isn’t being factored in. In my own code, I’m using the values that I compute when adding values, in direct contradiction of the datasheet. It’s likely wrong, but it’s not a large difference for now.
Sensitivity Table
senIFGains = []Stages{ Stages{-30, 00, 00, 00, 30, 30}, // 6 dB gain Stages{-30, 00, 00, 10, 30, 30}, // 7 dB gain Stages{-30, 00, 00, 20, 30, 30}, // 8 dB gain Stages{-30, 30, 00, 00, 30, 30}, // 9 dB gain Stages{-30, 30, 00, 10, 30, 30}, // 10 dB gain Stages{-30, 30, 00, 20, 30, 30}, // 11 dB gain Stages{-30, 60, 00, 00, 30, 30}, // 12 dB gain Stages{-30, 60, 00, 10, 30, 30}, // 13 dB gain Stages{-30, 60, 00, 20, 30, 30}, // 14 dB gain Stages{60, 00, 00, 00, 30, 30}, // 15 dB gain Stages{60, 00, 00, 10, 30, 30}, // 16 dB gain Stages{60, 00, 00, 20, 30, 30}, // 17 dB gain Stages{60, 30, 00, 00, 30, 30}, // 18 dB gain Stages{60, 30, 00, 10, 30, 30}, // 19 dB gain Stages{60, 30, 00, 20, 30, 30}, // 20 dB gain Stages{60, 60, 00, 00, 30, 30}, // 21 dB gain Stages{60, 60, 00, 10, 30, 30}, // 22 dB gain Stages{60, 60, 00, 20, 30, 30}, // 23 dB gain Stages{60, 90, 00, 00, 30, 30}, // 24 dB gain Stages{60, 90, 00, 10, 30, 30}, // 25 dB gain Stages{60, 90, 00, 20, 30, 30}, // 26 dB gain Stages{60, 90, 30, 00, 30, 30}, // 27 dB gain Stages{60, 90, 30, 10, 30, 30}, // 28 dB gain Stages{60, 90, 30, 20, 30, 30}, // 29 dB gain Stages{60, 90, 60, 00, 30, 30}, // 30 dB gain Stages{60, 90, 60, 10, 30, 30}, // 31 dB gain Stages{60, 90, 60, 20, 30, 30}, // 32 dB gain Stages{60, 90, 90, 00, 30, 30}, // 33 dB gain Stages{60, 90, 90, 10, 30, 30}, // 34 dB gain Stages{60, 90, 90, 20, 30, 30}, // 35 dB gain Stages{60, 90, 90, 00, 60, 30}, // 36 dB gain Stages{60, 90, 90, 10, 60, 30}, // 37 dB gain Stages{60, 90, 90, 20, 60, 30}, // 38 dB gain Stages{60, 90, 90, 00, 90, 30}, // 39 dB gain Stages{60, 90, 90, 10, 90, 30}, // 40 dB gain Stages{60, 90, 90, 20, 90, 30}, // 41 dB gain Stages{60, 90, 90, 00, 120, 30}, // 42 dB gain Stages{60, 90, 90, 10, 120, 30}, // 43 dB gain Stages{60, 90, 90, 20, 120, 30}, // 44 dB gain Stages{60, 90, 90, 00, 150, 30}, // 45 dB gain Stages{60, 90, 90, 10, 150, 30}, // 46 dB gain Stages{60, 90, 90, 20, 150, 30}, // 47 dB gain Stages{60, 90, 90, 00, 150, 60}, // 48 dB gain Stages{60, 90, 90, 10, 150, 60}, // 49 dB gain Stages{60, 90, 90, 20, 150, 60}, // 50 dB gain Stages{60, 90, 90, 00, 150, 90}, // 51 dB gain Stages{60, 90, 90, 10, 150, 90}, // 52 dB gain Stages{60, 90, 90, 20, 150, 90}, // 53 dB gain Stages{60, 90, 90, 00, 150, 120}, // 54 dB gain Stages{60, 90, 90, 10, 150, 120}, // 55 dB gain Stages{60, 90, 90, 20, 150, 120}, // 56 dB gain Stages{60, 90, 90, 00, 150, 150}, // 57 dB gain Stages{60, 90, 90, 10, 150, 150}, // 58 dB gain Stages{60, 90, 90, 20, 150, 150}, // 59 dB gain Stages{60, 90, 90, 30, 150, 150}, // 60 dB gain }
Linerarity Table
linIFGains = []Stages{ Stages{-30, 00, 00, 00, 30, 30}, // 6 dB gain Stages{-30, 00, 00, 10, 30, 30}, // 7 dB gain Stages{-30, 00, 00, 20, 30, 30}, // 8 dB gain Stages{-30, 00, 00, 00, 30, 60}, // 9 dB gain Stages{-30, 00, 00, 10, 30, 60}, // 10 dB gain Stages{-30, 00, 00, 20, 30, 60}, // 11 dB gain Stages{-30, 00, 00, 00, 30, 90}, // 12 dB gain Stages{-30, 00, 00, 10, 30, 90}, // 13 dB gain Stages{-30, 00, 00, 20, 30, 90}, // 14 dB gain Stages{-30, 00, 00, 00, 30, 120}, // 15 dB gain Stages{-30, 00, 00, 10, 30, 120}, // 16 dB gain Stages{-30, 00, 00, 20, 30, 120}, // 17 dB gain Stages{-30, 00, 00, 00, 30, 150}, // 18 dB gain Stages{-30, 00, 00, 10, 30, 150}, // 19 dB gain Stages{-30, 00, 00, 20, 30, 150}, // 20 dB gain Stages{-30, 00, 00, 00, 60, 150}, // 21 dB gain Stages{-30, 00, 00, 10, 60, 150}, // 22 dB gain Stages{-30, 00, 00, 20, 60, 150}, // 23 dB gain Stages{-30, 00, 00, 00, 90, 150}, // 24 dB gain Stages{-30, 00, 00, 10, 90, 150}, // 25 dB gain Stages{-30, 00, 00, 20, 90, 150}, // 26 dB gain Stages{-30, 00, 00, 00, 120, 150}, // 27 dB gain Stages{-30, 00, 00, 10, 120, 150}, // 28 dB gain Stages{-30, 00, 00, 20, 120, 150}, // 29 dB gain Stages{-30, 00, 00, 00, 150, 150}, // 30 dB gain Stages{-30, 00, 00, 10, 150, 150}, // 31 dB gain Stages{-30, 00, 00, 20, 150, 150}, // 32 dB gain Stages{-30, 00, 30, 00, 150, 150}, // 33 dB gain Stages{-30, 00, 30, 10, 150, 150}, // 34 dB gain Stages{-30, 00, 30, 20, 150, 150}, // 35 dB gain Stages{-30, 00, 60, 00, 150, 150}, // 36 dB gain Stages{-30, 00, 60, 10, 150, 150}, // 37 dB gain Stages{-30, 00, 60, 20, 150, 150}, // 38 dB gain Stages{-30, 00, 90, 00, 150, 150}, // 39 dB gain Stages{-30, 00, 90, 10, 150, 150}, // 40 dB gain Stages{-30, 00, 90, 20, 150, 150}, // 41 dB gain Stages{-30, 30, 90, 00, 150, 150}, // 42 dB gain Stages{-30, 30, 90, 10, 150, 150}, // 43 dB gain Stages{-30, 30, 90, 20, 150, 150}, // 44 dB gain Stages{-30, 60, 90, 00, 150, 150}, // 45 dB gain Stages{-30, 60, 90, 10, 150, 150}, // 46 dB gain Stages{-30, 60, 90, 20, 150, 150}, // 47 dB gain Stages{60, 00, 90, 00, 150, 150}, // 48 dB gain Stages{60, 00, 90, 10, 150, 150}, // 49 dB gain Stages{60, 00, 90, 20, 150, 150}, // 50 dB gain Stages{60, 30, 90, 00, 150, 150}, // 51 dB gain Stages{60, 30, 90, 10, 150, 150}, // 52 dB gain Stages{60, 30, 90, 20, 150, 150}, // 53 dB gain Stages{60, 60, 90, 00, 150, 150}, // 54 dB gain Stages{60, 60, 90, 10, 150, 150}, // 55 dB gain Stages{60, 60, 90, 20, 150, 150}, // 56 dB gain Stages{60, 90, 90, 00, 150, 150}, // 57 dB gain Stages{60, 90, 90, 10, 150, 150}, // 58 dB gain Stages{60, 90, 90, 20, 150, 150}, // 59 dB gain Stages{60, 90, 90, 30, 150, 150}, // 60 dB gain }