/*
 * vgaC - capture VGA signals most simply... I wish
 *   by uratan! 2012.5.2
 *     revised 2013.3.7
 */

vgaC 概要デモ

vgaC によってあなたの PC をただのディスプレイにしてしまえ



極上のデモムービーをご覧ください。
デモ 3分の1 (mpg, 114sec, 19MB)
デモ 3分の2 (mpg, 155sec, 26MB)
デモ 3分の3 (mpg, 101sec, 17MB)
デモ 全部入り (xvid, 370sec, 32MB)

(あなたの PC をただのキーボードにしてしまうこともできます、 ArmUZK によって)






製作の経緯

キーボード・マウス共有・延長器(?) の ArmUZK と双対をなすものとして、PC の画面出力を PC で受けるものを前から 考えていましたが、アナログかデジタルか、どの程度の性能を目指すか、と もんもんと考えるだけの日々が何年も続いていました。

この春に こちらのページを見つけまして、かなり衝撃を受けて さっそく試してみましたが、解像度が不十分で文字の判別が困難であり、 私の所望する状況は得られませんでした。
しかしながら、おかげさまで「もっとも簡便にやる」というふうに割り切れまして、 ようやっとスイッチが入って製作に踏み切りました。

というわけで vgaC は、アナログ VGA (今更ですが) の RGB 信号を 各々 1bit でキャプチャーし、PC には USB FullSpeed で送り込む、 という装置です。速度もそれなりです。

世間的にはちゃんとした製品もありますので そちらを選んだほうが無難ではありますが、 ま たいへん面白かったです。
DVI/アナログVGA 画像入力 …(株式会社アルゴ)
HDMI+キャプチャ+USB ………(google 検索)


なにはともあれ、もろもろリリースです。
vgaC-037R.zip --- 回路図/HDL/arm/win 全部入りパッケージ
    (sch: 2.8+A1.6, HDL: 0x27, arm: 0.33, win: 0.94 ... 11changes.txt)


            赤の LPC-H2148、緑の FPGA と合わせて基板も RGB

目次

システム構成
アナログ回路
ロジック回路
FPGA の回路記述
LPC2148 ファームウェア
windows 用アプリケーション wvgaC.exe
動作シーケンス
消費電流
USB 転送レートの不思議
パフォーマンス
他 OS から vgaC へのアクセス方法
ギャラリー (screen-shot と写真)
vgaC の今後



システム構成

[txt] SYSTEM BLOCK DIAGRAM

vgaC は、アナログ VGA の RGB 信号を 各々 1bit でキャプチャーし、 PC には USB FullSpeed で送り込む、という装置です。

キャプチャー対象の video mode としては、BIOS Setup 他のための 720x400@70Hz、640x480@60Hz と、通常の OS 動作の 1024x768@60Hz を 考えます。
VGA video 信号はアナログアンプで増幅した後にデジタル信号に変換します。 RGB video 信号は 0/1 の 2値に変換されますが、 バイアス電圧を可変することにより スライスレベルは変更することができます。
FPGA ではビデオ同期信号とタイミングを取って内蔵のバッファーメモリに RGB 信号を取り込みます。
USB インターフェース内蔵 ARM マイコンの LPC2148 が Mass Storage Device として PC と接続し、バス接続した FPGA を制御・データを引き取り PC に転送します。
ターゲットとなる PC をリモートから制御することを鑑み、フォトモスリレー による on/off スイッチを 2つ付けて評価してみました。

(目次)

アナログ回路

回路図 sch/vgaC_A-XX.png をご覧下さい。

試行錯誤の結果この回路に落ち着きましたがまったく自信がありません。
一応説明しますと、
マイナス 1V電源を用意して、-1→5V の 6V 電源で 0V をベースにすると AC カップリング無しにできそうに思いますが、 スライスレベルを自由にできるので これはこれでよし…としたい。
[osc] アナログ動作波形 (High Intensity ビデオ信号入力からオペアンプの出力まで)
[osc] アナログ動作波形 (Low Intensity ビデオ信号入力から LCX04 の出力まで)
              (リンギングは測定環境のせいだと思いたい)
回路図は相変わらずH.Okada さんの BSch Version 0.92 にて作成しています、感謝。
LT1399 をはじめ大方の部品は 千石電商 で入手しました。あ LED は 秋月電子通商だ。 たいへんお世話になっております。
(目次)

ロジック回路

回路図 sch/vgaC-XX.png をご覧下さい。

基本 繋ぎだけなので回路としての説明は不要でしょう。

コントローラーには ArmUZK でも使用した勝手知ったる NXP の LPC2148 ( OlimexLPC-H2148 ) を使います。
LPC2148 は USB 1.1 の FullSpeed (12Mbit/sec) のデバイスとしての インターフェース機能を内蔵しており、これを使って USB Mass Storage Class の Bulk-Only Transport プロトコルを実装し、SCSI リムーバブル HDD として PC に認識させます。 この為、概ね OS を選ばずに認識させることができるはずです。
しかしながら、運用としては常にメディアが無い状態として OS による通常の リクエストをすべて無効とし、独自に定義したベンダーユニークコマンドを発行する アプリケーションのみが装置を制御できる形とします。

