Tang-Nano-9Kで動くＮＥＳに、ゲームパッドをUSBで繋ぐ

# 目的
　Tang-Nano-9Kで(限定的だが)NESを動かせる事が出来たので、次のステップとして単体動作を夢想する。
　データは内蔵RAMに書き込むか、SDに格納できる筈。
　LCDは見本がそこそこ有るから、後は操作するGamepadの接続かな。
　ちらっと見た限りでは、USB接続のものしか見当たらない。
　配線をばらしてディスクリート接続すると言う手も有るが、
　◆◆◆　そうだ、Tang-Nano-9KにUSB接続でつなげよう　◆◆◆
　USB1.0なら見本が有るから、何とかなるでしょう。
![ukp_全体.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/435c4344-4c81-e7c0-7587-43263bf0ed56.jpeg)


# 方針
　USBは1.0(1.5Mbps)から始まりUSB4(40Gbps)迄進化してるが、今回は1.0のロースピード。
　　※USB1.1は仕様の明確化のみ、1.0と規格は同一。
　USB1.0には速度の異なる2種類のグレードが規格化されている
　　Low-Speed　ロースピード 1.5Mbps
　　Full-Speed　ハイスピード 12Mbps
　12Mbps程度ならFPGAで十分制御可能な筈だが、High-Speed動作では18mAの定電流駆動が必要。
　これは、Tang-Nano-9Kの入出力端子ではドライブできない。
　　※やってみたら、無視できない遅延が発生していた。
　従ってGamepadは、通信がロースピードのみの対応とする。

　FPGAでのUSB接続例はジオシティーズに２０年前に公開されていたが閉鎖され今は下記に。
　　「[FPGAでPC-8001を作る計画](http://kwhr0.g2.xrea.com/hard/pc8001.html)」
　このプロジェクトのUKP部分を切り出しそのまま使えばよかったのだが...
　新たなconfigデータが必要になる事を考慮し、先行して機能拡張を推進...
　一応拡張できたので取り合えず本家ukpの初期化データで動作させた所、そのまま動作してしまった。
　　※購入したGamepadがHID機器と同一のコマンドで動作するとは。
　　※このGamepad、安かったけどキーストロークが長くアクション操作には不向き。
　やって来た事のかなりの部分が、特に要らない事になってしまった。
　小さくまとめ上げるのであれば、本家ukpを使った方が効率良いと思う。
　　※但し、本家ukpでは外部信号を直接使っている部分が有り、誤動作するかも。

　なお、本家ukpに対し下記を拡張している。
　　アドレスを8bitから12bitに拡張。
　　12bitアドレスでジャンプ可能なjmp命令追加。
　　jmpした番地に戻れるret命令追加。
　　送信データのNRZ変換機能を追加。※本家ukpはNRZ変換後のデータを扱う。
　この追加により、新たなコマンドの追加が容易になっている(はず)。


# 成果物
　「[fpganes Tang-Nano-9K バージョン](https://github.com/hi631/tang-nano-9K/tree/master/NES/fpganes)」
　「[fpganes Tang-Nano-9K ローダー](https://github.com/hi631/tang-nano-9K/tree/master/NES/loader)」
　「[fpganes Tang-Nano-9K モニター](https://github.com/hi631/tang-nano-9K/tree/master/NES/mon)」


# 必要な追加機器
　□GamePad　※ロースピード(1.5MHz)で動作するもの。
　□USBコネクタ(メス)

　あると便利
　□ロジックアナライザー
　□USB中継基板


# 機能概説
　UKPは接続されたデバイスを、HID接続として動作させている。
　以下機能を、UKPハードと、UKPソフトと、UKPI/Fに分けて説明する。

　□UKPハード
　　12MHzのクロックで動作し、1/8分周して1.5Mbpsの信号を作成。
　　　※PLLが不足しているので、126MHzを1/10.5分周して約12MHzを作成。
　　　　ない物ねだりだが、もそっと何とかならないみのかな。
　　ホスト側にはプルダウン抵抗が必要だが、FPGAの内部抵抗で代用。

　□UKPソフト
　　ソフトはコマンドの送信と受信から成り立ってる。
　　初期化時はsetadr1でUSBチャネルを1に設定後、setconfig1でconfigを送信する。
　　コマンド送信後はrcvdtでACKを受信する(が読み飛ばす)。
　　初期化後はin10を定期的に発行し、デバイスからのデータを受信する。

　　ソフトはukprom.vに、通常のverilogと同形式で書き込む。
　　ukp.sをasukpでアセンブルすると、コンパイル可能なukprom.vが出来上がる。
　　asukpを動作させるには、perlの動作環境が必要。
　　　※今回使用したukp.sとasukpは[fpganes Tang-Nano-9K バージョン]に添付。
　　　※当方はmingwin32環境で実行、./asukpと打てば動作する。
	  
　□UKPI/F
　　初期化が完了すると、ホストからのリクエストにデバイスが応答を返す。
　　下図は応答の一例だが、ukprdyがhiの期間にukpstbが8回動作する。
　　そのタイミングでukpdatを読み取る。
　　読み取ったデータをukp2nesで、fpganesが必要とする形に変換している。
　　　※当方のGamepadでは、押さなくても毎回応答が帰って来てる。
　　　※参考資料はGamepadにしか対応していない。
![ukp_波形.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/d78fe8d6-3bbb-e920-c6b3-ef6391ee4df3.jpeg)

# ロジアナ
　波形解析とプログラムデバッグには、ロジアナが有効だった。
　　※USB波形解析とか、周期の長い信号の観測に威力を発揮。
　　※USBも含め２５種類の解析が出来るらしい。
　20年前はUSB1.0の波形観測も一苦労だったのだろうが、今では簡単に行える。
　　※多少の投資は必要だが、便利な世の中になったものだ。
　最大サンプリング速度は100Mbps。
　計測データはUSB2でパソコンに送るので、HDDが許す限り計測できるだろう。
　　※但し100Mbps計測時は2チャンネルしか使えない、USB2の速度制限だろう。
　　　更に、別のUSB機器が動作時は速度制限される。
![ukp-logic.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/b0e45f0c-2435-ae39-dada-a77f78ec2964.jpeg)　
![ukp-log_sig.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/478c717c-98d4-efc9-650b-a25b01c48a1e.jpeg)


# 感想
　UKP機能の切り出しと動作確認中にタイミング処理をミスっていて、keyboardは動作するがGamepadは動作ないと言う珍現象に陥ってしまった。
　この動作により、てっきりconfigから作り直す必要が有ると勘違いして、機能拡張を行った。
　まあこれも、今後別のUSB機器を使う時に役立つ技術だと自己弁護をしておこう。
　なお、上記記載内容は全て無保証であり、各自の責任においてご利用願います。