This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.
Leif Asbrink leif at sm5bsz.comHi All, The e4000 tuner is flexible in that it allows different gain distributions that optimize it for usage in different environments. With high gain near the antenna and low gain after the filters one can get a low noise figure and a good dynamic range for close range interference. The bad side is that the early stages can become saturated by signals at large frequency separations. If the user adds a bandpass filter for a narrow frequency range, this mode gives the best performance. With low gain near the antenna and high gain after the filters one can tolerate stronger signals at large frequency separation at the expense of a lower dynamic range for close spaced signals. This is useful when using the tuner without any filters. Besides the standard gain distribution which is a compromise I have added two more gain modes in Linrad. The function set_tuner_gain_mode() accepts values from 0 to 3 where 0 and 1 are identical to the original settings. The AGC mode does not work quite ok, it was better some months ago, but it does work with the batch below since it is no longer totally disabled. Always disabling the AGC in the rtl2832 chip may or may not be a good idea. The noise figures and points of saturation are similar at full gain in all modes. The table shows performance with the tuner set to 144.2 MHz with Linrad set to receive 144.5 MHz. The columns with a frequency show the signal level in dBm at each frequency that can be applied without A/D saturation or significant loss of S/N: Mode Gain NF 143.8 145.5 154.2 1 42 7.9 -53 -44 -43 2 25 8.3 -56 -44 -20 3 25 7.0 -59 -48 -20 Note what happens for 10 MHz separation. Better performance at wide range leads to worse performance at close range. In mode 2 there is a 3 dB dynamic range loss at close range. When the attenuator is set for a NF of about 17 dB (10 dB below optimum sensitivity for the desired signal, these data are obtained: Mode Gain NF 143.8 145.5 154.2 1 24 17 -41 -29 -30 2 10 20 -41 -30 -8 3 0 17 -34 -26 -16 The above was performed applying the pattc below to the library downloaded a couple of days ago. I do not think the changes will affect any other software that uses the library. The set_tuner_gain_mode() function now returns the gain mode or the highest allowed gain mode if the user tries to set a too high one. Before, the function always returned zero so there was no reason to check the return value. The patch is included below. If the basic principle is accepted for the osmocom library I guess defines should be moved to the header file and the global variable put into the dev structure. Regards Leif / SM5BSZ diff ../rtl-sdr-ref/src/librtlsdr.c src/librtlsdr.c 93a94,102 > // Sept 24 2012 SM5BSZ. Gain modes. > // Note that these things are used in tuner_e4k.c also. > // The routine using them should be moved to tuner_e4k.c > extern int e4k_gain_mode; > #define E4K_GAIN_MODE_OLD 1 > #define E4K_GAIN_MODE_LINEARITY 2 > #define E4K_GAIN_MODE_SENSITIVITY 3 > #define MAX_E4K_GAIN_MODES 3 > 127c136,140 < if(e4k_set_lna_gain(&devt->e4k_s, min(300, gain - mixgain * 10)) == -EINVAL) --- > // SM5BSZ Sept24 2012: Use only (the modified) set_lna_gain if the user > // asked for linearity or sensitivity. > if(e4k_gain_mode <= E4K_GAIN_MODE_OLD) > { > if(e4k_set_lna_gain(&devt->e4k_s, min(300, gain - mixgain * 10)) == -EINVAL) 129c142 < if(e4k_mixer_gain_set(&devt->e4k_s, mixgain) == -EINVAL) --- > if(e4k_mixer_gain_set(&devt->e4k_s, mixgain) == -EINVAL) 130a144 > // SM5BSZ: enhanced gain should affect how the AGC turns down the gain 132c146 < if(enhgain >= 0) --- > if(enhgain >= 0) 136c150,153 < return 0; --- > return 0; > } > e4k_set_lna_gain(&devt->e4k_s, gain); > return 0; 137a155 > 141a160 > 785a805,807 > // Sept 2012 SM5BSZ: Add standard gains > const int e4k_std_gains[] = { -250, -200, -150, -100, -50, 0, 50, > 100, 150, 200, 250}; 802c824,832 < ptr = (int *)e4k_gains; len = sizeof(e4k_gains); --- > // Sept 2012 SM5BSZ: Use standard gains (5 dB step) if gain is mode above 1. > if(e4k_gain_mode < 2) > { > ptr = (int *)e4k_gains; len = sizeof(e4k_gains); > } > else > { > ptr= (int *)e4k_std_gains; len = sizeof(e4k_std_gains); > } 879a910,922 > > // SM5BSZ Oct 17 2012 Reconfigure the rtl > if(mode) > { > /* enable SDR mode, disable DAGC (bit 5) */ > rtlsdr_demod_write_reg(dev, 0, 0x19, 0x05, 1); > } > else > { > /* enable AGC */ > rtlsdr_demod_write_reg(dev, 0, 0x19, 0x25, 1); > } > diff ../rtl-sdr-ref/src/tuner_e4k.c src/tuner_e4k.c 41a42,49 > // Sept 24 2012 SM5BSZ. Gain modes. > // Note that these things are used in librtlsdr.c also. > int e4k_gain_mode; > #define E4K_GAIN_MODE_OLD 1 > #define E4K_GAIN_MODE_LINEARITY 2 > #define E4K_GAIN_MODE_SENSITIVITY 3 > #define MAX_E4K_GAIN_MODES 3 > 659a668,671 > // SM5BSZ Sept 24 2012: Use all gain controls if gain mode > // is above 1 > if(e4k_gain_mode <= E4K_GAIN_MODE_OLD) > { 666a679,935 > } > if(e4k_gain_mode == E4K_GAIN_MODE_LINEARITY) > { > switch (gain) > { > case -250: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 0); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 9); > e4k_if_gain_set(e4k, 6, 6); > break; > > case -200: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 0); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 9); > break; > > case -150: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 0); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 9); > break; > > case -100: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 0); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 3); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 9); > break; > > case -50: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 0); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > case 0: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 4); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > case 50: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 6); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > case 100: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 8); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > > case 150: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 10); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > case 200: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 12); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > > case 250: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 12); > e4k_if_gain_set(e4k, 6, 12); > break; > } > } > if(e4k_gain_mode == E4K_GAIN_MODE_SENSITIVITY) > { > switch (gain) > { > case -250: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 6); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case -200: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 8); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case -150: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 10); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case -100: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 12); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case -50: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 4); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case 0: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 2); > e4k_if_gain_set(e4k, 5, 3); > e4k_if_gain_set(e4k, 6, 3); > break; > > case 50: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, -3); > e4k_if_gain_set(e4k, 2, 3); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case 100: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, 6); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 6); > e4k_if_gain_set(e4k, 6, 3); > break; > > case 150: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, 6); > e4k_if_gain_set(e4k, 2, 0); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 2); > e4k_if_gain_set(e4k, 5, 9); > e4k_if_gain_set(e4k, 6, 3); > break; > break; > > case 200: > fprintf(stderr,"\nCASE 200"); > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, 6); > e4k_if_gain_set(e4k, 2, 3); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 1); > e4k_if_gain_set(e4k, 5, 9); > e4k_if_gain_set(e4k, 6, 6); > break; > > case 250: > e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, 14); > e4k_mixer_gain_set(e4k, 12); > e4k_if_gain_set(e4k, 1, 6); > e4k_if_gain_set(e4k, 2, 6); > e4k_if_gain_set(e4k, 3, 0); > e4k_if_gain_set(e4k, 4, 0); > e4k_if_gain_set(e4k, 5, 9); > e4k_if_gain_set(e4k, 6, 9); > break; > } > } > return gain; 694a964,969 > // Sept 24 2012 SM5BSZ. Add a flag for more gain modes and return it > // so we know the library has this feature. > e4k_gain_mode=manual; > if(e4k_gain_mode > MAX_E4K_GAIN_MODES)e4k_gain_mode=MAX_E4K_GAIN_MODES; > return e4k_gain_mode; > 695a971 > e4k_gain_mode=0; 701a978 >