アナログ回路にて 2値化された RGB 信号は、V-SYNC/H-SYNC に同期して サンプリングしますが、この回路およびバッファーメモリは FPGA にて 実現します。
FPGA は手持ちの関係および過去の経緯から Xilinx SPARTAN-3を選択しました。
Design Wave Magazine 2005年1月号 付録の xc3s50 評価基板 FRK-S35を使って開発は行いましたが、 さすがにこれは今から入手はほぼ不可能でしょうから、 HuMANDATA製の xc3s200 モジュール XCM-301-200 も使用できるように設計してあります。
xc3s50 と xc3s200 とは内蔵のロジック数・メモリ容量などが違うだけの兄弟 チップです。xc3s50 では 8kByte、xc3s200 では 24kByte まで FPGA 内キャプチャーバッファーメモリが確保できますが、中継の LPC2148 で 28kByte程度までしか転送バッファを取れないので やや宝の持ち腐れっぽいです。

LPC2148 と FPGA は 8bit のパラレルバスで接続します。このパラレルバスは、 FPGA 内部に 16bit のアドレスポインタを持たせシーケンシャルアクセスに 機能を特化することによりアドレスバスは省略してあります。
LPC2148 側は特殊なハードウェアは持てないため、LPC2148 では GPIO として 手作業でバスアクセスを実現します。処理に集中できれば 2MByte/sec 近いデータ転送速度が出ています。
[osc] write_fpga() アクセス波形 1.4MB/sec ぐらい
[osc] read_fpga() アクセス波形 2.0MB/sec ぐらいか
参考:[txt] BUS SEQUENCE
        (今となっては SPI でシリアルもありかもしれません)
FPGA 内部のメモリ空間は 64kByte 分あり、ここに内蔵バッファのほか 32Byte 分の制御レジスタをマップします。LPC2148 がこれらのレジスタを経由して 情報をとったりキャプチャーの実行を指示したりします。
また LPC2148 は、常に PC からの ベンダーユニークの SCSI コマンドを受けて その結果を返す形で動作します。
参考:[txt] MEMORY MAP   REGISTERS
FPGA のクロックは LPC2148 より供給するため 現在は外付けの発振器は 必要ありませんが、固定供給源としてあれば便利なため回路を残しました。
デモにあるリモートからの利用を意識してフォトモスリレー(AQY210, AQV212) による汎用スイッチ出力も評価してみました。耐圧・電流(と値段)が違う 両者ですが、PC のスイッチの代わりにはどちらも十分なようです。

電源は消費電流が概ね 250mA に収まりそうなので USB バスパワーで使うことにしまして、LPC-H2148 の 3.3V 供給を そのまま使っています。アナログ回路に供給する 5V は、LPC-H2148 の拡張コネクタからは衝突防止のため USB の 5V からダイオードを経由したもの しか取れませんのでバイパス回路をつけてみました。

アートワークは高戸谷 隆さんの PCBE で描きました、感謝。
      (それにしてもシュリンク D-SUB 15 のコネクタを使う基板を 自分が作る日が来るとは・・・)

(目次)

FPGA の回路記述

verilog ソース HDL/top.v をご覧ください。(なおシミュレーションは使わずに 実機デバッグで済ませました)

VGA 信号規格におけるドットクロック 25.2MHz, 31.5MHz, 65MHz あたりから 126MHz を基準クロックとします。(当初は 100MHz でした)   この 126MHz クロックは、LPC2148 より供給される 18MHz を使って FPGA の PLL(DCM) にて作成します。
参考:[txt] VGA STANDARD REFRESH RATES   THINK ABOUT CLOCK AGAIN
                Spartan3 DCM PLL RESTRICTION
BUS_SEQUENCER ではパラレルバスの制御信号をウォッチし、内部アドレス信号を 管理するとともに内部アドレス空間とバスを接続します。
参考:[txt] BUS SEQUENCE   MEMORY MAP
内蔵レジスタは 8bit × 32個用意しました。このうち半分は入力 VGA 信号の 状態をとるリードオンリーのレジスタです。
参考:[txt] REGISTERS   BITWISE REGISTERS
最初の手配線回路では H-SYNC にノイズが大目に見られたため、前処理として SYNC_MODERATE_UNIT にて V-SYNC/H-SYNC に簡単なフィルターをかませています。 起こした基板ではノイズが消えているようなので原因は手配線だったようです。
ついでに FPGA を抜ける信号の遅延も調べてみましたが 10nsec ぐらいですね。
[osc] xHin vs fil_hsync
[osc] xHin vs raw_hsync
MEASURE_SYNC_INTERVAL_UNIT では情報取得のために両同期信号の周期(と 面白そうだったので極性)を測定します。また周期測定カウンターが オーバーフローする場合は VGA が未接続あるいは信号入力がないものとして OVF フラグを立てます。これらの情報は FPGA では使用しておらず、 上位のアプリケーションで吟味します。

