1
0
Fork 0

Set RTL AGC mode by default (no improvement), with command-line option to disable.

This commit is contained in:
Joris van Rantwijk 2014-01-18 20:44:17 +01:00
parent ff985cd623
commit 761b368282
5 changed files with 33 additions and 12 deletions

View File

@ -29,9 +29,7 @@ settings during a run. The LNA gain seems to switch between ~ 24 dB
and ~ 34 dB without intermediate steps. and ~ 34 dB without intermediate steps.
With RTL in AGC mode, the level of the digital sample stream is normalized With RTL in AGC mode, the level of the digital sample stream is normalized
to -6 dB FS. to -6 dB FS. Unknown whether this is an analog or digital gain stage.
Unknown whether this is an analog or digital gain stage.
Does this improve SNR or not?
At first I suspected that AGC mode may be a cooperation between the RTL and At first I suspected that AGC mode may be a cooperation between the RTL and
the Elonics tuner. I thought that the RTL would monitor the level and send the Elonics tuner. I thought that the RTL would monitor the level and send

View File

@ -39,7 +39,8 @@ RtlSdrSource::~RtlSdrSource()
bool RtlSdrSource::configure(uint32_t sample_rate, bool RtlSdrSource::configure(uint32_t sample_rate,
uint32_t frequency, uint32_t frequency,
int tuner_gain, int tuner_gain,
int block_length) int block_length,
bool agcmode)
{ {
int r; int r;
@ -78,6 +79,13 @@ bool RtlSdrSource::configure(uint32_t sample_rate,
} }
} }
// set RTL AGC mode
r = rtlsdr_set_agc_mode(m_dev, int(agcmode));
if (r < 0) {
m_error = "rtlsdr_set_agc_mode failed";
return false;
}
// set block length // set block length
m_block_length = (block_length < 4096) ? 4096 : m_block_length = (block_length < 4096) ? 4096 :
(block_length > 1024 * 1024) ? 1024 * 1024 : (block_length > 1024 * 1024) ? 1024 * 1024 :

View File

@ -25,13 +25,14 @@ public:
* *
* sample_rate :: desired sample rate in Hz. * sample_rate :: desired sample rate in Hz.
* frequency :: desired center frequency in Hz. * frequency :: desired center frequency in Hz.
* gain :: desired tuner gain index, or -1 for auto-gain. * tuner_gain :: desired tuner gain in 0.1 dB, or -1 for auto-gain.
* block_length :: preferred number of samples per block. * block_length :: preferred number of samples per block.
* *
* Return true for success, false if an error occurred. * Return true for success, false if an error occurred.
*/ */
bool configure(uint32_t sample_rate, uint32_t frequency, int tuner_gain, bool configure(uint32_t sample_rate, uint32_t frequency, int tuner_gain,
int block_length=default_block_length); int block_length=default_block_length,
bool agcmode=false);
/** Return current sample frequency in Hz. */ /** Return current sample frequency in Hz. */
uint32_t get_sample_rate(); uint32_t get_sample_rate();

View File

@ -1,12 +1,9 @@
* (experiment) consider reducing IF filter bandwidth to ~ 80 kHz * (experiment) consider reducing IF filter bandwidth to ~ 80 kHz
* (experiment) consider downsampling IF signal before FM detection * (experiment) consider downsampling IF signal before FM detection
* (experiment) try if RTL AGC mode improves FM decoding
* (feature) support 'M' 'k' suffixes for sample rates and tuning frequency * (feature) support 'M' 'k' suffixes for sample rates and tuning frequency
* (feature) implement stereo pilot pulse-per-second * (feature) implement stereo pilot pulse-per-second
* (speedup) maybe replace high-order FIR downsampling filter with 2nd order butterworth followed by lower order FIR filter * (speedup) maybe replace high-order FIR downsampling filter with 2nd order butterworth followed by lower order FIR filter
* figure out why we sometimes lose stereo lock * figure out why we sometimes lose stereo lock
* it looks like IF level sometimes varies so much that it saturates the receiver; perhaps this can be solved by dynamically managing the hardware gain in response to level measurements
* (quality) figure out if hardware gain settings can improve weak stations
* (feature) implement RDS decoding * (feature) implement RDS decoding
* (quality) consider FM demodulation with PLL instead of phase discriminator * (quality) consider FM demodulation with PLL instead of phase discriminator

23
main.cc
View File

