kopia lustrzana https://github.com/keenerd/rtl-sdr
rtl_test: generic tuner range test
This scans 0 - 3GHz looking for frequencies that can be tuned to without error, and refines the band edges further once a tuneable band is found. It should work with any tuner that correctly reports tuning errors. It takes about 1.5 minutes to complete on a R820T.squashed
rodzic
6ea7023be1
commit
9d706f7e1c
229
src/rtl_test.c
229
src/rtl_test.c
|
@ -76,7 +76,7 @@ void usage(void)
|
||||||
"Usage:\n"
|
"Usage:\n"
|
||||||
"\t[-s samplerate (default: 2048000 Hz)]\n"
|
"\t[-s samplerate (default: 2048000 Hz)]\n"
|
||||||
"\t[-d device_index (default: 0)]\n"
|
"\t[-d device_index (default: 0)]\n"
|
||||||
"\t[-t enable E4000 or R820T tuner range benchmark]\n"
|
"\t[-t enable tuner range benchmark]\n"
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
"\t[-p[seconds] enable PPM error measurement (default: 10 seconds)]\n"
|
"\t[-p[seconds] enable PPM error measurement (default: 10 seconds)]\n"
|
||||||
#endif
|
#endif
|
||||||
|
@ -221,78 +221,160 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void e4k_benchmark(void)
|
/* smallest band or band gap that tuner_benchmark() will notice */
|
||||||
{
|
static uint32_t max_step(uint32_t freq) {
|
||||||
uint32_t freq, gap_start = 0, gap_end = 0;
|
if (freq < 1e6)
|
||||||
uint32_t range_start = 0, range_end = 0;
|
return 1e4;
|
||||||
|
if (freq > 1e8)
|
||||||
fprintf(stderr, "Benchmarking E4000 PLL...\n");
|
return 1e6;
|
||||||
|
return freq / 1e2;
|
||||||
/* find tuner range start */
|
|
||||||
for (freq = MHZ(70); freq > MHZ(1); freq -= MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq) < 0) {
|
|
||||||
range_start = freq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find tuner range end */
|
|
||||||
for (freq = MHZ(2000); freq < MHZ(2300UL); freq += MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq) < 0) {
|
|
||||||
range_end = freq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find start of L-band gap */
|
|
||||||
for (freq = MHZ(1000); freq < MHZ(1300); freq += MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq) < 0) {
|
|
||||||
gap_start = freq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find end of L-band gap */
|
|
||||||
for (freq = MHZ(1300); freq > MHZ(1000); freq -= MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq) < 0) {
|
|
||||||
gap_end = freq;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "E4K range: %i to %i MHz\n",
|
|
||||||
range_start/MHZ(1) + 1, range_end/MHZ(1) - 1);
|
|
||||||
|
|
||||||
fprintf(stderr, "E4K L-band gap: %i to %i MHz\n",
|
|
||||||
gap_start/MHZ(1), gap_end/MHZ(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void r820t_benchmark(void)
|
/* precision with which tuner_benchmark() will measure the edges of bands */
|
||||||
{
|
static uint32_t min_step(uint32_t freq) {
|
||||||
uint32_t freq;
|
return 100;
|
||||||
uint32_t range_start = 0, range_end = 0;
|
|
||||||
|
|
||||||
fprintf(stderr, "Benchmarking R820T PLL...\n");
|
|
||||||
|
|
||||||
/* find tuner range start */
|
|
||||||
for (freq = MHZ(30); freq > MHZ(1); freq -= MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq)) {
|
|
||||||
break;}
|
|
||||||
range_start = freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find tuner range end */
|
|
||||||
for (freq = MHZ(1750); freq < MHZ(1950UL); freq += MHZ(1)) {
|
|
||||||
if (rtlsdr_set_center_freq(dev, freq)) {
|
|
||||||
break;}
|
|
||||||
range_end = freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "R820T range: %i to %i MHz\n",
|
|
||||||
range_start/MHZ(1), range_end/MHZ(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void report_band_start(uint32_t start) {
|
||||||
|
fprintf(stderr, "Found a new band starting at %u Hz\n", start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void report_band(uint32_t low, uint32_t high) {
|
||||||
|
fprintf(stderr, "Tuning band: %u - %u Hz\n", low, high);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tuner_benchmark(void)
|
||||||
|
{
|
||||||
|
uint32_t current = max_step(0);
|
||||||
|
uint32_t band_start = 0;
|
||||||
|
uint32_t low_bound = 0, high_bound = 0;
|
||||||
|
char buf[20];
|
||||||
|
enum { FIND_START, REFINE_START, FIND_END, REFINE_END } state;
|
||||||
|
|
||||||
|
fprintf(stderr, "Testing tuner range. This may take a couple of minutes..\n");
|
||||||
|
|
||||||
|
/* Scan for tuneable frequencies coarsely. When we find something,
|
||||||
|
* do a binary search to narrow down the exact edge of the band.
|
||||||
|
*
|
||||||
|
* This can potentially miss bands/gaps smaller than max_step(freq)
|
||||||
|
* but it is a lot faster than exhaustively scanning everything.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* handle bands starting at 0Hz */
|
||||||
|
if (rtlsdr_set_center_freq(dev, 0) < 0)
|
||||||
|
state = FIND_START;
|
||||||
|
else {
|
||||||
|
band_start = 0;
|
||||||
|
report_band_start(band_start);
|
||||||
|
state = FIND_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (current < 3e9 && !do_exit) {
|
||||||
|
switch (state) {
|
||||||
|
case FIND_START:
|
||||||
|
/* scanning for the start of a new band */
|
||||||
|
if (rtlsdr_set_center_freq(dev, current) < 0) {
|
||||||
|
/* still looking for a band */
|
||||||
|
low_bound = current;
|
||||||
|
current += max_step(current);
|
||||||
|
} else {
|
||||||
|
/* new band, starting somewhere at or before current */
|
||||||
|
/* low_bound < start <= current */
|
||||||
|
high_bound = current;
|
||||||
|
state = REFINE_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REFINE_START:
|
||||||
|
/* refining the start of a band */
|
||||||
|
/* low_bound < bandstart <= high_bound */
|
||||||
|
if (rtlsdr_set_center_freq(dev, current) == 0) {
|
||||||
|
/* current is inside the band */
|
||||||
|
/* low_bound < bandstart <= current */
|
||||||
|
if (current - low_bound <= min_step(current)) {
|
||||||
|
/* start found at low_bound */
|
||||||
|
band_start = current;
|
||||||
|
report_band_start(band_start);
|
||||||
|
low_bound = current;
|
||||||
|
current = band_start + max_step(band_start);
|
||||||
|
state = FIND_END;
|
||||||
|
} else {
|
||||||
|
/* binary search */
|
||||||
|
high_bound = current;
|
||||||
|
current = (current + low_bound) / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* current is outside the band */
|
||||||
|
/* current < bandstart <= high_bound */
|
||||||
|
if (high_bound - current <= min_step(current)) {
|
||||||
|
/* start found at high_bound */
|
||||||
|
low_bound = band_start = high_bound;
|
||||||
|
report_band_start(band_start);
|
||||||
|
current = band_start + max_step(band_start);
|
||||||
|
state = FIND_END;
|
||||||
|
} else {
|
||||||
|
/* binary search */
|
||||||
|
low_bound = current;
|
||||||
|
current = (current + high_bound) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FIND_END:
|
||||||
|
/* scanning for the end of the current band */
|
||||||
|
if (rtlsdr_set_center_freq(dev, current) == 0) {
|
||||||
|
/* still looking for the end of the band */
|
||||||
|
low_bound = current;
|
||||||
|
current += max_step(current);
|
||||||
|
} else {
|
||||||
|
/* end found, coarsely */
|
||||||
|
/* low_bound <= bandend < current, refine it */
|
||||||
|
high_bound = current;
|
||||||
|
state = REFINE_END;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REFINE_END:
|
||||||
|
/* refining the end of a band */
|
||||||
|
/* low_bound <= bandend < high_bound */
|
||||||
|
if (rtlsdr_set_center_freq(dev, current) < 0) {
|
||||||
|
/* current is outside the band */
|
||||||
|
/* low_bound <= bandend < current */
|
||||||
|
if (current - low_bound <= min_step(current)) {
|
||||||
|
/* band ends at low_bound */
|
||||||
|
report_band(band_start, low_bound);
|
||||||
|
low_bound = current;
|
||||||
|
current = low_bound + max_step(low_bound);
|
||||||
|
state = FIND_START;
|
||||||
|
} else {
|
||||||
|
/* binary search */
|
||||||
|
high_bound = current;
|
||||||
|
current = (current + low_bound) / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* current is inside the band */
|
||||||
|
/* current <= bandend < high_bound */
|
||||||
|
if (high_bound - current <= min_step(current)) {
|
||||||
|
/* band ends at high_bound */
|
||||||
|
report_band(band_start, current);
|
||||||
|
low_bound = high_bound;
|
||||||
|
current = low_bound + max_step(low_bound);
|
||||||
|
state = FIND_START;
|
||||||
|
} else {
|
||||||
|
/* binary search */
|
||||||
|
low_bound = current;
|
||||||
|
current = (current + high_bound) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == FIND_END)
|
||||||
|
report_band(band_start, current);
|
||||||
|
else if (state == REFINE_END)
|
||||||
|
report_band(band_start, low_bound);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -387,16 +469,7 @@ int main(int argc, char **argv)
|
||||||
verbose_set_sample_rate(dev, samp_rate);
|
verbose_set_sample_rate(dev, samp_rate);
|
||||||
|
|
||||||
if (test_mode == TUNER_BENCHMARK) {
|
if (test_mode == TUNER_BENCHMARK) {
|
||||||
switch (rtlsdr_get_tuner_type(dev)) {
|
tuner_benchmark();
|
||||||
case RTLSDR_TUNER_E4000:
|
|
||||||
e4k_benchmark();
|
|
||||||
break;
|
|
||||||
case RTLSDR_TUNER_R820T:
|
|
||||||
r820t_benchmark();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "No testable tuner found, aborting.\n");
|
|
||||||
}
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue