Transceiver

図書館に行くと、司書の方が月代わりで、色々なジャンルの本を集めて紹介されている。秋の夜長に推理小説とか、ミステリー系とか、青春系とか、色々な職業編とか。知恵と言うかアイデアの発露ですな。それ以外に、作家が亡くなったりすると、追悼って事で、その作家の著作を並べたり。そういうのに乗せられて(乗って)、違うジャンルの本を読むのも楽しいものだ。

鉄道好きな人を俗に鉄分豊富とか、鉄ちゃんなんて言う事がある。あるいは、どんな風に鉄を愛してるかによって分類する事もある。乗鉄とか撮鉄とかだ。

鉄に関する小説を集めた本が飾ってあったので、借りてきた。『 古くからある小説やら書下ろしを含めて、50編が収録されてた。

名前は聞いた事があったけど今まで読んだ事が無い、房総安房列車。鉄道好きが高じての、暴走で、千葉県内を4泊しながら、乗り鉄する。一日の乗車時間は、せいぜい3時間ぐらい。行った先々で、観光して酒を喰らってうじうじする。何とも優雅というか、のんびりしてるというか。 まあ、昔の小説だから、時代離れしてる所があるな。

時代と言うと、戦時中、兵隊さんを大陸に送り出して、機関士にしてくれと、軍部から頼まれた、ベテラン機関士の物語。

先生となる機関士が、生徒を一人前にしてあげようと汽車の本を探す。そんな特殊なジャンルの ものが普通の本屋にあるんか?やっと見つけたのは、うらぶれた古書店。べらぼうに高い。 こんな特殊な本を在庫しててもはける可能性は少ないでしょうから、安価で売って下さい。 足元を見た店主は、びた一文と負けられません。悩んだ末に機関士は、言い値で購入。 そして、サインを入れて、生徒に手渡す。ほろりとさせる話だった。

何処から読んでも、独立してるんで、気のむいたタイトルを拾い読みすれば良い。長編小説は ずっと読み通さないといけないので、たまにはこういうのもいいな。

pico nano micro

前回作ったポータブルFreeBSD、よく考えたら、PicoBSDの延長じゃなかろうか? いや、NanoBSDの延長かな。PicoならOSを焼き込む先が、主としてフロッピーディスクだった。用途は、突然電源断になっても壊れないルーターとかにどうぞって触れ込み。

また、NanoBSDなら、組み込みの基盤にどうぞって訳。

じゃ、今回オイラーが作ったポータブルFreeBSDは? pico、nanoときたから、MicroBSDと呼称していもいいんでなかろうか。

OSはフルスタックのもの、そして全ソース付き。ユーザーランドは、自分の好みに合わせて、firefoxとかemacsとかが入っている豪華なものだ。

作成時間も、virtualboxでOSを入れて、freebsd-update fetch(install)してセキュリティーパッチを当て、好みのユーザーランドを入れる。ここまで、慣れてれば30分コースぐらいだろう。(ああ、グルる様から褒められるぐらいの、回線スピードは必要だけど) それから、USBに焼くのに余裕をみて30分ぐらいか。計1時間もあれば、お釣りがくる。

だったら、これをMicroBSDって名乗ってどこが悪い。

ぐるると、ウブで、USBにライブ版を焼いて自慢してる記事がやたらと引っかかってくるけど、それらは、オンリーワンじゃないんだよな。

Unixを使うなら、カスタマイズしなくちゃ使ったうちに入らないと思うぞ。

カスタマイズったら、カーネルからぜい肉ぐらいは落とせよ。boot時の挙動を見てると、dataセグメントのロードに多大な時間がかかってるぞ。それ、やってもいいんだけど、カスタムカーネルにすると、バイナリーパッチが当てられなくなるんで、痛しかゆしなのよね。

$ df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/da0s1a    5.7G    3.9G    1.3G    75%    /
devfs          1.0K    1.0K      0B   100%    /dev
/dev/da0s1b    1.1G    155M    885M    15%    /home
tmpfs          2.7G    4.0K    2.7G     0%    /tmp
/dev/md0        31M    348K     28M     1%    /var
$ mount
/dev/da0s1a on / (ufs, local, read-only)
devfs on /dev (devfs, local, multilabel)
/dev/da0s1b on /home (ufs, local, journaled soft-updates)
tmpfs on /tmp (tmpfs, local)
/dev/md0 on /var (ufs, local)

今は、突然に電源が切れても、本体を守るようにread-onlyにしてる。それから、emacsの起動も、事の他速いので、viで大きなファイルを編集するってのは、放棄した。従って、varの容量も減らしてある。こうして、段々と仕様が収斂してくのさ。

speed up

以前、TOSHIBAのUSBメモリーにOpenBSDを焼いた時、随分遅かった。遅い事にかけては天下一品のやつだからしょうがないと思っていたんだ。

ob# dd if=/dev/rwd0c of=/dev/rsd0c bs=1m
7168+0 records in
7168+0 records out
7516192768 bytes transferred in 2071.593 secs (3628219 bytes/sec)

これ、前回の結果。

でも、virtualboxで、USBのアドインを入れると、USB2.0やUSB3.0が使える事を知った今、試してみたくなった。丁度、syspatchをしたら、パッチが色々と入ってきたしね。OpenBSDの仮想マシンの所で、USBの設定を開き、USB3.0を有効にしてやる。(有効にする前は、USB1.1だった)こうしておいて、焼いてみると、

ob# dd if=/dev/rwd0c of=/dev/rsd0c bs=1m
7168+0 records in
7168+0 records out
7516192768 bytes transferred in 1311.214 secs (5732238 bytes/sec)

あーら不思議。同じ環境なのに、倍近く書き込みスピードがあがったよ。USBメモリー自身は、USB2.0対応を謳っているので、得した気分。こうなると、バッファローのUSB3.0は、怪しい雰囲気だな。果たして、USB3.0分の働きをしているのやら、はなはだ疑問。

RSSI

実際に遊べる(遊ばれてる)ワイヤレスなNICを楽しんでる。その中で、RSSIってのが出てくるんだけど、なんじゃいな? ちょいと調べてみると、 受信強度(RSSI:Received Signal Strength Indicator)らしい。

シグナルストリングスって、昔使ってたぞ。例えば、月山の山頂にトランシーバーを担ぎあげて、昼休みに、

CQ,CQ,CQ JA1XXXX/7、月山山頂、どなたかお声がけ下さい。オバー。
こんにちは、JA1XXXさん、こちらは、JH7YYY、日本海沖の、飛島ポータブル。59です。
早速のお声がけありがとうございます。こちらからは、メリット5、
シグナルストリングス9+をお送りします。

これで、交信成立。この後は、『天気晴朗なれど風強し』とか、ちょっと気取って『雲の峰、幾つ崩れて、月の山』とか、おしゃべりモード(ラグチューって業界用語があります)に突入したりします。

メリットってのは、人間の主観による了解度を1から5の数字で表したもの。次の9とか9+ってのは、トランシーバーとかに付いている信号強度計の振れ具合。生憎Sメーターが付いていなかったりすると、耳Sと言って、耳で判断した(高度な)信号強度を送る事になる。

RSSIなんて持って回った言い方をしないで、Sでいいじゃん。ああ、ただのSだと、公安警察で 言う、スパイの隠語になるか。

そう言えば、昔、消防無線とか警察無線の傍受を趣味にしてる人が居たな。

救急1号より、本部。
死にそうなばあさんを、XX病院へ搬送完了。これから帰還します。

傍受されてるとも知らないで、時々荒っぽい言葉が出て来るとか。荒っぽい言葉と言ったら、 警察の方がよっぽど酷いとか。ここに書けないぞ。まあ、昔はおおらかだったって事です。 今は、デジタル化して、こういう楽しみは無いとか。航空無線ぐらいで我慢しとけ。

ワイヤレスLANも、認証だ、暗号だと、うるさいぐらいになってるな。それとスピード競争ね。

オイラーが遊びの対象にしてるのは、送信アンテナが1本、受信アンテナが2本のものだ。受信アンテナが2本あるって事は、2.4Gと5Gを同時受信出来るんだな。送信機能と受信機能が一つの箱(チップ)に収められている物を、トランシーバーと言う。ばらばらに持つよりも回路を有効に使えたり、小型化出来るので、最近のリグは、全部トランシーバーになっている。

ちょっと横道に逸れてしまったので、本道に戻ります。

RSSIについて

RSSIレベルと信号強度

Wireless LAN - Site Survey

RSSIってのは、メーカーが勝手に言ってるだけのものなんか。まあ、アマチュア無線のトランシーバーに付いてるSメーターも、振れ方が各社各様だからなあ。

でも、受信電力をちゃんと dBmの単位付きで、権威を込めて表示してるな。どういう風に算出してるのかな? そんなのソース嫁。

$ wlanstats
   :
12.5       current rssi
-85        current noise floor (dBm)
-72.5      current signal (dBm)

