在软件中收听 FM 收音机,逐步指南

作者:Eric Blossom

我的文章 “GNU Radio:探索射频频谱的工具” [LJ,2004 年 6 月] 概述了 GNU Radio 系统的工作原理,并讨论了将 RF 信号数字化并输入计算机的几种硬件选项。本文着眼于如何使用 GNU Radio 收听 FM 收音机。

本文中使用的硬件设置如图 1 所示。这是一种简单直接、朴实无华的方法,非常适合解释一切如何工作。在本文的后面,我们将讨论通用软件无线电外围设备 (USRP) 及其可以为您做些什么。

Listening to FM Radio in Software, Step by Step

图 1. 有线电视调制解调器调谐器 RF 前端

我们的设置包括一个传统的 FM 偶极天线、一个安装在评估板上的有线电视调制解调器调谐器模块和一个 20M 采样/秒 PCI 模数转换器 (ADC) 卡。天线插入调谐器模块的输入端。调谐器模块的 IF 输出通过一段同轴电缆连接到计算机背面的 ADC 输入端。调谐器模块评估板连接到 PC 的并行端口,以便我们可以控制该模块。

我们正在使用的特定硬件是 Microtune 4937 DI5 3X7702 有线电视调制解调器调谐器模块和 Measurement Computing PCI-DAS 4020/12 ADC 板。这种特定的调谐器模块很难获得,但其他模块,例如 Sharp Microelectronics 的模块,应该也能正常工作(请参阅在线资源部分)。

有线电视调制解调器调谐器充当我们的 RF 前端,负责将我们感兴趣的射频信号转换为我们的 ADC 可以处理的范围。在本例中,该模块将 50MHz–800MHz 范围内的可选 6MHz 频谱块转换为以 5.75MHz 为中心的 6MHz 频谱块。有关这些概念的更多背景知识,请参阅前面提到的 6 月份的文章。

入门指南

首先,让我们看一下当我们把前端调谐到 FM 频段的中间,比如 100.1MHz 时会发生什么。图 2 显示了接收到的样本与时间的关系。这种视图,即时域,是您在示波器上看到的。它并没有特别启发意义,但它确实表明我们的样本范围在 -170 到 -70 之间,这很好。在理想世界中,它们应该关于零对称。对于我们的目的来说,偏移量无关紧要。

Listening to FM Radio in Software, Step by Step

图 2. 时域中的 ADC 样本

频域提供了额外的信息。在本例中,我们一次抓取 1,024 个样本,并使用快速傅里叶变换 (FFT) 算法计算离散傅里叶变换。这为我们提供了输入信号中包含的频率的表示。图 3 显示了结果频谱。x 轴是频率,y 轴是功率,单位为分贝(10 * log10 功率)。低端为零 Hz,高端为 10MHz,是我们采样率的一半。

Listening to FM Radio in Software, Step by Step

图 3. 包含九个电台的 FM 频段的快速傅里叶变换

图 3 中的每个尖峰都是一个广播电台。我们的软件一次性看到了所有这些电台!要收听某个电台,我们需要一种方法将其与其他所有电台分离,将其转换为基带(DC,0Hz),并反转频率调制的效果。我们将逐步完成此操作,但首先让我们谈谈 FM。

什么是频率调制?

为了理解 FM 接收器的工作原理,了解一些 FM 信号是如何生成的会很有帮助。对于 FM,发射波形的瞬时频率随着输入信号的函数而变化。图 4 显示了 m(t),输入信号(消息、音乐等),以及 s(t),结果调制输出。严格来说,任何时刻的瞬时频率由以下公式给出

f(t) = k*m(t) + fc

m(t) 是输入信号,k 是控制频率灵敏度的常数,fc 是载波频率(例如,100.1MHz)。请记住,频率的单位是弧度/秒。因此,频率可以被认为是某物旋转的速率。如果我们对频率积分,我们得到相位或角度。反之,对相位求时间导数得到频率。这些是我们用来构建接收器的关键见解。

Listening to FM Radio in Software, Step by Step

图 4. 一个简单的频率调制信号

框图

图 5 显示了我们收听 FM 电台的策略。如果我们移除载波,我们就留下了一个基带信号,该信号的瞬时频率与原始消息 m(t) 成正比。因此,我们的挑战是找到一种方法来移除载波并计算瞬时频率。

Listening to FM Radio in Software, Step by Step

图 5. FM 接收器框图

