Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Requesting pull for improved accuracy/features of mutability fork into keenerd. #19

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
31ce37d
Improve tuner precision by calculating the VCO divisor at full precis…
mutability Aug 23, 2014
a0e6fae
Spaces->tabs.
mutability Aug 23, 2014
0abf7a8
Quick hackery to allow finetuning by tweaking the IF used by the RTL2…
mutability Aug 24, 2014
3424272
Cleanups to IF-finetuning code.
mutability Aug 24, 2014
d2c7417
Merge branch 'finetune-with-if' of https://github.com/mutability/libr…
mutability Aug 24, 2014
8436d2d
Fix calculation of tuned frequency (sign error).
mutability Aug 24, 2014
f455fa7
More cleanups to finetuning
mutability Aug 25, 2014
e928c5c
Missed a couple of changes while cherrypicking.
mutability Aug 25, 2014
dea6355
Separate tuner IF filter frequency from preferred tuner IF.
mutability Aug 25, 2014
285ee4d
Refuse to set out-of-range downsampling frequencies.
mutability Aug 26, 2014
7762b14
Remove some debug output.
mutability Aug 26, 2014
af744aa
Don't fall over if two consecutive batches happen to set entirely ide…
mutability Aug 26, 2014
6ff9ef0
Simplify the PLL mix_div / div_num calculation, and make sure we don'…
mutability Aug 26, 2014
4ed98de
Set RF mux based on target frequency, not LO frequency.
mutability Aug 26, 2014
d775bd0
Better selection of PLL/LO frequencies near the edges of the tuning b…
mutability Aug 26, 2014
4b5544c
Decrease vco_min a little as it still seems stable there.
mutability Aug 26, 2014
c5d2337
Set the image rejection filter correctly based on whether we are doing
mutability Aug 26, 2014
a22a0f6
Simplifying how direct sampling, filtering, offset tuning etc interact.
mutability Aug 26, 2014
9f79bdb
Merge remote-tracking branch 'upstream/master'
mutability Aug 26, 2014
75aeff8
Integrate no-mod direct sampling with tuning changes, including bugfi…
mutability Aug 28, 2014
c2bd4fe
Untested E4K support for extended tuning ranges.
mutability Aug 28, 2014
686ee59
Replace E4K_FLO_MIN/MAX defines (which were unused) with comments.
mutability Aug 28, 2014
0abb25f
Try to discover the PLL range of the particular dongle in use at runt…
mutability Aug 28, 2014
790a61b
Silence some more debugging output.
mutability Aug 28, 2014
302950b
Add a generic tuner tester to replace the E4k/R820T benchmarks.
mutability Aug 28, 2014
fa7bbce
Fix a misleading comment.
mutability Aug 28, 2014
2d9d32b
Fix an inconsistency in max_step()
mutability Aug 28, 2014
7bf2dd9
r82xx: Fix VCO lower-bound range check.
mutability Aug 29, 2014
29ef211
Update README
mutability Sep 29, 2014
437036d
linewrap
mutability Sep 29, 2014
f37e89f
Set PLL_INITIAL_HIGH to 1885MHz based on feedback
mutability Sep 29, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,132 @@ turns your Realtek RTL2832 based DVB dongle into a SDR receiver

For more information see:
http://sdr.osmocom.org/trac/wiki/rtl-sdr


Notes on the mutability tree (2014/09/29)
=========================================

Since there seems to be some wider interest in this, some quick notes on
my changes here.

TL;DR:

0Hz
.
. "no mod direct sampling"
. no mixing at all, tuner is mostly disabled, just ram as much signal
. as you can at it and maybe some will leak through.
. YMMV a lot
.
~13MHz (PLL lower limit - 14MHz)
.
. normal tuning, large IF.
. high-side mixing
. you will see nasty aliasing / attentuation / harmonics
. near the lower edge of the range
. you will see lots of noise from the dongle itself near 14.4MHz
.
~21MHz (PLL lower limit - 6MHz) <- upstream tuner lower limit
.
. normal tuning, regular IF
. high-side mixing
. this should behave much like upstream
.
~1844Mhz (PLL upper limit - 6MHz) <- upstream tuner upper limit
.
. normal tuning, small IF (getting squashed against the PLL upper bound)
. high-side mixing
.
~1848MHz (PLL upper limit - 2MHz)
.
. tuning with low-side mixing (PLL frequency below tuned frequency)
. you will see nasty aliasing / attentuation / harmonics
. near the upper edge of the range
.
~1864MHz (PLL upper limit + 14MHz) <- that's all, folks

(PLL limits vary by dongle - some go as high as 1885MHz)

This tree is a collection of random tuner hacks which are really exploratory
more than anything. They may or may not work for you.

First some background for those unfamiliar with the internals of the dongle:

* The R820T tuner has a tunable PLL that can generate frequencies between
around 27MHz .. 1850MHz. The exact range varies from dongle to dongle.
* The tuner mixes the incoming RF signal with this PLL output. This shifts
the RF signal down to a frequency that is the difference between the PLL
frequency and the RF signal's frequency.
* The tuner sends this intermediate frequency (IF) signal to the RTL2838U
* The RTL2838U digitizes the IF signal and does a digital downconversion
step to generate I/Q samples that are centered around "zero". The
downconverter can theoretically handle IF signals up to 14.4MHz.