@ -217,6 +217,7 @@ void usage()
" -d devidx RTL-SDR device index, 'list' to show device list (default 0)\n" " -d devidx RTL-SDR device index, 'list' to show device list (default 0)\n"
" -s ifrate IF sample rate in Hz (default 1000000, min 900001)\n" " -s ifrate IF sample rate in Hz (default 1000000, min 900001)\n"
" -r pcmrate Audio sample rate in Hz (default 48000 Hz)\n" " -r pcmrate Audio sample rate in Hz (default 48000 Hz)\n"
" -a 0 Disable RTL AGC mode (default 1 = enabled)\n"
" -M Disable stereo decoding\n" " -M Disable stereo decoding\n"
" -R filename Write audio data as raw S16_LE samples\n" " -R filename Write audio data as raw S16_LE samples\n"
" use filename '-' to write to stdout\n" " use filename '-' to write to stdout\n"
@ -266,6 +267,7 @@ int main(int argc, char **argv)
string filename; string filename;
string alsadev("default"); string alsadev("default");
double bufsecs = -1; double bufsecs = -1;
int agcmode = 1;
fprintf(stderr, fprintf(stderr,
"SoftFM - Software decoder for FM broadcast radio with RTL-SDR\n"); "SoftFM - Software decoder for FM broadcast radio with RTL-SDR\n");
@ -275,6 +277,7 @@ int main(int argc, char **argv)
{ "dev", 1, NULL, 'd' }, { "dev", 1, NULL, 'd' },
{ "ifrate", 1, NULL, 's' }, { "ifrate", 1, NULL, 's' },
{ "pcmrate", 1, NULL, 'r' }, { "pcmrate", 1, NULL, 'r' },
{ "agc", 1, NULL, 'a' },
{ "mono", 0, NULL, 'M' }, { "mono", 0, NULL, 'M' },
{ "raw", 1, NULL, 'R' }, { "raw", 1, NULL, 'R' },
{ "wav", 1, NULL, 'W' }, { "wav", 1, NULL, 'W' },
@ -284,7 +287,7 @@ int main(int argc, char **argv)
int c, longindex; int c, longindex;
while ((c = getopt_long(argc, argv, while ((c = getopt_long(argc, argv,
"f:d:s:r:MR:W:P::b:", "f:d:s:r:MR:W:P::b:a:",
longopts, &longindex)) >= 0) { longopts, &longindex)) >= 0) {
switch (c) { switch (c) {
case 'f': case 'f':
@ -328,13 +331,24 @@ int main(int argc, char **argv)
badarg("-b"); badarg("-b");
} }
break; break;
case 'a':
if (!parse_opt(optarg, agcmode)) {
badarg("-a");
}
break;
default: default:
usage(); usage();
fprintf(stderr, "ERROR: Unknown option\n"); fprintf(stderr, "ERROR: Invalid command line options\n");
exit(1); exit(1);
} }
} }
if (optind < argc) {
usage();
fprintf(stderr, "ERROR: Invalid command line options\n");
exit(1);
}
vector<string> devnames = RtlSdrSource::get_device_names(); vector<string> devnames = RtlSdrSource::get_device_names();
if (devidx < 0 || (unsigned int)devidx >= devnames.size()) { if (devidx < 0 || (unsigned int)devidx >= devnames.size()) {
fprintf(stderr, "ERROR: invalid device index %d\n", devidx); fprintf(stderr, "ERROR: invalid device index %d\n", devidx);
@ -377,7 +391,8 @@ int main(int argc, char **argv)
} }
// Configure RTL-SDR device and start streaming. // Configure RTL-SDR device and start streaming.
rtlsdr.configure(ifrate, tuner_freq, -1); rtlsdr.configure(ifrate, tuner_freq, -1,
RtlSdrSource::default_block_length, agcmode);
if (!rtlsdr) { if (!rtlsdr) {
fprintf(stderr, "ERROR: RtlSdr: %s\n", rtlsdr.error().c_str()); fprintf(stderr, "ERROR: RtlSdr: %s\n", rtlsdr.error().c_str());
exit(1); exit(1);
@ -389,6 +404,8 @@ int main(int argc, char **argv)
ifrate = rtlsdr.get_sample_rate(); ifrate = rtlsdr.get_sample_rate();
fprintf(stderr, "IF sample rate %.0f Hz\n", ifrate); fprintf(stderr, "IF sample rate %.0f Hz\n", ifrate);
fprintf(stderr, "RTL AGC mode %s\n", agcmode ? "enabled" : "disabled");
// Create source data queue. // Create source data queue.
DataBuffer<IQSample> source_buffer; DataBuffer<IQSample> source_buffer;