第一部分很容易。我们通过使用我们的软件数字下变频器 (DDC) 模块 freq_xlating_fir_filter_scf 来消除载波。从概念上讲,该模块由一个数控振荡器组成,该振荡器在我们想要转换为零的频率下生成正弦波和余弦波形,一个混频器(对于我们这些软件人员来说是一个乘法器)和一个抽取有限脉冲响应滤波器。后缀 scf 表示该模块在其输入端接收短路流,在其输出端产生复数流,并使用浮点抽头来指定滤波器。

数字下变频器的工作原理是利用三角恒等式,该恒等式表明,当您将频率为 f1 和 f2 的两个正弦波相乘时,结果由两个新的正弦波组成,一个在 f1+f2,另一个在 f1–f2。在我们的例子中,我们将输入信号乘以载波频率。输出由两个分量组成,一个在 2x 载波处,另一个在零处。我们用低通滤波器消除 2x 分量,留下基带信号。

MIPS 是我们的强项!

在软件中直接实现数字下变频器模块在计算上非常昂贵。我们将以完整的输入速率执行正弦和余弦生成和乘法运算。在奔腾 4 上,计算正弦和余弦大约需要 150 个周期。给定 20M 采样/秒的输入流,我们仅计算正弦和余弦就会消耗 20e6 * 150 = 3e9 周期/秒!这绝对是不可行的。

好消息是,有一种更好的方法可以在软件中实现 DDC。Vanu Bose 等人在 “虚拟无线电” (见资源)中描述的这项技术允许我们通过重新排列操作顺序并使用特定于频率的复数滤波器系数而不是实数系数,以抽取后的速率运行所有计算。最终结果是巨大的胜利!我们可以实时完成它!

正交解调

下一个任务是计算基带信号的瞬时频率。我们使用 quadrature_demod_cf 模块来实现这一点。我们通过确定相邻样本之间的角度来近似微分相位。回想一下,下变频器模块在其输出端产生复数。使用更多的三角学知识,我们可以通过将一个样本乘以另一个样本的复共轭,然后取乘积的反正切来确定两个后续样本之间的角度。列表 1 和 2 显示了 quadrature_demod_cf 模块的实现。一旦您知道您想要什么,就不需要太多代码。信号处理的大部分是 sync_work 中的三行循环。

列表 1. 正交解调器头文件

/*
 * Copyright 2004 Free Software Foundation, Inc.
 *
 * This file is part of GNU Radio
 *
 * GNU Radio is free software; you can redistribute
 * it and/or modify it under the terms of the GNU
 * General Public License as published by the Free
 * Software Foundation; either version 2, or (at
 * your option) any later version.
 */

#ifndef INCLUDED_GR_QUADRATURE_DEMOD_CF_H
#define INCLUDED_GR_QUADRATURE_DEMOD_CF_H

#include <gr_sync_block.h>

class gr_quadrature_demod_cf;
typedef boost::shared_ptr<gr_quadrature_demod_cf>
  gr_quadrature_demod_cf_sptr;

gr_quadrature_demod_cf_sptr
gr_make_quadrature_demod_cf (float gain);

/*
 * quadrature demodulator: complex in, float out
 */
class gr_quadrature_demod_cf : public gr_sync_block
{
  friend gr_quadrature_demod_cf_sptr
    gr_make_quadrature_demod_cf (float gain);
  gr_quadrature_demod_cf (float gain);

  float         d_gain;

 public:

  int sync_work (
        int noutput_items,
        gr_vector_const_void_star &input_items,
        gr_vector_void_star &output_items);
};

#endif /* INCLUDED_GR_QUADRATURE_DEMOD_CF_H */

列表 2. 正交解调器实现