The main change is to feed information about the actually-tuned frequency back
from the tuner (R820T) code to the core (RTL2832U) code, allowing the core
code to adjust to the actual IF in use, rather than requiring a fixed IF. The
core code has also been taught how to handle low-side mixing, where the PLL
frequency is lower than the requested frequency (e.g. the spectrum inversion
changes then)

When tuning, the R820T tuner will try to tune to the requested frequency +
6MHz, producing a 6MHz IF. If the PLL cannot handle that frequency, the tuner
will try a few things to produce something useful.

At the top of the tuning range:

* It will tune as high as it can go normally, then stick there producing a
smaller effective IF as the requested frequency gets higher and higher.
* Once the IF starts getting too small (below about 1.5MHz things start to
go bad), it will switch to low-side mixing and try to put the PLL frequency
*below* the target frequency. This gives you another 14-15 MHz at the top
of the range.

I've had reports that some dongles can tune to within a whisker of 2000MHz
with this.

At the bottom of the range:

* It will tune as low as it can go normally, then stick there producing a
larger effective IF as the requested frequency gets lower and lower.
* Once the required IF exceeds 14.4MHz, it will switch to a variant of tejeez'
et al "no mod direct sampling" mode. This essentially disables the PLL in
the tuner entirely, and relies on some RF signal leaking through the tuner
unchanged. The tuner claims to be tuned to 0Hz in this mode, and the core
does all the real tuning. The dongle is almost deaf in this mode, you will
have to turn the RF gain WAY UP. You do not need to mess with direct sampling
settings to enable this, it's integrated with normal tuning.

The success of the "no mod direct sampling" mode seems to vary a lot from dongle
to dongle. Mine is almost completely deaf so I can't test this much. Others have
had success in tuning to shortwave stations as low as 3.5MHz.

The actual PLL limits vary from dongle to dongle, and from day to day (they're
probably temperature related). The tuner has three sets of tuning limits:

* a hardcoded "do not exceed this" set of limits - see PLL_INITIAL_LOW /
PLL_INITIAL_HIGH in tuner_r82xx.c. These are in place because, especially at
the low end of the range, the PLL can get into a state where you ask for (for
example) 25MHz, the PLL claims to be locked OK at that frequency, but in
reality it's actually producing 27MHz, which screws up the core's calculations
of the IF offset needed.
* a hardcoded "known to be OK" set of limits - see PLL_SAFE_LOW / PLL_SAFE_HIGH
in tuner_r82xx.c. This is a range where the PLL should always work; if the PLL
doesn't work in this range it is treated as a tuning error and tuning fails.
* a runtime "seems to be OK at the moment" set of limits. This varies from run
to run and initially starts at the "do not exceed" limits. Whenever a failure
to get PLL lock is seen, the runtime limits are shrunk accordingly and we try
again. This allows the tuner to adapt to the particular dongle in use.

Remember that at the extreme edges of these ranges you will be fighting an uphill
battle against the dongle design itself, as you will be far out of the intended
range of the filters etc and nothing works particularly well.

You are likely to see small frequency shifts (maybe 1-2ppm) from what you get in
upstream. This is because the tuner+2832 combination can be tuned a little more
accurately than upstream does, so some errors that you will have previously been
correcting for will disappear.


-- Oliver ([email protected] / [email protected])

4 changes: 0 additions & 4 deletions include/rtl-sdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,6 @@ RTLSDR_API int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data,

RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq);

RTLSDR_API int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq);

RTLSDR_API int rtlsdr_set_if_bandwidth(rtlsdr_dev_t *dev, int bw);

/*!
* Get actual frequency the device is tuned to.
*
Expand Down
2 changes: 1 addition & 1 deletion include/tuner_e4k.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ int e4k_standby(struct e4k_state *e4k, int enable);
int e4k_if_gain_set(struct e4k_state *e4k, uint8_t stage, int8_t value);
int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value);
int e4k_commonmode_set(struct e4k_state *e4k, int8_t value);
int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq);
int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq, uint32_t *lo_freq);
int e4k_tune_params(struct e4k_state *e4k, struct e4k_pll_params *p);
uint32_t e4k_compute_pll_params(struct e4k_pll_params *oscp, uint32_t fosc, uint32_t intended_flo);
int e4k_if_filter_bw_get(struct e4k_state *e4k, enum e4k_if_filter filter);
Expand Down
10 changes: 8 additions & 2 deletions include/tuner_r82xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ struct r82xx_priv {
enum r82xx_tuner_type type;

uint32_t bw; /* in MHz */
uint32_t if_filter_freq; /* in Hz */

int pll_off;

/* current PLL limits */
uint32_t pll_low_limit;
uint32_t pll_high_limit;

void *rtl_dev;
};
Expand All @@ -116,11 +123,10 @@ enum r82xx_delivery_system {

int r82xx_standby(struct r82xx_priv *priv);
int r82xx_init(struct r82xx_priv *priv);
int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq);
int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq, uint32_t *lo_freq_out);
int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain);
int r82xx_set_nomod(struct r82xx_priv *priv);
int r82xx_set_dither(struct r82xx_priv *priv, int dither);
int r82xx_set_bw(struct r82xx_priv *priv, uint32_t bw);
int r82xx_set_if_freq(struct r82xx_priv *priv, uint32_t freq);

#endif
Loading