CAPTURE_CONTROLLER がキャプチャー動作の制御ユニットです。
LINE_COUNTER_UNIT が生成する現在ライン番号(LINE_NOW)が、 キャプチャー対象の指定のライン番号 TARGET に一致したライン処理します。
目的のラインが見つかると、H-SYNC から指定の DELAY 時間待ち、 その後、OPTIONS の取り込み設定に従って N_DOTS ドット分取り込みます。
この動作は、指定の本数 N_LINES 分 引き続くラインに対して繰り返されます。
非力なデータ転送能力をカバーするため、RGB をまとめて 1byte に 8ドット分詰め込むモードなどを多数実装したため やや複雑ですが、 全体としては特に特殊なことをしているつもりはありません。
なお 両 SYNC は、変化点を基準とするということで極性は無視してますし、 信号の相対遅延も気にしていません。 (wvgaC.exe で与えるパラメータでカバーする)
また、RGB の並び・重みを G=4,R=2,B=1 にこだわっているのは私が PC-8001 でカラーを知った世代だからです。
参考:[txt] CAPTURE TIMING   DATA FORMAT
バッファとして使用する内蔵メモリ CAPTURE_BUFFER_DPRAM は Simple Dual Port RAM で使用しています。 CAPTURE_CONTROLLER 側が書き込みのみ、LPC2148 側が読み出しのみですが TEST レジスタの設定により LPC2148 側から書き込めるよう繋ぎ変えできます。

以上 開発ツールは ISE 12.4 Webpack を使用しました。ゲート使用率(?)は 見方がよくわかりませんが xc3s50 で半分ぐらいです。
FPGA への書き込みは 自作の FPGA ライター で行いました。今ベースにしている DELL PC にパラレルポートがあったため jtagw は使っていません、やっぱり直接接続は便利…。

私わけのわからない中間ファイルがわさわさある状態が我慢できないので毎度 「Cleanup Project Files」しているのですが、今ひとつ必要十分に削除して くれないので Makefile に記述して自前で clean しています、 どうだ きれいだろ。 また top.bit から top.mcs の変換もこの Makefile から iMPACT バッチモードを起動して行っています、便利。
それと、ファーム屋として verilog 記述のスタイルに心を砕いたのですが どんなもんでしょうか。

自分では一応同期回路の素養はあった(過去形、LS-TTL の頃)と 思っているのですが、なにぶんブランクが長いですし verilog も素人です。 いろいろあるでしょう、突っ込み大歓迎です。
それにしても何気に 100んMHz の回路が動かせてしまうなんて、 感慨しきりです。

(目次)

LPC2148 ファームウェア