/*
 * Copyright 2004 Free Software Foundation, Inc.
 *
 * This file is part of GNU Radio
 *
 * GNU Radio is free software; you can redistribute
 * it and/or modify it under the terms of the GNU
 * General Public License as published by the Free
 * Software Foundation; either version 2, or (at
 * your option) any later version.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gr_quadrature_demod_cf.h>
#include <gr_io_signature.h>

gr_quadrature_demod_cf::gr_quadrature_demod_cf (
                                         float gain)
  : gr_sync_block (
       "quadrature_demod_cf",
      gr_make_io_signature(1,1,sizeof (gr_complex)),
      gr_make_io_signature(1,1,sizeof (float))),
    d_gain (gain)
{
  set_history (2);    // provide 1 sample look ahead
}

gr_quadrature_demod_cf_sptr
gr_make_quadrature_demod_cf (float gain)
{
  return gr_quadrature_demod_cf_sptr (
      new gr_quadrature_demod_cf (gain));
}

int
gr_quadrature_demod_cf::sync_work (
    int noutput_items,
    gr_vector_const_void_star &input_items,
    gr_vector_void_star &output_items)
{
  gr_complex *in = (gr_complex *) input_items[0];
  float *out = (float *) output_items[0];
  in++;         // ensure that in[-1] is valid

  for (int i = 0; i < noutput_items; i++){
    gr_complex product = in[i] * conj (in[i-1]);
    out[i] = d_gain * arg (product);
  }

  return noutput_items;
}

将所有这些结合在一起,图 6 显示了数字下变频器的输出,图 7 显示了正交解调器的输出。在图 7 中,您可以看到 FM 波形的所有组成部分。从 0 到大约 16kHz 是左声道加右声道 (L+R) 音频。19kHz 处的峰值是立体声导频音。左声道减右声道 (L-R) 立体声信息以导频音的 2 倍 (38kHz) 为中心,并在 FM 之上进行 AM 调制。在 57kHz–96kHz 区域有时会发现额外的副载波。

Listening to FM Radio in Software, Step by Step

图 6. 数字下变频器输出端的 FFT

Listening to FM Radio in Software, Step by Step

图 7. 解调 FM 信号的 FFT

为了简化生活,我们使用截止频率为 16kHz 的低通滤波器对正交解调器的输出进行低通滤波。这为我们提供了单声道输出,我们将其连接到声卡输出。

多通道接收器

列表 3,可从 Linux Journal FTP 站点获得(请参阅资源),是实现整体接收器的 Python 代码。事实上,它可以同时收听两个 FM 电台,一个从左扬声器输出,另一个从右扬声器输出!我并不是说这是一个特别实际的应用,但它确实说明了软件无线电的一些强大功能。这种同时提取多个电台的想法可以用作无线电的类似 TiVo 的多通道设备的基础。

代码分为三个函数。main 函数处理参数解析,管理 RF 前端,并控制主信号处理循环。如果我们接收单个电台,我们会告诉 RF 前端将电台放在调谐器输出频率的中心,即 IF。如果我们接收两个电台,我们确保它们彼此在 5.5MHz 以内。这种限制是由于有线电视调制解调器调谐器中内置的 SAW 滤波器造成的。它是一个以 5.75MHz 为中心的带通滤波器,带宽约为 6MHz,即北美电视频道的宽度。在这种情况下,我们平分差值,并将前端精确地调谐到两个电台的中间。

不止一种方法!

可以同时接收的最大电台数量是计算机速度的函数。即使使用我们精巧的实现,大多数 CPU 周期仍然在 freq_xlating_fir_filter 模块中消耗。我们所描述的可以称为哑 ADC/蛮力方法。释放计算资源的一种方法是将数字下变频移到硬件中。德州仪器、Intersil 和模拟器件等公司销售专门的 ASIC 来执行此操作。通用软件无线电外围设备 (USRP) 中使用的策略是在 Verilog 硬件描述语言中编写数字下变频器代码,然后通过 USB 将生成的比特流下载到 FPGA 中。这为我们提供了一个硬件/软件组合系统,该系统最大限度地提高了灵活性,同时仍然允许我们将一些计算密集型部分卸载到硬件中。有关 USRP 的更多信息,请参阅 GNU Radio Wiki。

总结

我们已经逐步了解了一个功能齐全但精简的多通道 FM 接收器。我们设法将价值数千美元的硬件变成了相当于两台 5 美元的晶体管收音机,并且在此过程中学到了很多东西。对于那些有兴趣追求 FM 收听的人来说,GNU Radio 代码库包括一个更高保真度的 FM 接收器 (hifi_fm.py),以及各种其他好东西。

目前,GNU Radio 正在进行许多有趣的工作。有些人专注于移动自组织网络,另一些人专注于传统的业余无线电波形,一些人专注于软件 GPS,另一组人正在设计下一代地面到空间的业余卫星通信系统。虽然 GNU Radio 工具包对 I/O 设备大多漠不关心,但这些努力中的大多数都在使用或计划使用 USRP 作为 RF 世界和 PC 之间的接口。

本文的资源: /article/7650

Eric Blossom 是 GNU Radio 项目的创始人。在参与软件无线电之前,他曾在安全电话业务领域工作多年。当他不编写软件无线电程序时,您很可能会发现他在练习瑜伽或柔术。可以通过 eb@comsec.com 联系到他。

加载 Disqus 评论