/usr/src/tools/tools/net80211/wlanstats/wlanstats.c

static int
wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
{
        const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];

        switch (s) {
        case S_RATE:
                snprintf(b, bs, "%.1fM", (float) si->isi_txmbps/2.0);
                return 1;
        case S_RSSI:
                snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0);
                return 1;
        case S_NOISE:
                snprintf(b, bs, "%d", si->isi_noise);
                return 1;
        case S_SIGNAL:
                snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0
                    + (float) si->isi_noise);
                return 1;

RSSIはチップから得られた値を2で割ってる。SIGNALも同様だ。何故2で割るんだよーーーと 考えていたら、思いついた。チップから得られるのは、電圧換算なんだろう。それを電力換算のdBmに直してるんだな。

Pv = 10 * log(Pr/1mW)                      ...(1)
Pr = Ir * Er                               ...(2)
   = Er/50 * Er
   = Er^2 /50
Ev = 10 * log((Er^2 / 50) / (Eref^2 / 50)) ...(3)
   = 10 * log((Er/Eref)^2)
   = 20 * log(Er/Eref)

上記で(1)式は、電力表現によるdBmの定義。基準となる1mWに対して、比較する電力Prは、何倍(あるいは、弱いか)を、対数表現したもの。(2)式は、電力を抵抗(無線業界では、通常50オーム、audio系だと600オームかな)と、抵抗の両端電圧差で表したもの。(3)式は、電圧換算による表現。(2)式を(1)へ代入して、整理すると得られる。(Erefは1mWを消費する時の電圧を表すものとしてる。(2)式を1mWとして計算すると、大体0.223Vになる)

果たして予想は本当か? データシートを見れば書いてあるだろけど、見つけられず。 インテル® ワイヤレス・アダプター・ファミリーの仕様情報 こんなのしか、出てこない。

大体Intelさんはチップだけを売ってくれるのか。チップを載せた ボードの形にして、付加価値をつけて利益を上げてる疑惑があるな。だから、チップ情報は、頭を下げて契約しないと出てこない。(多分)

iwn in FreeBSD

iwnstatsというtoolが置いてあったので、走らせてみた。今は、rssiとノイズに注目してるんで、その結果だけを表示する。他にも山ほどのデータが、100ms間隔で流れてくる。

root@fb:/tmp # iwnstats
  :
iwn_stats_rx_general_print: noise=[4885, 4885, 0] flags=0x00000001, load=102393, fa=0
iwn_stats_rx_general_print: rssi=[35, 40, 0] energy=[66 61 101]

ノイズにしろ、rssiにしろ、何で3組あるの?該当するソースを眺めてみると、

