rtl_sdr:可靠地检测频率变化,丢弃之前获得的样本

rtl_sdr: reliably detect frequency changes, discard samples obtained prior

我正在使用 rtl_sdr 和通用 DVB-T 棒(调谐器是 FC0013)为模拟 FM 收音机编写搜索例程。代码主要取自 rtl_power.crtl_fm.c.

我的做法是:

问题是我无法可靠地将样本映射到它们的收集频率。这是相关的(伪)代码片段:

/* freq is the new target frequency */
rtlsdr_cancel_async(dongle.dev);
optimal_settings(freq, demod.rate_in);
fprintf(stderr, "\nSeek: currently at %d Hz (optimized to %d).\n", freq, dongle.freq);
rtlsdr_set_center_freq(dongle.dev, dongle.freq);

/* get two bursts of samples to measure RSSI */
if (rtlsdr_read_sync(dongle.dev, samples, samplesSize, &samplesRead) < 0)
    fprintf(stderr, "\nSeek: rtlsdr_read_sync failed\n");
/* rssi = getRssiFromSamples(samples, samplesRead) */
fprintf(stderr, "\nSeek: rssi=%.2f", rssi);

if (rtlsdr_read_sync(dongle.dev, samples, samplesSize, &samplesRead) < 0)
    fprintf(stderr, "\nSeek: rtlsdr_read_sync failed\n");
/* rssi = getRssiFromSamples(samples, samplesRead) */
fprintf(stderr, "\nSeek: rssi=%.2f\n", rssi);

当我使用该代码片段扫描 FM 波段时,我发现两个 RSSI 测量值通常有很大差异。特别是,第一次测量通常在从先前频率获取的第二次测量的附近,表明一些样本是在仍调谐到旧频率时获取的。

我还尝试在收集样本之前插入对 rtlsdr_reset_buffer() 的调用,以努力冲洗仍卡在管道中的所有样本,但没有明显效果。甚至

的组合
usleep(500000);
rtlsdr_cancel_async(dongle.dev);
rtlsdr_reset_buffer(dongle.dev)

除了 usleep() 显着减慢搜索操作外,不会更改图片。 (缓冲区大小为 16384 个样本,采样率为 200 万,因此 usleep() 延迟远高于获得一个样本突发所需的时间。)

如何确保在调谐到新频率后获得我采集的样本?

再次查看rtl_power.c的代码,我发现了这个函数:

void retune(rtlsdr_dev_t *d, int freq)
{
    uint8_t dump[BUFFER_DUMP];
    int n_read;
    rtlsdr_set_center_freq(d, (uint32_t)freq);
    /* wait for settling and flush buffer */
    usleep(5000);
    rtlsdr_read_sync(d, &dump, BUFFER_DUMP, &n_read);
    if (n_read != BUFFER_DUMP) {
        fprintf(stderr, "Error: bad retune.\n");}
}

从本质上讲,调谐器需要稳定下来,没有明显的迹象表明此过程何时完成。

rtl_power.c 通过等待 5 毫秒解决此问题,然后丢弃一些样本(BUFFER_DUMP 定义为 4096,采样率在 1–2.8M 之间)。

我发现 4096 个样本不够,所以我选择了最大值 16384。这样结果看起来更稳定,尽管即使这样似乎也并不总是足以让调谐器稳定。

对于波段扫描,另一种方法是循环获取样本并确定它们的 RSSI,直到 RSSI 值开始稳定,即变化不再单调或低于某个阈值。