RTL-SDR 無改造でダイレクトサンプリング
大元の話は reddit.com のこの話
A Very Surprising Discovery (self.RTLSDR)
チューナーに対し3686.6MHzというような周波数を指示すると、ローカル発振が止まって RF側の信号が筒抜けて来てダイレクトサンプリング状態になるということらしい。
この話 E4000 チューナに限った話だと思っていたのだが
R820Tチューナでも無改造でダイレクトサンプリングができるらしい
rtl-sdr and GNU Radio w/Realtek RTL2832U, E4000 and R820Tの "High Frequency (0-30Mhz) Direct Sampling Mod" の"No hardware change, software mod direct sampling" の項に
... (R820T IF frequency, IF filter bandwidths, ?, etc) ...
とあるのが目に付いた。
2014年 1月に IRCチャンネルにて tejeezという人がチューナーをバイパスするようなレジスタ設定を見つけ出したとか何とか。
直後にあるGitHubリポジトリ(RTL-SDR experimental branch)へのリンクをたどって、変更履歴をみてみると、1/26のコミットで src/tuner_r82xx.cに r82xx_set_nomod(struct r82xx_priv *priv)なる関数が追加されていたりする。
src/librtlsdr.c の rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on) の on に 3を渡すと呼ばれるようだ。
rtl_fm コマンドに対しては
-E no-modrtl_sdr, rtl_power コマンドに対しては
-D 3のようにオプション指定してやると、このモードが使われるような修正が入っている(ソース見ただけで未確認)。
とりあえず SDR# から使ってみたい
いつもSDR# から rtl_tcp 越しに使っているのだが、これを試すにはどうしよう? SDR#に手を入れるのはメンドクサすぎるので、rtl_tcp を修正してみよう。この間 APC でコンパイルしてみたことだし。
340行目付近に
printf("set direct sampling %d\n", ntohl(cmd.param));
rtlsdr_set_direct_sampling(dev, ntohl(cmd.param));
とダイレクトサンプリングモード設定を呼び出しているところがあるので、"3" に固定してみる
printf("set direct sampling %d\n",3);
rtlsdr_set_direct_sampling(dev, 3);
こんな具合。
たしかに HFが受信できる
ラジオNIKKEI(3.925MHz, 6.055MHz)が受信できるのは確認したが、もっと低い方の中波や高い周波数のほうはダメのようだ。
アンテナがどうしようもない状態なので本当にダメなのかはわからない。
rtl_tcp をAPC で動かそうと思ったら Raspbery Piでも動かなくなっていた
APCにインストールした Apricot-R5 は Raspbianとおなじなので、Raspberry Piと同じことをすればよいハズ。
rtl_tcp などのビルド/インストール
rtl-sdr – OsmoSDR の Software の項にあるので、従えばよい。
ビルドに必要なパッケージのインストールをしておいて
# apt-get install git cmake install autoconf libtool libusb-1.0-0-dev
ソースを持ってくる
# git clone git://git.osmocom.org/rtl-sdr.git
で、ビルドする。
APC/Apricot では autoconf を使うとなぜか libusb の場所などを誤解するようなので cmake を使った。
# cd rtl-sdr/
# mkdir build
# cd build
# cmake ../ -DINSTALL_UDEV_RULES=ON
# make
# make install
# ldconfig
これでよさそう。
でも、ハマッた
rtl_tcpを実行すると
Found 1 device(s): 0: Generic RTL2832U OEM Using device 0: Generic RTL2832U OEM Kernel driver is active, or device is claimed by second instance of librtlsdr. In the first case, please either detach or blacklist the kernel module (dvb_usb_rtl28xxu), or enable automatic detaching at compile time. usb_claim_interface error -6 Failed to open rtlsdr device #0.
とはいたあとに、kernelが Bug! メッセージを出して、以降どうにもならなくなった。
Raspberry Pi の方でも試してみる
Raspberry Piの方ではどうか確認してみたところ、同じメッセージを出して動かない。
ただし kernelの Bugメッセージは出ない。
むむむ。
最近の linux kernel には DVBドライバが入っていて衝突する
ということらしい。
http://www.hamradioscience.com/raspberry-pi-as-remote-server-for-rtl2832u-sdr/のコメントを追っていくと、解決策があった
/etc/modeprobe.d/以下に blacklistを置いて DVBドライバを読まないようにするということだ。
blacklist をつくる
/etc/modprobe.d/rtl-tcp-blacklist.conf に以下のような内容を書いておくことにした。
blacklist dvb_usb_rtl28xxu
blacklist rtl2830
blacklist dvb_usb_v2
blacklist dvb_core
既存のファイルに追加してもよい。
これで reboot してやれば OK。 Pi でも APCでもうまく起動できた。
windows で SDR# を起動、APCでの rtl_tcpに接続して FM放送が受信できることまで確認した。
ただ SDR# からの接続を切ると rtl_tcp が Segmentation Fault を起こして落ちてしまう。 これは rtl_tcp側の問題のようだ。
TUMBLR氏のブログの記事
*Raspberry PiとRTL2832Uドングルを受信サーバとして使うためにrtl_tcpを修正した
に同様の症状を修正したことが書いてあった。この記事の github リンクにあるものは確かに落ちないのだが、1年ほど前のものなので、ドングルの情報が取れなかったり、ゲインが変更できなかったりする。
今のバージョンに修正をあてても症状が変わらない。根が深そうなので後で見ることにしよう。
APC に Apricot-R5 をインストールした
Google group に forumがあった https://groups.google.com/forum/#!forum/apc-pico-itx-boards
というわけで、APC に Apricot-R5 をインストール
https://groups.google.com/forum/#!category-topic/apc-pico-itx-boards/wmt-8750/4ExLaVHny98 をもとに APC をUSB デバイスモードにして USB/TFTPブートを可能に
Apricot-R5のイメージはここにhttp://breizhcloud.eu/depot/Apricot-R5/ある。
USBメモリに書き込んで立ち上げるだけ。
Raspbian のパッケージがそのまま使える。ということで、ネットワークで使う分には Raspberry Piとかわらなくなった。
GRUB2 からZFS rootの FreeBSDの起動を試す
実は FreeBSD 10.0-RELEASE をインストールしたマシンには、ArchLinuxをインストールした別のHDDが接続してあり、そちらはGRUB2から起動するようにしてあった。
マシンのBIOSメニューに入ってbootドライブを変更してやることで、FreeBSDとLinuxの選択ができる。
でも、いちいち BIOSに入るのはメンドクサイ!
そこにGRUBがあるじゃないか
GPTパーティションからの起動なので MBM は使えない。というわけで、GRUBから FreeBSDの起動する設定を模索する。そもそもそのための GRUBだ。しかし、UFSならともかくZFS rootに設定したところからブートできるのか?
幸い、ArchLinuxから入れたので GRUB は最新(だと思う)の GRUB 2.02。ZFSにも対応しているらしい。
Google先生は役に立たない(こともある)
とりあえず grub zfs freebsdなどでググってみる
これはFreeBSDのportsからGRUBをインストールしてうまくいかなくてパッチを当てている話だ。っと、portsに GRUB があったんだ。知らなかった。しかし、今回の目的とは違うようだ。
これか? ZFS root から起動しているようだ。真似していろいろ試みるが、うまくいかない。2011年の記事だし。 よく読んでみると /boot は UFS に置いているようだ。ダメではないか。今回 /bootはZFS の中にあるのだ。
灯台下暗し。困ったときは源典へ。GNU のドキュメントは info を見る
GRUB そのものについても検索するも、よくわからない。man grub はありません。GRUB のドキュメントはいったいどこに?
あぁ、忘れてたよ info だ。 info grub だ。
info grub → Configuration → Multi-boot manual config とたどると、探していたそのものの例があった。
menuentry "FreeBSD" {
insmod zfs
search --set=root --label freepool --hint hd0,msdos7
kfreebsd /freebsd@/boot/kernel/kernel
kfreebsd_module_elf /freebsd@/boot/kernel/opensolaris.ko
kfreebsd_module_elf /freebsd@/boot/kernel/zfs.ko
kfreebsd_module /freebsd@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache
set kFreeBSD.vfs.root.mountfrom=zfs:freepool/freebsd
set kFreeBSD.hw.psm.synaptics_support=1
}
insmod zfs の指定とパーティション指定、ルートディレクトリへのpathの指定がキモのようだ。 synapticsは関係ない。
GRUBからZFS中のFreeBSDが起動できた
さて、どうすればよさそうか考える。
手元のマシンでは
なので、目の前にあるマシンの状態と先の例を見比べてできたのが以下の設定。
menuentry "FreeBSD load kernel zroot" --class freebsd --class bsd --class os {
insmod zfs
search --no-floppy --set=root --label zroot --hint hd0,gpt3
echo 'Loading FreeBSD kernel in zroot ...'
kfreebsd /ROOT/default@/boot/kernel/kernel
kfreebsd_module_elf /ROOT/default@/boot/kernel/opensolaris.ko
kfreebsd_module_elf /ROOT/default@/boot/kernel/zfs.ko
kfreebsd_module /ROOT/default@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache
set kFreeBSD.vfs.root.mountfrom=zfs:zroot/ROOT/default
}
grub.cfg は custom.cfg というファイルがあれば、それを読み込むようなので、 こいつを grub.cfg と同じディレクトリの custom.cfg に書いてやった。
成功! 起動した。
--label zroot する代わりにUUID指定で --fsuuid xxxxxxxx でもよいかもしれない。UUIDを調べるのは
ArchLinuxから lsblk -o NAME,UUID /dev/sda
でよいかもしれない。うまくいっちゃったので未確認。
/boot/kernel のところを /boot/kernel.old などとしたものを作っておけば、腐った kernelをインストールして起動しなくなっても、前のカーネルに切り替えられて便利かもしれない。
FreeBSD のローダーメニューは出せないか?
試してみたらできてしまった。見慣れた BSD のブートメニューが現れた。
kernel を指定する代わりに zfsloaderを指定する。設定は以下の通り。さっきより行数が減った。
menuentry "FreeBSD load zfsloader in zroot" --class freebsd --class bsd --class os {
insmod zfs
search --no-floppy --set=root --label zroot --hint hd0,gpt3
echo 'Loading FreeBSD ZFSloader in zroot...'
kfreebsd /ROOT/default@/boot/zfsloader
set kFreeBSD.vfs.root.mountfrom=zfs:zroot/ROOT/default
}
めでたし。
FreeBSD 10.0-RELEASE の ZFS root へのインストールを試してみた
今時、こんなことは仮想マシンでやればいいのだが、
DVD から 10.0-RELEASE をインストールする
実マシンでまっさらにできる HDD ができたので、10.0-RELEASE の DVD からのインストールを試してみた。
ZFS rootへのインストールがインストーラからできるようになったとのことで、せっかくなので ZFS rootにしてみる。
インストーラが全部やってくれるので、とても楽。何も問題は出なかった。 ZFS のメニューに進むと stripe/mirror/raid選択、HDD選択があったが、 試せる HDD は一台のみなので、冗長化なしの pool になった。
できたパーティションの状態
150GBしかない HDD だけどこんな感じになった。
当たり前だけれども GPT になっている。
# gpart show ada0
=> 34 312581741 ada0 GPT (149G)
34 1024 1 freebsd-boot (512K)
1058 8388608 2 freebsd-swap (4.0G)
8389666 304192109 3 freebsd-zfs (145G)
各パーティションにはラベルがついていて、それぞれ gptboot0 swap0 zfs0
となっていた。
ZFS プール名は zroot 。
デバイスは ada0 などではなく UUID (gptid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx) で参照される。長くて見難い。
できた ZFS ファイルシステム
以下のような構成になった。
NAME USED AVAIL REFER MOUNTPOINT
zroot 1.63G 141G 144K none
zroot/ROOT 852M 141G 144K none
zroot/ROOT/default 852M 141G 852M /
zroot/tmp 176K 141G 176K /tmp
zroot/usr 813M 141G 144K /usr
zroot/usr/home 184K 141G 184K /usr/home
zroot/usr/ports 813M 141G 813M /usr/ports
zroot/usr/src 144K 141G 144K /usr/src
zroot/var 1.25M 141G 616K /var
zroot/var/crash 148K 141G 148K /var/crash
zroot/var/log 216K 141G 216K /var/log
zroot/var/mail 144K 141G 144K /var/mail
zroot/var/tmp 152K 141G 152K /var/tmp
zroot/ROOT/default がルートになる。
結構細かく分けているようだ。ZFS なので構成の変更は後でどうにでもなるだろう。
src や ports は展開しなかったが filesystem はできている。
プロパティに関してメモ
zroot以下 atime=off がデフォルト /var/mail だけは atime=on
compression=lz4 になっているもの
/tmp /usr/ports /var/crash /var/log /var/mail /var/tmp
- setuid=off になっているもの
/tmp /var/log /var/tmp
- exec=off になっているもの
/var/crash /var/log
追記
150GBの古いHDD なので当然 物理セクタサイズは 512byte/sector なのだが、zdb zroot で見てみると ashift が 12 になっていた(つまり 4Kbyte/sectore扱い)。
ZFS 配下のディレクトリに linprocfs をマウントするには late オプションを使えばいいらしい
自宅サーバ(FreeBSD9.2)では ZFS を使っている。
まだ全部 ZFS にしてしまうには不安があったので、/ や /usrなどは ufs のまま。
linuxエミュレーションを使うのに linux procfs が必要だったので、/etc/fstab に
linproc /usr/compat/linux/proc linprocfs rw 0 0
のように記述していたのだが、boot時このマウントがうまくいかなくて single user mode で対処しないといけない状態になってしまった。
/usr/compat 以下は ZFS 配下にあり、boot時の mount 順がうまくない様子だった。
サーバなのでそれほど reboot する機会はないので /etc/fstab から先の記述をはずしてそのまま放っておいたのだが、 ふと思い立って Google 検索したところ あるブログが引っかかった。うちの状況と同じだ。
というわけで、/etc/fstab の linproc に関する部分に lateオプションを追加、以下のようにした。
linproc /usr/compat/linux/proc linprocfs rw,late 0 0
むむむむ late というオプションには気がつかなかったよ。
FreeBSD-10.0BETA1 が出た
予想どおりアナウンスがあった。
amd64, i386, ia64, powerpc, powerpc64, sparc64についてイメージが出ている模様。
注意が必要なのは、10.0-BETA1 の freebsd-update(8)に問題があるので、アップグレードに freebsd-update(8)を使わないでね ということ。
-ALPHA5 から -BETA1 への変更点
Changes between -ALPHA5 and -BETA1 include:
o Introduce freebsd-version(1), which is intended to be used as an
auditing tool, to determine the userland patch level when it
differs from what 'uname -r' reports.
o Improve ZFS lzjb decompress performance.
o Add two new MIPS CPU families - mips24k and mips74k.
o The "jail_<jname>_*" rc.conf(5) variables for per-jail
configuration are automatically converted to
/var/run/jail.<jname>.conf before the jail(8) utility is invoked,
so the new jail.conf(5) syntax is used.
o Remove most of the ATF tools and the _atf user.
o Updates to random(4). Please note the following:
- In 10.0-BETA1, it is not possible for random(4) to be loaded
as a kernel module via kldload(8). If not using GENERIC, and
the system kernel configuration excludes 'device random',
please include random(4) in the kernel configuration file.
The fix for this issue is pending review, and is expected to
be fixed in 10.0-BETA2.
o Updates to bsdinstall(8). Please note the following:
- 10.0-BETA1 introduces a number of updates to bsdinstall(8),
notably the ability to install to a full ZFS filesystem.
Please keep in mind that this is an experimental feature.
- If using the ZFS installation option in *and* have enabled
full-disk encryption is enabled, a few entries will need to be
manually added to loader.conf(5) before the 'bootpool' zpool
will be available after the system boots. This manual step
is expected to be fixed in 10.0-BETA2.
The entries that need to be added are:
zpool_cache_load="YES"
zpool_cache_type="/boot/zfs/zpool.cache"
zpool_cache_name="/boot/zfs/zpool.cache"
This can be done at the final menu of bsdinstall(8), when
prompted to boot into the newly-installed system;
alternatively, this can be done post-install, in which case,
the following must be run before appending loader.conf(5):
# zpool import -f bootpool
テキトーにやくしてみる
- freebsd-version(1) の追加
- ZFS lzjb 展開時パフォーマンスの向上
- MIPS CPUファミリを二つ追加 - mips24k and mips74k
- jail毎のコンフィグ変数 rc.conf(5)をjail(8)起動前に自動的に /var/run/jail.
.conf に変換する。なので jail.conf(5)の文法を使うようになった - ほとんどの ATF ツールと _atf ユーザの削除
- random(4) へのアップデート。以下に注意のこと
10.0-BETA1 では random(4)を kldload(8)でカーネルモジュールとしてロードすることができない。カーネルコンフィグファイルに device random'が除かれていたり、GENERIC を使わないなら、random(4)をカーネルコンフィグに追加のこと。この問題は10.0-BETA2では修正される見込み。
- bsdinstall(8)へのアップデート。以下に注意のこと
** 10.0-BETA1 では bsdinstall(8) に、特に full ZFS filesystem へのインストールができるという、いくつかアップデートが追加された。 これはまだ実験的な機能だということに注意。
** ZFSインストールで 全disk暗号化を有効化する場合、システムブート後 'bootpool' zpool が現れる前に、手動でエントリを loader.conf(5)に追加する必要がある。この手動ステップは 10.0-BETA2 では修正される予定。 追加する必要のあるものとは
zpool_cache_load="YES"
zpool_cache_type="/boot/zfs/zpool.cache"
zpool_cache_name="/boot/zfs/zpool.cache"
これは bsdinstall(8)の最終メニュー、 新しくインストールしたシステムをブートするところで行うことができる。 あるいは、これはインストール後に行うことができる、この場合、 loader.conf(5)への追加の前に、以下を実行しないといけない。
# zpool import -f bootpool