static void
iwn_stats_rx_general_print(struct iwnstats *is, struct iwn_rx_general_stats *g)
{
            :
        printf("%s: noise=[%d, %d, %d] flags=0x%08x, load=%d, fa=%d\n",
            __func__,
            le32toh(g->noise[0]),
            le32toh(g->noise[1]),
            le32toh(g->noise[2]),
            le32toh(g->flags),
            le32toh(g->load),
            le32toh(g->fa));

rssiとかも3つの整数グループになってた。ああそうか、最大で受信アンテナが3本あるチップが有るから、それぞれを表示してんだな。

大元のデータは、下記を使って収集してる。引数のisは、/dev/iwn0のファイルディスクリプタになってる。

int
iwn_collect(struct iwnstats *is)
{
        int err;
        struct iwn_ioctl_data d;

        printf("st: %p\n", &is->st);
        d.dst_addr = &is->st;
        d.dst_len = sizeof(is->st);
        err = ioctl(is->s, SIOCGIWNSTATS, (caddr_t) &d);
        if (err < 0)
                warn("ioctl");
        return (err);
}

更に、/sys/dev/iwnの中で、色々と調整をやってる。

static int
iwn5000_get_rssi(struct iwn_softc *sc, struct iwn_rx_stat *stat)
{
           :
        DPRINTF(sc, IWN_DEBUG_RECV,
            "%s: agc %d rssi %d %d %d result %d\n", __func__, agc,
            phy->rssi[0], phy->rssi[1], phy->rssi[2],
            rssi - agc - IWN_RSSI_TO_DBM);
        return rssi - agc - IWN_RSSI_TO_DBM;

agcなんていう懐かしい言葉が出て来たなあ。まあ、受信機なんで、強い信号でサチらないようにしたり、弱い信号の場合は目一杯ゲインを上げて聞き耳をたてる必要があるな。更に、IWN_RSSI_TO_DBMで、補正してdBmに直してるのか。この値はif_iwnreg.hで44って定義されてたよ。

rtw in OpenBSD

iwnなデバイスのデータシートは、一般人では手に入りそうにない。譲歩して、 取れるもので我慢しよう。どうせトランシーバーですから、奇妙奇天烈なものは無いだろう。

REALTEK WIRELESS LAN NETWORK INTERFACE CONTROLLER RTL8180

蟹さんチップの仕様書が見つかった。 OpenBSDでは、rtwで認識されるデバイス。

DESCRIPTION
     The rtw driver supports PCI/CardBus 802.11b wireless adapters based on
     the Realtek RTL8180L.

     A variety of radio transceivers can be found in these devices, including
     the Philips SA2400A, Maxim MAX2820, and GCT GRF5101.

Card(PCMCIA?)にして、BuffaloとかCoregaaあたりが採用してるんで、オイラーもひょっとして近接接近してるかも知れないな。

ドライバー関係は、下記っぽい。

/usr/src/sys/dev/cardbus/if_rtw_cardbus.c
/usr/src/sys/dev/ic/rtw.c
/usr/src/sys/dev/ic/rtwreg.h
/usr/src/sys/dev/ic/rtwvar.h

折角手に入れたシートなんで、最初から眺めていくと、4ページ目に PDFのBlock Diagram が出ていた。TX/RX sectionが、いわゆる、トランシーバーの部分になる。TXの出力はDACを経由して、デジタル信号からアナログ信号に変換される。この時、TXIとTXQって信号に分離される。

受信側も同様に、RXIとRXQの2つのアナログ信号RXIとRXQを受け取ってから、ADCを通してデジタル信号に変換してる。更にAGCとかRSSIなんて信号も出入りしてるな。

これらの先は、ブロック図になっていないけど、無線屋なら、大体想像がつくよ。ミキサーで、搬送波と混合されるんだ。送信機の場合は、スプリアス除去のため、フィルターを通って、終段に行く。そこで、電力増幅してから、送信アンテナへ送られ、電波となって、飛んでけーー。

受信側だと、ミキサーでビートダウンして、低い信号だけを、取り出すとな。ああ、ミキサーは、IQ信号を分離するため、sin波、cos波を加える別々な回路になってるんだな。 AGCが有るって事は、高周波(2.4G)のアンプが使われているのかな。それとも、扱い易い周波数帯に一度落としているのかな?

まあ、そういう無線屋が喜びそうな事は、デバドラ書くのに一切関係ないから、省いちゃったんだろうね。

IQ信号で処理してるって事は、SDRだな。ADCとか、何Bit構成なんだろう?変換スピードはいかほどかな。仕様書を丹念に読むと、何処かに書いてあったりして。

iwlist in Debian

Debianのwireless-toolsに入っているiwlistを使うと、各局の信号レベルが、下記のように採取出来る。ここでは、直接にRSSIってのは出てきていないけど、それに相当するのは、Qualityと考えられる。RSSI==Sメーターっていう理解なんで、この場合、0から70まで振れるメーターがあって、一番上の例だと55の目盛りまで振れてる強い局だと思われる。ミリワット換算すると、それは-55dBmですって事だな。

debian:~$ sudo iwlist scan | grep dBm | sort -nr
                        :
                    Quality=55/70  Signal level=-55 dBm
                    Quality=45/70  Signal level=-65 dBm
                    Quality=44/70  Signal level=-66 dBm
                        :
                    Quality=22/70  Signal level=-88 dBm
                    Quality=21/70  Signal level=-89 dBm

どんなコードが書かれているか、ソースを取り寄せて開いてみるか。

debian:tmp$ mkdir wl; cd wl
debian:wl$ sudo apt source wireless-tools
Reading package lists... Done
Need to get 363 kB of source archives.
Get:1 http://ftp.jaist.ac.jp/debian stretch/main wireless-tools 30~pre9-12 (dsc) [2,127 B]
Get:2 http://ftp.jaist.ac.jp/debian stretch/main wireless-tools 30~pre9-12 (tar) [348 kB]
Get:3 http://ftp.jaist.ac.jp/debian stretch/main wireless-tools 30~pre9-12 (diff) [12.1 kB]
Fetched 363 kB in 0s (1,134 kB/s)
dpkg-source: info: extracting wireless-tools in wireless-tools-30~pre9
dpkg-source: info: unpacking wireless-tools_30~pre9.orig.tar.gz
dpkg-source: info: unpacking wireless-tools_30~pre9-12.debian.tar.xz
dpkg-source: info: applying fix-makefile-for-debian.diff
dpkg-source: info: applying zero-struct-iwr.diff
dpkg-source: info: applying wireless-tools-docs.patch
dpkg-source: info: applying honour-cflags
dpkg-source: info: applying add-import-type-to-udev-rules
dpkg-source: info: applying fix-typos
dpkg-source: info: applying improve-make-install
W: Download is performed unsandboxed as root as file 'wireless-tools_30~pre9-12.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

ぐちゃぐちゃとファイルを散りばめてくれるので、捨てdirを掘って、その中でやるのが、後片付けが楽で良いと思うぞ。

で、Sメーターの値とかを計算してる部分は、iwlib.cにあった。例がコメントに書かれていた。

   * The range allow to specify the real min/max of the value. As the
   * range struct only specify one bound of the value, we assume that
   * the other bound is 0 (zero).
   * For relative values, range is [0 ; range->max].
   * For absolute values, range is [range->max ; 63].
   *
   * Let's take two example :
   * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100
   * 2) value is -54dBm. noise floor of the radio is -104dBm.
   *    qual->value = -54 = 202 ; range->max_qual.value = -104 = 152
          :
      /* Deal with quality : always a relative value */
      if(!(qual->updated & IW_QUAL_QUAL_INVALID))
        {
          len = snprintf(buffer, buflen, "Quality%c%d/%d  ",
                         qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':',
                         qual->qual, range->max_qual.qual);
              :
      /* Check if the statistics are in RCPI (IEEE 802.11k) */
      if(qual->updated & IW_QUAL_RCPI)
        {
          /* Deal with signal level in RCPI */
          /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */
          if(!(qual->updated & IW_QUAL_LEVEL_INVALID))
            {
              double    rcpilevel = (qual->level / 2.0) - 110.0;
              len = snprintf(buffer, buflen, "Signal level%c%g dBm  ",
                             qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':',
                             rcpilevel);

色々な場合分けが、この後に書かれているんだけど、代表的な所を抜粋。ノイズレベルは、-110に決め打ちしてるな。そして、dBmにするのに2で割り算してる。まあ、このあたりは、FreeBSDと一緒か。

Wireless Tools for Linux これ、作者さんの特設ページ。簡単にプロファイルすると、フランス在住でヒューレットパッカード社に勤めている。仕事としてLinuxと戯れているのかな? ソースを開くと、色々な事が見えてきて、楽しいな。

wireless.22.h

#define IWEVQUAL        0x8C01          /* Quality part of statistics (scan) */

ちょっと見てる所が違うけど、こんな要領で、リクエストを出すと、イベントのデータが流れて来るんだな。この仕組みで、中身が公開されていないドライバーとやり取り出来るとな。なお、下記のコードは、iwlib.cの中にあったもの。Getと対になるSetも当然存在する。

  /* Get frequency / channel */
  if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0)
    {
      info->has_freq = 1;
      info->freq = iw_freq2float(&(wrq.u.freq));
      info->freq_flags = wrq.u.freq.flags;
    }

ioctl

デバドラは、open/read/write/closeの他にioctlの実装が必要らしい。少し調べてみた。

ioctl

FreeBSD なら /usr/include/sys/ioccom.h を見ておけとな。

ioctlの実例

組み込みLinuxデバイスドライバの作り方 (6)

/usr/share/examples/drivers/ に、デバドラの作り方を解説するスクリプトが置いてあった。そして、実際に動いてるやつなら、/sys/dev/null/null.c が有る。null、zero、fullを扱えるとな。

SDR

前回だかにやったウォーターホールの所で、サンフランシスコの受信設備を載せた。その局の 案内を見てたら、NSAもびっくりするような、立派なアンテナを使っているのね。土地が広いと いいなあ。それと、設備はdebianで動いているんだって。分かってる人がOSを選べば、そうなるわな。SDR系のパッケージも豊富に揃っているしね。

hamradio-sdr - Debian Hamradio Software Defined Radio Packages
freedv - Software Defined Radio (SDR)
gqrx-sdr - Software defined radio receiver
rtl-sdr - Software defined radio receiver for Realtek RTL2832U (tools)
soapysdr0.5-2-module-all - All device support for SoapySDR (metapackage)

SDR Radio Dongles

Technik im Amateurfunk

OpenBSDにもcomm/rtl-sdr なんてパッケージが有って、 rtl-sdrが、本拠地として、紹介されてた。ウォーターホールも有ったぞ。

庶民の味方、蟹さんチップ。