ソフトウェア無線
ソフトウェア無線がRFをホスト上の複素サンプルに変換する仕組み、その上にあるドライバ層とフレームワーク層、サンプルレートの選び方、SigMFによるIQの記録と再生を解説します。
概要
ソフトウェア無線(SDR)は、従来の無線機が固定のアナログ回路で行っていた処理をソフトウェアで行います。ハードウェアは、RFと複素ベースバンドサンプルのストリームとの間で変換を行います。フィルタリングから復調・復号まで、それ以降の処理はすべて汎用プロセッサ、FPGA、またはその両方で実行します。Joseph Mitolaは、このアーキテクチャをThe software radio architecture(IEEE Communications Magazine、1995年)で示しました。現在では、受信専用のUSBドングルからFPGAを搭載したマルチチャネル無線機まで、同じ考え方が使われています。
このハブは、実機で波形を受信・送信・記録したり、試作したりしたいエンジニアを対象としています。当サイトのレッスンの多くも、SDRを通じて実際の電波につながります。NumPyでシミュレーションした変調方式は、コードをほとんど変えずに実機の無線機に通せます。
重要な考え方
信号チェーンとソフトウェアが始まる位置
一般的なSDRは、RFフロントエンド(フィルタ、低雑音増幅器(LNA)、ミキサ、局部発振器)、1対の変換器、FPGA、ホストへのリンクで構成されます。FPGAは通常、デジタルダウンコンバージョンと間引きを行います。これにより、ホストリンクが運ぶのは指定した帯域幅の分だけになります。ホスト側には、選択したレートと中心周波数のIQサンプルが届きます。
ハードウェアの種類は多岐にわたります。RTL-SDR Blog V4は受信専用のドングルです。データシートによれば、500 kHzから1.766 GHzまでをカバーし、8 ビットのRTL2832U変換器と2.56 MHzの安定したサンプルレートを備えます。USRP B210は、Ettus Researchの製品ページによれば、70 MHzから6 GHzまでをカバーし、最大56 MHzの瞬時帯域幅と送信2チャネル・受信2チャネルをUSB 3.0経由で提供します。このページはAD9361トランシーバを挙げていますが、変換器のビット数は記載していません。ほかのデバイスとの比較はハードウェア表を参照してください。
ドライバとフレームワーク
ハードウェアのファミリーごとに専用のドライバがあります。UHD(ホスト側コードはGPL-3.0)はUSRPシリーズを駆動します。libiio(LGPL-2.1)は、Linux IIOフレームワークを使うAnalog Devicesのデバイスを駆動します。SoapySDR(Boost Software License 1.0)はベンダー非依存の層で、多くのデバイス向けのモジュールを備えています。そのため、1つのプログラムで引数文字列を変えるだけで異なる無線機を開けます。
GNU Radio(GPL-3.0)は、多くのエンジニアが最初に使うフレームワークです。フローグラフはブロックを接続し、スケジューラがブロック間でサンプルバッファを受け渡します。当サイトのコードはGNU Radio 3.10.12で動作します。GNU Radio 4.0は全面的な書き直しです。プロジェクトのニュースページによれば、その3番目のリリース候補は2026年10月13日に公開されました。
サンプルレート、帯域幅、ホストリンク
レートfsで複素サンプリングすると、同調周波数を中心に−fs/2から+fs/2までの幅fsのスペクトラムが見えます。無駄になる負周波数の鏡像が別に生じないため、実サンプリングではなく複素サンプリングが標準です。fsは信号帯域幅より少し高めに選び、残りはデジタルフィルタに任せてください。レートが高すぎると、CPUとリンク容量を消費します。低すぎると、隣接する信号が帯域内にエイリアシングで折り返します。
計算は単純ですが、よく忘れられます。complex64のサンプル1個は8 バイトなので、ホスト上で20 MS/sなら、処理を始める前の時点で160 MB/sのメモリトラフィックになります。ホストが追いつかないと、ドライバはサンプルを取りこぼし、オーバーフローを報告します。測定値を信用する前に、オーバーフローの有無を確認してください。
IQの記録と再生
生のIQを記録しておけば、1回のキャプチャを何度でも解析したり、同僚と共有したり、シールドした環境で送信機から再生したりできます。.binファイル単体では情報が足りません。1か月後には、サンプルレートも中心周波数もサンプル形式も誰にもわかりません。SigMFは、データファイルとJSONメタデータファイルの組でこの問題を解決します。仕様のライセンスはCC BY-SA 4.0で、リポジトリの例ではバージョン1.2.0を使っています。
次のコードは、合成したトーンをSigMFのファイル対として書き出し、読み戻してトーンを検出します。無線機は不要です。
import json
from pathlib import Path
import numpy as np
rng = np.random.default_rng(7)
fs = 1_000_000.0 # sample rate, Hz
n = 100_000
t = np.arange(n) / fs
# complex64 baseband: a tone 125 kHz above the centre frequency plus noise
iq = np.exp(2j * np.pi * 125e3 * t) + 0.05 * (rng.standard_normal(n) + 1j * rng.standard_normal(n))
iq = iq.astype(np.complex64)
base = Path("tone_capture")
iq.tofile(base.with_suffix(".sigmf-data")) # interleaved little-endian float32 I, Q
meta = {
"global": {"core:datatype": "cf32_le", "core:sample_rate": fs, "core:version": "1.2.0",
"core:description": "synthetic tone, 125 kHz offset"},
"captures": [{"core:sample_start": 0, "core:frequency": 433.92e6}],
"annotations": [],
}
base.with_suffix(".sigmf-meta").write_text(json.dumps(meta, indent=2))
# read it back the way any other tool would
m = json.loads(base.with_suffix(".sigmf-meta").read_text())
x = np.fromfile(base.with_suffix(".sigmf-data"), dtype=np.complex64)
spec = np.fft.fftshift(np.abs(np.fft.fft(x[:4096])))
freqs = np.fft.fftshift(np.fft.fftfreq(4096, 1 / m["global"]["core:sample_rate"]))
peak_hz = freqs[np.argmax(spec)]
rf_hz = m["captures"][0]["core:frequency"] + peak_hz
print(f"{x.size} samples, {x.nbytes} bytes, peak at {peak_hz / 1e3:.1f} kHz offset = {rf_hz / 1e6:.4f} MHz RF")
実行すると100000 samples, 800000 bytes, peak at 125.0 kHz offset = 434.0450 MHz RFと表示されます。
どこから始めるか
まず、サンプルの意味を説明する複素ベースバンドとIQから始めてください。次に初めてのGNU Radioフローグラフを作り、IQの記録と読み込みに取り組みます。GNU Radio FM受信機プロジェクトで、これらの要素を組み合わせます。SDRにおけるFPGA側の信号処理については、FPGA GuideのワイヤレスとSDRのハブがあります。
ツールとプラットフォーム
| ツール | 用途 | ライセンス |
|---|---|---|
| GNU Radio | 信号処理と無線機制御のためのフローグラフ・フレームワーク | GPL-3.0 |
| UHD | USRP無線機用のドライバとAPI | GPL-3.0(ホスト側コード) |
| SoapySDR | デバイスモジュールを備えたベンダー非依存のSDR API | Boost Software License 1.0 |
| libiio | Analog Devices IIOデバイス用のドライバライブラリ | LGPL-2.1 |
| SigMF | IQ記録用のメタデータ形式 | CC BY-SA 4.0 |
プラットフォームのハブ: GNU Radio、NI・Ettus Research、Analog Devices、オープンソースツール。バージョンと対応OSの一覧はソフトウェア一覧表を参照してください。
よくある間違い
- サンプルレートを信号帯域幅と同じ値に設定し、フィルタのロールオフ分の余裕を残さない。
- 直接変換方式のフロントエンドに特有のDCスパイクとIQインバランスを無視する。信号から少しずらして同調し、デジタル処理で周波数をシフトする。
- IQをメタデータなしで保存し、後で形式を推測する羽目になる。
- ファイルの読み込み時に、int16、float32、8 ビット符号なしのサンプル形式を取り違える。
- ドライバがサンプルの取りこぼしやオーバーフローを報告していないか確認しない。
- 免許なしで、または許可された帯域の外で送信する。送信試験にはケーブル、減衰器、シールドボックスを使う。
- 受信機を過入力にする。近くの強い信号がフロントエンドを飽和させ、本物の信号に見えるスプリアスを生む。
さらに深く
- Mitola、The software radio architecture、IEEE Communications Magazine、1995年。
- GNU Radioプロジェクトのサイト。リリースノートとドキュメントへのリンクがあります。
- Ettus ResearchのUHDマニュアル。
- SigMF仕様のリポジトリ。