arm/* をご覧ください。

前作 ArmUZK で作成した Framework を ほぼそのまま(*2)利用して Mass Storage Class, Bulk Only Transport (BBB(*1)) を実装しました。開発環境も同じ WinARM + FlashMagic で UART debug です。 例によって、USB の VID/PID は世を忍ぶ仮の番号(0x0547/0xfffe) を使用しています。ご留意ください。
(*1) CBI に対して、コマンドもデータもステータスも BULK 転送を使用する ということで BBB と称します。
(*2) USB_ISR() から各 Endpoint 処理への分岐は 無駄が多かったので少々改良しました。
FPGA やらなしの LPC-H2148 単体でもドライブアイコンも出ますし そこそこ動きます。'wvgaC.exe -t 1000' で転送レートの測定もできました。 SCSI レイヤーの実装は まぁいんちきですが、この程度で OS の持つ 標準ドライバを使っての大容量データ転送が扱えるということで。
参考:[txt] SCSI COMMANDs
USB のデータ転送は割り込みハンドラで、他のジョブはポーリング処理で、 という形でダブルバッファーの並列処理を実現していますので、 読まれる方は まずは各関数がどちらのコンテキストで実行されるか を意識されるとよいと思います。
USB のデータ転送に DMA は使っていません。 後述する動作シーケンスにも書きましたが、 USB データ返送と FPGA からのデータ引取りが 重なるケースでは CPU を取り合って効率が 悪くなりますので DMA が有効そうではあるんですが…。
伸び代としては 後は LPC2148 を 48MHz で動かす、パラレルバス止めて SPI にしてみる、というのもあります。 (clock up を試される場合には FPGA の PLL の倍率もケアして下さい)

その際、割り込みハンドラと通常タスク両方からアクセスされるリソースは 競合防止の排他処理(実際は割り込みマスク)を施す必要があります。 特に FPGA へのアクセスは、FPGA 内部のアドレスポインタが上書きされるため 決して重なってはいけません。割り込みハンドラから FPGA をアクセスするのは EINT3 の割り込み要因クリアがありますのでお気をつけください。 まあ ダメなら FPGA に入力ピンを増やしてモードを分け、アドレスポインタを 二つ持たせる、とか割り込みクリアピンを作るとかできるわけで これが FPGA 併用・同時開発のおもしろい所でしたね。
思いつく→回路直す→HDL変える→firmいじる→exeもいじる のループが続くと一人三役に耐えられなくて 気が狂いそうになりましたが…
また上の WinARM の gcc には __attribute((interrupt())) 属性にバグが あるようでスタックポインタを間違えて暴走しました。対策は scsi.c の eint3_handler() 記述の最寄に書いてありますので興味のある方は ご覧ください。

vconsole.c にあるのは UART ベースのハードウェア評価ツールです。 開発当初は大活躍で、キャプチャー動作の評価もこれで やってました

組み込みファームが一応本業(*3)なのでがんばりましたが、例外処理関係ほかの 煮詰めがちょっと足りないかもしれません。大バグ 5つぐらいあるかな?
開発環境の DELL マシンでは MASS_STORAGE_RESET request が どうしても発行させられませんでしたのでデバッグできていませんし、非同期の USB RESET への完璧な対応は現状の構成では無理な気がしていますが、 このあたりはそもそも問題を起こさなければ…。
(USB RESET は XP では時間差で 2回くるようなので これがうまいこと状態をリセットしてくれるような気がしています)

最後に、本機は USB Bus Power Device としての実装されてますが、Suspend での電流低減は入れましたが それは気持ちだけで、 他 規格を遵守するまでの実装はされておりません。

      (*3) そんなわけでこの項目はそっけないのです。 また気が向いたら解説でも書きますか。

(目次)

windows 用アプリケーション wvgaC.exe

win/wvgaC-XXX.exe は vgaC を扱う総合 windows アプリケーションです。 例によって Borland C++ Compiler 5.5.1にて作成しました。 動作の評価は windows XP SP3 と windows 7 x64 SP1 にて行っています。

コンソールベースの色合いが濃いので、ダブルクリックでなく コマンドプロンプトから起動することをお勧めします。
capture window の「閉じる」ボタンは殺してありますので、 コンソールから "ESC" キーで終了して下さい。
オプションなしではキャプチャーモードが起動します。
-t オプションではデータ転送レート測定ほか USB TEST モードを実行します
-u オプションでは LPC2148 のファームウェアの書き換えができます。
ソースは -S オプションで表示できます。
その他、下のスクリーンショットの help をご覧ください。

wvgaC.exe は、ターゲットの vgaC が見つからない場合には自動的に vgaC エミュレーション機能を使用するように実装してありますので ハードウェアが無くても おおむねの機能をお試しできます。

アイコンのバイナリをここ

スクリーンショット
[ss] コマンドラインオプション
[ss] キャプチャーコマンド説明
[ss] キャプチャー時の画面表示
[ss] vgaC が検出できない場合はエミュレーションで
[ss] エミュレーションでの擬似キャプチャー画面
[ss] USB 通信テストモード実行例
[ss] ファームウェア書き換えモード実行例
各キーに対応したコマンドで、FPGA のレジスタを操作するイメージで使用 しますのでかなりとっつきにくいかもしれません。 液晶ディスプレイの設定方法の、クロック・フェーズ・ポジションとか の仕組みを理解されているときっと慣れるのは早いでしょう。
エミュレーションモードで練習されるといいかと思います。 まずは 'n','m' で BIAS の具合を味わっていただいて、 次に 'yuio' でポジション変更を見ていただいて、 その後は '.' で slow モードにして 'hjkl' で領域指定あたりを 見られるといいかと思います。
パラメータを変えずにモードだけ変えて評価するため、 一回のキャプチャーあたりのライン数をバッファ容量にあわせて自動計算する 機能が、コマンドによって入る時と入らない時があります。 コンソール画面が 'だーっ' と流れてスキャンに失敗するような時は とりあえず '=' キーを叩いて再計算させてみてください。
後エミュレーションでは起こさないのですが、横に長くキャプチャーして H-SYNC の領域も入れてしまうと連続ラインをフォローできなくなって 1V-SYNC 周期毎に 1ラインしかキャプチャーできなくなりタイムアウト、 というケースもあります。そんな時は 'q' コマンドでサンプル周波数を上げると とりあえずまるく収まる(ことが多い)です。

windows アプリはやっとこ調べながら書いています。突っ込み歓迎です。 つーか どなたか粋なアプリを書いていただけませんか?

(目次)

動作シーケンス

[osc] Seq1: Single buffer mode, continuous

Seq1 が、基本となる Single buffer の逐次処理でのキャプチャーの流れに なります。
各信号は上から、 です。

基本動作の流れを Seq1 に従って以下に説明します。
キャプチャー実行の SCSI コマンド CDB_VGAC_CAPTURE が CommandBlockWrapper にて到着すると、LPC2148 は FPGA にパラメータを書き込んで実行を指示します。 FPGA は、サンプル対象のラインが現れるまで待ち、TARGET_LINE が現れたら サンプリングを開始します。指定された本数のキャプチャーが終了すると、 FPGA は割り込みにて LPC2148 に通知します。終了を通知された LPC2148 は FPGA のバッファから自分の内部バッファにデータを採取します。
全データを取り込み終わった後、USB にこれを流してホストに返送し、 最後に CommandStatusWrapper にて終了報告をして CDB_VGAC_CAPTURE コマンドの処理を終了します。
ホストは受け取ったデータを処理(wvgaC.exe では画面描画スレッドに渡す) してから次のコマンドを発行し、上が繰り返されることになりますが、 この流れのなかではホスト PC の処理はうんと早く、 流れの中で占める割合は非常に小さいです。
Single buffer の逐次処理でのキャプチャーは 基本ではあるものの、 各処理が直列で 遊んでいるユニットが多いため効率がよくありません。
そこで LPC2148 のバッファを、FPGA からの受け取り用と、USB 返送用の 2つに増やして処理の並列度を上げます。いわゆる Double buffer ってヤツです。
[osc] Seq2: Double buffer mode, single shot #1
[osc] Seq3: Double buffer mode, single shot #2
[osc] Seq4: Double buffer mode, single shot #3
上の 3枚は、Double buffer モードでの単発のキャプチャーの様子を 計測したものです。
Seq2 のように、Double buffer モードの場合、コマンド受領後すぐに データ返送を開始します。そしてデータを返送し終わったら CSW を送信しコマンドの処理は終わりです。
  えっ!
実は返送するデータは一つ前のコマンドでサンプルしたデータになります。 逆に今回のコマンドでサンプルしたデータは次のコマンドのために 取っておくことになります。
データの位相はズレますが、上記の例ではホスト PC はほとんど待たされていない ことがわかります。そして次のコマンドが来る前に、サンプルが終了すれば 大成功です。
ちなみに CBW/CSW の前後に割りと大きく時間が空いているのはデバイスドライバの 動作仕様と思われます。非力なデバイスがついてこられる ようにわざと待ちを入れているようです。

ここで、latency が変わった場合には USB でのデータの返送と FPGA からの データの採取が重なる場合があります。Double buffer モードではこのために バッファを二つ持っているのでこれらは並列動作が可能なのですが、 本システムでは USB 返送も FPGA からのデータ採取も CPU が介在して行っており、 しかも USB 返送は割り込み内で処理しているため USB 返送が優先され、 FPGA からのデータの採取は細切れになり時間がややよけいにかかります。 上の Seq3、Seq4 がその例です。

では次に Double buffer モードの連続の場合を見てみましょう。
[osc] Seq5: Double buffer mode, continuous
[osc] Seq6: Double buffer mode, continuous+TUR
単発では無駄がなくなってすべてうまくいくように見えた Double buffer モードですが、連続ではやはり限界があります。結局 FPGA からの採取が終了する 前にホスト PC から次のリクエストが来てしまいます。PC 速すぎ!
返送するデータが用意できてないので、リクエストされた前データの返送は 待たせざるを得ません。
まあ それでも 全体として画面更速度を量るフレームレート は Double buffer 方式の方がおおむね性能がいいです。 データ採取完了を待たずに取れた分だけ返送する FIFO + full-empty 制御という 手法もありますが、まぁ宿題ということで。
Seq6 では、wvgaC.exe からのリクエストの合間に OS からのメディア存在確認の CDB_TEST_UNIT_READY+REQUEST_SENSE のやり取りが入って ちょっと息を 継ぎますが、それも春の夜の夢、あるいは焼け石に水、 すぐ元にもどってしまうでしょう。

以上、処理の流れを見てきましたが、FPGA にキャプチャーを指示してからの 待ち時間がヤケに長いことに気が付きましたでしょうか? IN_CAPTURE が High になってから TARGET_LINE が High になるまでの 時間のことです。
これが「latency」です。FPGA はキャプチャーを指示されても指定された ラインが来ないことにはサンプルを始められませんので、これまでの図内で 「latency」と書いてある待ち時間が発生します。 latency ってなに、どうして?
[osc] V-SYNC vs TARGET_LINE
上図はキャプチャー中の V-SYNC と TARGET_LINE の関係を計測したものです。 ここで wvgaC.exe は、画面の上から下へ順番に埋めるように TARGET_LINE (と本数)を指定しています。
最初のコマンドでは指定された TARGET_LINE は、V-SYNC の 1.12msec 後にやって来て、そこからサンプルが 0.8msec 分行われています。
ライン番号は V-SYNC を基準に数えますので繰り返しやってきます。 先のコマンドに引き続く領域を指定した次のコマンドでは、TARGET_LINE は 基準の V-SYNC から (1.12+0.8)msec 後に、さらにその次は (1.12+0.8+0.8)msec 後に現れるわけで、(ちょっと測定誤差がありますが) 概ねそのような時間間隔で キャプチャーが行われる部分が V-SYNC 基準でずれていっていることがわかります。

このように目的のラインは、その同期信号の周波数に従って繰り返しやってくる ものの、ライン番号を指定してキャプチャーを行うこちらとしては開始の タイミングによって待ち時間が必ず発生してしまうわけです。
これはあたかも乗り物に乗るタイミングの話に似ています。例えば、毎時00分に 電車がくる駅があったとして、10時00分の電車に乗るのには 9時30分に駅に着いても 9時45分に駅に着いても乗る列車が同じ、すなわち到着の時間も同じ、なのに 似ています。
しかしながら 8時59分に着けば話は別です。一本前の電車に乗れるので うんと早く目的地に着くことになります。逆に 1分遅れただけで 1時間後になりますので遅れが 1時間に拡大されます。

実際の電車の場合と違って、今回のシステムのキャプチャー動作では 対象のラインは指定しますので、例えば全体で 500ラインあるとして、 0ラインからのキャプチャーを指定した次は 25ライン、 では一周以上後になってしまいますので、 例えば 0ライン→250ライン→25ライン→275ライン…、と半周単位で指定をする という手があります。これが「skew」と呼ばれる手法ですなんですが、 wvgaC.exe の場合、画面がとびとびに更新されると見ているほうがわけが わからなくなるので、上から下へ連続的にキャプチャーするか、下から上へ 連続的にキャプチャーするか、の選択にとどめています。('z' コマンド、 上から下だとサンプル開始の周期は(一周+本数)であり、 下から上だと(一周-本数)になって間隔が狭まる)
それともうひとつ、wvgaC.exe が使用される PC の性能がわからないので、 半周飛ばしでうまくいく PC とやっぱり間に合わない PC があるだろうという 点もあります。latency に合わせてベストチューニングすると得られる効果も 大きいですが、これ はずれると一周後になり落差も大きいのです。
半周ずらしを例として使いましたが、ようは駅に着く時間 を見計らって そのちょっと後の電車を狙うように指定する、 ということです。
まったく別の解もありまして、各ステージおよび各ステージ間のデータの 処理速度をキャプチャーデータレート以上に設計できれば、いわゆるパイプライン 的に(ステージ間で遅延を伴いながらも)ずるずる流すという手が考えられます。 が それは USB FullSpeed + コマンドドリブンな SCSI のシステムには 望むべくも無いことなので、今回は考えていません。

(目次)

消費電流

FPGA ユニットとして FRK-S35(xc3s50)を使用した場合の 全体の消費電流は だいたい以下の通りです。 (デジタルテスターの 10A レンジにて実測)
  LPC-H2148
@ ISP mode
USB Suspend USB connected
  idle   in capture
power consumption
from USB
0.16A 0.15A 0.20A 0.22A
XCM-301-200(xc3s200) では FRK-S35 に比べて定常的に 0.03A ぐらい増える感じです。 XCM-301-200 はモジュール上にオシレーターを抱いているので その分は不利ですかね。

各ユニット別の消費電流は おおよそ以下の感じです。
  analog block LPC-H2148 FRK-S35 XCM-301-200
power consumption
from USB
0.10A 0.07A 0.05A 0.08A
アナログ回路が一番大食いですが、まぁ 数10MHz 帯域で使う回路としては かわいいもんでしょうか。

FPGA って、100MHz 超で動いている割に意外と喰わないですね。 FPGA クロック停止・動作の差が 0.01A ぐらいでしたので、ほとんど 静的に消費するようです。

なお、USB Bus Power では 本来 Host PC から許可が出ないと 100mA 以上消費してはいけないのですが、 この制御はしていません。 また、Suspend 中は極微小まで低減しなくてはいけないのですが これもやっていません。ご留意ください。

(目次)

USB 転送レートの不思議

LPC2148 を採用したために USB は FullSpeed 接続 (12Mbit/sec) となるわけですが、 手持ちの環境でデータ転送速度を測定した結果、いろいろと面白い状況が わかりました。

ベースとしている DELL PC では、直接接続するよりも USB1.1 HUB を 経由するほうがやや転送速度が上がります。(この理由はわかりません) また USB2.0 HUB を経由するとさらに速度が上がります。

  DELL OptiPlex780
(winXP SP3)
CF-R5L
(winXP SP3)
CF-J10V
(win7 x64 SP1)
direct thru
USB1.1 HUB
thru
USB2.0 HUB
direct thru
USB2.0 HUB
USB2.0 port USB3.0 port
direct thru
USB2.0 HUB
direct thru
USB2.0 HUB
Connection hierarchy fig.01 fig.02 fig.03 fig.04 fig.05 fig.06 fig.07 fig.08 fig.09
Transfer rates 8kB
/cmd
read 609kB/s 657kB/s 999kB/s 609kB/s 899kB/s 991kB/s 954kB/s 553kB/s 394kB/s
write 609kB/s 657kB/s 943kB/s 609kB/s 862kB/s 867kB/s 862kB/s 514kB/s 388kB/s
24kB
/cmd
read 848kB/s 848kB/s 1038kB/s 848kB/s 961kB/s 1066kB/s 1022kB/s 797kB/s 506kB/s
write 848kB/s 848kB/s 980kB/s 848kB/s 915kB/s 923kB/s 919kB/s 721kB/s 498kB/s
Wait near CBW/CSW transaction 2msec
osc.1
2msec
osc.2
0.1msec
osc.3
2msec
osc.4
0.2msec
osc.5
0.2msec
osc.6
0.2msec
osc.7
2msec
osc.8
2msec
osc.9
        番外: Mac OS 10.4: 1msec osc.10

Bulk-Only Transport プロトコルの CBW / CSW のやり取りの前後には 待ち、というか タメがわざわざ挿入されているよう (osc.1〜9 を参照のこと) で、 これはおそらく非力なデバイスに配慮してのものと思われますが、 この無駄時間がトータルの転送速度に効いているようです。 (当然一コマンド当たりの転送長が長くなれば影響は薄まります)

DELL/CF-R5 では、直接接続では USB1.1 である UHCI に認識されており これらのタメが長めですが、USB2.0 HUB を経由することにより EHCI での認識に変わりタメがほとんどなくなります。

CF-J10V の USB2.0 ポートは内部に USB2.0 HUB を内包した形と なっておるようで、UHCI コントローラーがなくなってしまっており、 タメは常に短いです。反対に USB3.0 ポートでは 頑なに長いタメを適用しておるようで 結果 転送速度は遅めです。

vgaC ではシステム全体のバランスの都合で 700kB/sec を越えても さほどパフォーマンスに恩恵はないようですが、 そもそもわざわざ挿入していたっぽいタメを 簡単に無しにしてしまっていいんでしょうかねぇ?

(目次)

パフォーマンス

手持ちの PC (遅いほうと速いほうの 2台)でとったキャプチャーの フレームレートを以下に示します。
各欄の下段はその際のパラメータです。DBL/sgl は 'x' コマンドによる Single / Double buffer モード、up/down は 'z' コマンドによるスキャン 方向、xxL は '+', '-', '=' コマンドによる一回のサンプル本数です。
  640x400
(720x400@70Hzを
25.2MHzで)
640x480
(640x480@60Hzを
25.2MHzで)
1000x770
(1024x768@60Hzを
63MHzで)
xc3s50
(8KB)
CF-R5L
(600kB/s)
color 4.4f/s
(DBL/up/25L)
3.1f/s
(DBL/up/25L)
1.2f/s
(DBL/up/16L)
mono 15.6f/s
(DBL/up/101L)
12.9f/s (+)
(DBL/up/100L)
5.4f/s
(DBL/up/65L)
CF-J10V
(USB2.0)
(990kB/s)
color 4.6f/s
(DBL/up/25L)
3.1f/s
(DBL/up/25L)
1.2f/s
(sgl/up/16L)
mono 20.3f/s (*)
(DBL/up/101L)
15.2f/s
(DBL/up/101L)
5.4f/s
(DBL/up/65L)
xc3s200
(24KB)
CF-R5L
(600kB/s)
color 5.1f/s
(DBL/up/44L)
4.3f/s
(DBL/down/44L)
1.7f/s
(DBL/down/28L)
mono 17.4f/s
(DBL/down/176L)
15.2f/s
(DBL/down/176L)
6.6f/s
(DBL/down/113L)
CF-J10V
(USB2.0)
(990kB/s)
color 5.4f/s
(DBL/up/44L)
4.6f/s
(DBL/down/44L)
1.8f/s
(DBL/down/28L)
mono 17.7f/s (*)
(DBL/up/176L)
15.2f/s
(DBL/down/176L)
7.2f/s
(DBL/down/113L)
データ量が 1/4ですむモノクロモードがまずは圧倒的に速いです。(あたりまえか) そして、Double buffer モードがやはり効率がいいようです。 USB 転送速度の違いはの差は これではよくわかりませんね。

バッファ容量の 8kB/24kB の違いは、それほど極端にはレートに 現れていませんが、(*) を除き大きいほうがとりあえず効果的なようです。
実際には LPC2148 のメモリの都合で、Single buffer モードでは 8kB/24kB フルに使えますが、Double buffer モードでは 8kB/14kB に なります。
wvgaC.exe の現在のシーケンシャルなスキャン指定方式では、次のスキャンは すなわち最短で一周後になりますので、スキャン回数× V-SYNC 周期は 必ず時間がかかります。なので、一回のスキャン本数が多く取れると 総スキャン回数が減りますので高速化に向かうわけです。
しかしながらデータ量も増え、FPGA→LPC2148 も、LPC2148→PC も 転送時間がかかるようになりますので、例えば スキャン本数 1本分の時間差でも一周後に間に合わなくなれば もう一周後まで待たされ大きなペナルティとなる ((+) マークの 100L というのがそうです) ように、 おそらく 24kB モードでは、一回のスキャンで倍取れる代わりにデータ転送に 倍時間がかかって標準で次は 2周後、というふうに「行って来い」 になっていると思われます。
想像だけではいけないので比較データを取りました。 下のケースでは、すべてが 2周後ではなく 時折 2周後、になってますね。 波の見方は動作シーケンスで。

[osc] Seq7: 640x25Lines (Double buffer=8kBx2)
[osc] Seq8: 640x44Lines (Double buffer=14kBx2)

まあバッファーサイズは大は小を兼ねますので 24kB あっても 8kB 分しか 使わないという手もありますか。
そして (*) の逆転は 24kB が遅いというよりは 8kB が偶然ベストタイミングに なったということでしょう。なので本来は、1本ずつ本数を変えて 見なければ本当のところはわからないということになります。 Single buffer モードが速いものも一つありますが、 これもおそらく同様の理由でしょう。

なお PC 側の描画の負荷ですが、SetPixel() をやめて StretchDIBits() 関数で 一括描画するようになってからはものすごく軽くなりました。(笑) 動作シーケンスのオシロ絵でわかるとおり、10msec に及ぶ USB データ転送はハード任せで CPU は休んでいるわけですから 負荷はかかりようがないんだろうと思います。wvgaC.exe のエミュレーション モードでは そのかわりに CPU が仕事してデータをでっち上げますので、 PC によっては重めに負荷が出るようです。

なおページトップのデモムービーでは RealVNC のフリー版を使用しています。 CF-J10V の Windows7(x64) でこれが使えなくなったので代替のものを探しましたが UltraVNC よりかは TightVNC の方が よさげに思われます。
(目次)

他 OS から vgaC へのアクセス方法

FreeBSD 8.3R からは CAM を使って /dev/passN デバイス経由で 通信することができます。
[ss] FreeBSD での転送レート測定 (サンプルプログラム)

Mac OS X 10.4 では OS として認識し、 メディア挿入を待つやり取りが行われている ところまでは確認しましたが、これ以上はまだです。 IO Kit に従えばできる、のかな?
[ss] USB Prober での認識の様子
(お客さまの中に Mac のプロの方はいらっしゃいませんか?)

(目次)

ギャラリー

キャプチャーサンプル
[ss] 720x400@70Hz … BIOS Setup 画面
[ss] 640x480@60Hz … FreeBSD console 画面
[ss] 640x480@60Hz … CF-R5L BIOS Setup 画面 (製造番号は念のため隠しました)
[ss] 800x600@60Hz … CF-J10V BIOS Setup 画面 (製造番号は念のため隠しました)
[ss] 1024x768@60Hz … winXP 画面
[ss] 1024x768@60Hz … CF-J10V で自分の出力をキャプチャーしてみた (*1)(*2)
[ss] 1024x768@60Hz … win7 をハイコントラスト画面にしてみた (*1)(*2)
[ss] 800x600@60Hz … vgaC を 2台つないで Mac と PC を同時に、なんか楽しそう (*1)
(*1) EDID なしの場合、windows 系は 1024x768まで OK として、
      Mac OS X 10.4では 800x600 まで OK として認識されるようです。
(*2) CF-J10V のワイド画面(1366x768)は自動的に
      1024x768 にリサイズされて出力されるみたいです。
ハードウェアその他写真
[photo] 初代の回路
[ss] 基板アートワーク
[photo] ベア基板   (部品面)
[photo] ベア基板   (半田面)
[photo] 開発中
[photo] 通常組立品と逆マウント品   (表)
[photo] 通常組立品と逆マウント品   (裏)
[photo] 通常組立品   (XCM-301-200 を使用)
[photo] フォトモスリレーの追加   (通常組立品)
[photo] 逆マウント品   (FRK-S35 を使用)
[photo] フォトモスリレーの追加   (逆マウント品)
[photo] LPC-H2148 の逆マウント加工   (たいへんでした)
動画
[mov] LED 点灯の様子 (mpg, 21sec, 3.5MB)

(目次)

vgaC の今後

現状の機能と性能には 個人的には だいたい満足しています。細々 バグ修正や小拡張はするとして、あまり大胆な拡張は考えていません。
(とりあえず 「LCX14 は違うだろう」の確認と 1.5bit拡張 は試さなきゃな > 自分)
がしかし無理やり今後のロードマップを描くとすると、 以下のようになるでしょう。
  1. USB 規格を遵守するために FET 等で FPGA/analog 回路の電源を 切れるようにし、
  2. EDID にも対応して、
  3. FPGA の config もマイコンからできるようにし、
  4. USB 2.0 High Speed を備えたマイコンに切り替え
  5. wuzk.exe の機能と有機的に結合したアプリケーションとし、
  6. 評価モジュールでなく LSI 単品を使う専用基板を起こす。

RGB 信号の分解能は 各 1.5〜2.5bitぐらい取れたら もう少しおもしろく なりそうなんですが、ディスクリート部品ベースではきついかもしれません。 データ量も増えますます遅くなりますし。
HDMI は (よく調べてないですが) 扱う周波数が一桁上がるはずなので あまり考えたくありません。EDID で「おれは RGB 1bit のモニターだよ」 と申告して、PC 側がこれに合わせて 1bit データを送出してくれると 遅くていいんですが まぁどうでしょう。
ちなみに現状の形で、LPC-H2148 と XCM-301-200 を購入するだけで \20,000 ぐらいかかります。上の 6. まで行けば \10,000 ぐらいに できるかもしれません。



家庭内サーバーの single user mode でのメンテナンスもこれで面倒なし

(目次)








というわけで、大学の先生方、学生の実習用にいかがですか?
2.54mmピッチから面実装部品(1.27mmピッチ, 2125)までハンダ付けできてアナログ・ ロジック、HDL に組み込みファーム、さらには win アプリまで全部入りですよ。 絵がでると楽しいしサンプリング定理も体感できますす。 おまけに基板には初心者向けの 半田付け練習用のパッドも 用意してありまっせ。(ハンダを流さず四隅に 4山盛れれば免許皆伝)

以上、各種お問い合わせは メールで お気軽にどうぞ

 

    uratan@miomio.jp
upward