橋の配線
2026-09-06 に、公表されている NES-001 のコントローラポートのピン配置、74HCT165 と 74HCT04 と 74LVC245 のデータシート、そして ESP32 のピンの規則から書き下ろし、2026-09-09 に、このコンソールがそれと食い違ったところを訂正した。2026-09-07 には、このディレクトリに写真のある実機材 (IMG_5660 から IMG_5675) に照らして改訂した。ここにある C6 の配線は結局作られなかった。ベンチは v1b で、同じ橋を Arduino UNO に 5 V で載せたものだ (bench-v1b-uno.md、2026-09-15 に組んだ)。ここで測ったもの、ポートのピン配置とポーリングのタイミングは、ベンチのものだ。「まず測る」の下にある行はすべて、このどれかを通してコンソールに電源を入れる前にメーターでする検査だ。ページから写したピン配置は主張にすぎず、ESP32 のピンに乗った 5 V の線は死んだ ESP32 だからである。
同じ配線を回路図にしたもの、頭とリレーとスコープを一枚に載せたものが bench-v1.svg で、tools/draw-schematics.py が描き、tools/check-sheets.py が下の表に押さえている。組む順序と v2 のシートは bench-build-v1-v2.md にある。
写真が決めたこと
- コンソールは開けてある。そして NES-CPU-10 の基板だ (RP2A03G、RP2C02G-0、Sony CXK5816 の SRAM 二枚、SN74LS373N、SN74LS139N、3193A の CIC、74HCU04AP。RF モジュールは NES 402TD と刻印)。コントローラポートはそれぞれ自分のハウジングに付いていて、圧着したハーネスで基板の白いヘッダにつながる (
IMG_5666)。だから橋はそのヘッダでハーネスをブレイクアウトで分岐し、延長ケーブルは一本も切らない。線の色はやはり導通で対応付ける。決めつけはしない。 - この基板のポートのバッファは Toshiba TC40H368P だ (U7 と U8、
40H368 (CI)と(CII))。74LS368 の役目に入った CMOS の 40H 系列の部品で、その横に 5.6 K のプルアップ R14 と R15 がある。模型 (nes-glue::controller) は SN74LS368A のデータシートから U9 と U10 として書き下ろしてある。機能は同じ (反転、three-state) で、番号と部品はこの基板のもので、記録として残す。165 の 5 V 出力はどちらも駆動できる。 - 音の段の部品は模型が持っているとおりだ: R6 47 K、C20 と C21 220 pF、C23 1 uF (Rubycon 50 V)、R7 20 K、R8 12 K。すべて
IMG_5669、IMG_5674、IMG_5675で読める。N7 の段は回路図から書き下ろしたものだが、基板は同意している。 - この計画のマイコンは ESP32-C6-DevKitC-1 v1.2 だ (
IMG_5662、IMG_5664)。古典的な ESP32 ではない (組んだ橋は代わりに Arduino UNO を使う。bench-v1b-uno.md): RISC-V、ヘッダに GPIO0 から 23、パルスカウンタが四ユニット、USB-C が二つ (一方は GPIO16 と 17 につながる UART ブリッジへ、もう一方はチップ自身の USB で GPIO12 と 13)。ストラッピングピンの 8、9、15 (それと念のため 4 と 5) は触らない。残るのは十四本の使えるピンで、D0 の監視をやめれば橋が必要とするのはちょうどそれだ。下のピンの表は C6 のもので、ファームウェアは両方の対応表を持っている。 - リセットのリレーは PC817 のフォトカプラのモジュールだ (
Iso_817_X1、IMG_5661): INPUT の + と - は自前の LED 抵抗を通り、出力トランジスタのコレクタが OUT (VCC へのプルアップ付き)、エミッタが GND。オープンコレクタのスイッチとして使う: OUT をリセットボタンのプルアップされたパッドへ、GND をそのグランドのパッドへ、VCC は未接続、Pi のピンはそのまま INPUT + へ。4N35 は使わず、直列抵抗も入れない。 - 頭は Raspberry Pi 4 Model B だ (
IMG_5660)。
考え方を一段落で
電源の領域が三つ、グランドは一つ共通。コンソールの +5 V がシフトレジスタとインバータに電源を与え、この二つがコンソールのポートに向き合って、パッド自身の 4021 と同じくその 5 V のレベルで話す。ESP32 の 3.3 V が、コンソールのラッチとクロックとデータを ESP32 まで下げるレベルシフタに電源を与え、さらに元のパッドにも電源を与えるので、パッドの 4021 は 3.3 V で話し、シフトは要らない。ESP32 の 3.3 V の出力はレジスタの入力を直接駆動する。HCT 系列の入力しきい値は 2 V だからだ。ESP32 は Pi から USB で電源を取る。コンソールの +5 V が ESP32 の電源に触れることはない。
コンソールのポート (NES-001、フロントローダー、7 ピン)
公表されているピン配置、コンソールのソケットを覗き込む向きで。番号の振り方は nesdev とパッドの修理案内が共有しているものだ。信じる前にメーターで確かめること (下記)。
このコンソールで 2026-09-09 に実測。 この表には以前、公表されているピン配置が載っていて、そちらは D3 を 5 に、D4 を 6 に、電源を 7 に置く。この基板については、手順 1.1 と 1.2 がそうではないと言う: 回路から外した導通の確認で、コントローラのケーブルはピン 1 から 5 に五本の導体を通し、6 と 7 には何も通していないことが分かり、それからスコープがピン 5 の線で 5.000 V の平坦を読んだ。この表がいま、ピン配置が書き留められている唯一の場所である。 そして tools/check-sheets.py が、回路図のコネクタの記号と tools/bringup.py の両方をこれに押さえている。
| ピン | 名前 | 向き | 何として使うか |
|---|---|---|---|
| 1 | GND | 共通のグランド | |
| 2 | CLK | コンソールからパッドへ | レジスタのクロック、かつ数える対象 |
| 3 | OUT0 | コンソールからパッドへ | レジスタのロード、反転して。かつ数える対象 |
| 4 | D0 | パッドからコンソールへ | レジスタのシリアル出力 |
| 5 | +5V | 電源。実測 5.000 V。公表の表では D3 のところ | |
| 6 | n/c | コントローラのケーブルが通していない。コンソール側は未測定 | |
| 7 | n/c | コントローラのケーブルが通していない。コンソール側は未測定 |
D0 の押された状態は LOW だ (パッドの 4021 が線を低く引き、コンソールの 74LS368 がそれを反転するので、CPU は 1 を読む)。八つ目のクロックの後、元のパッドは D0 を LOW に保つ。どちらも模型 (nes-glue::controller) に入っていて、どちらもレジスタのシリアル入力をグランドに固定する前に、B0 で元のパッドに対して実測する。
レジスタ: コンソールの 5 V に置いた 74HCT165
74HC(T)165 と 4021 は、この用途では同じ機械だ。八つの並列入力をクロック 1 発につき 1 ビットずつ押し出す。違いは一つ: 4021 は P/S ピンが HIGH のあいだロードし、165 は /PL ピンが LOW のあいだロードする。OUT0 はインバータ 1 段を通るので、165 は OUT0 が高いあいだロードし、その立ち下がりから保持する。模型が書き下ろした 4021 の振る舞いとちょうど同じだ。
165 は QH の方へ押し出し、QH が出力なので、最初に出るビットは入力 H だ。パッドの順序 A、B、Select、Start、上、下、左、右は、したがって H から A へ向かって配線する。
| 165 のピン | 信号 | どこへ |
|---|---|---|
| 16 VCC | +5 V | C6 のシートではポートのピン 5。v1b では UNO 自身の 5 V ピン |
| 8 GND | GND | ポートのピン 1 |
| 2 CP (クロック) | CLK | ポートのピン 2、直結 |
| 15 /CE (クロック禁止) | GND | |
| 1 /PL (ロード) | OUT0 の否定 | 74HCT04 の出力。その入力はポートのピン 3 から |
| 9 QH (出力) | D0 | ポートのピン 4、直結 |
| 10 DS (シリアル入力) | GND (八ビット目の後は LOW、パッドと同じ) | |
| 6 H | A | ESP32-C6 GPIO18 |
| 5 G | B | ESP32-C6 GPIO19 |
| 4 F | Select | ESP32-C6 GPIO20 |
| 3 E | Start | ESP32-C6 GPIO21 |
| 14 D | 上 | ESP32-C6 GPIO22 |
| 13 C | 下 | ESP32-C6 GPIO23 |
| 12 B | 左 | ESP32-C6 GPIO10 |
| 11 A | 右 | ESP32-C6 GPIO11 |
| 7 /QH | 未接続 |
押されたボタンは、その入力の LOW だ。ESP32 は押されたときに 0 を書く。+5 V の 74HCT04: 一つのゲートを OUT0 に、残る五つの入力は GND に落とす。各チップの電源ピンの間に 100 nF のセラミックを一つ。
ESP32 へ下ろす: 3.3 V の 74LVC245
245 の入力は 3.3 V で動かしたまま 5 V に耐え、クロックのパルス (数百ナノ秒) には十分に速い。抵抗分割は ESP32 の入力容量でそのパルスを丸めてしまうので使わない。方向ピン (1 DIR) は A から B へで HIGH、/OE (19) は GND、VCC (20) は ESP32 の 3V3、GND (10) は GND へ。
| 245 の A 側 (5 V 入力) | 信号 | 245 の B 側 (3.3 V 出力) | ESP32-C6 | 役目 |
|---|---|---|---|---|
| A1 | OUT0、ポートのピン 3 | B1 | GPIO0 | ラッチの計数 (PCNT のユニット 0)、ポーリングの番号 |
| A2 | CLK、ポートのピン 2 | B2 | GPIO1 | クロックの計数 (PCNT のユニット 1)、ラッチあたりのクロック数 |
| A3 から A8 | GND に落とす |
C6 には入力専用のピンが無いので、コンソール側は GPIO0 と 1 に座り、スケッチはそれを出力に設定することがない。コンソールから見た D0 は C6 では監視しない (十四本目に回せるピンが無い)。それはスコープが「まず測る」の一覧の中で見る。
元のパッド、3.3 V の橋の上で
パッドはコンソール自身のポートのハウジングの一つに挿す。そのハウジングのハーネスを基板のヘッダから抜いて、代わりに橋のパッド側に挿す。基板のヘッダのピンがコンソール側だ。何も切らないし、コンソールのもう一方のポートはそのままにしておく。
| パッドのプラグのピン | 信号 | どこへ |
|---|---|---|
| 1 | GND | GND |
| 7 | +5 V | ESP32 の 3V3 (4021 は 3 V で動く。2026-09-27 にパッドアダプタで実測、下の項目 4) |
| 3 | OUT0 | ESP32-C6 GPIO2 (出力、橋自身のラッチ) |
| 2 | CLK | ESP32-C6 GPIO3 (出力、橋自身のクロック) |
| 4 | D0 | ESP32-C6 GPIO6 (入力。パッドがそうなので 3.3 V) |
ESP32 はパッドを 1 ミリ秒ごとにポーリングする: OUT0 を 12 マイクロ秒高くし、低くし、それから 1 マイクロ秒ずつのクロックを八つ、各立ち上がりの前に D0 を読む。その八ビットが、パスのモードではレジスタの入力へ行く。
コンソール自身のポーリングが測るもの、そしてそれが一つの数字ではない理由
このコンソールで 2026-09-09、手順 2.1 で実測した。50 MS/s で 1200 万点の記録を、20 分あけて二つ。どちらも自分の中では安定していて、互いには食い違った:
| 記録 A | 記録 B | |
|---|---|---|
| ラッチが高い時間 | 4.44 us | 3.32 us |
| クロックが低い時間 | 0.62 us | 0.600 us |
| クロックの間隔 | 15.64 us | 10.62 us |
| 毎秒のポーリング数 | 60.0997 | 60.0997 |
| ポーリングあたりのクロック数 | 8 | 8 |
2A03 のサイクル 0.5587 us で割ると、これはラッチが 8 サイクルと 6 サイクル、クロックの低が 1 サイクル、クロックの間隔が 28 サイクルと 19 サイクルで、どれも整数サイクルに着地し、二つのクロックの周期は千分の 0.5 より良く合う。
つまりラッチの幅とクロックの間隔は、コンソールのものではなくコードのものだ。 ラッチが高いのは、ゲームが $4016 に二度書く、その隙間のあいだ。クロックの一つ一つは $4016 の一回の読み出し。間隔はゲームの読み出しループだ。二つの走行が二つのルーチンを捕まえた。
動かなかった二つは構造的なものだ。ポーリングあたり八つのクロック、そして 60.0997 Hz でフレームあたり一回のポーリング。これは NES のフレームレートと百万分の 15 まで一致し、それに合わせて当てはめたものではない。
この橋にとっての帰結: 165 は、画面に映っていたものではなく、どのカートリッジがしうる最速のポーリングよりも前に、自分のビットを立てておかなければならない。詰めた展開済みの読み出しは約 12 サイクル、7 us 近くだ。レジスタの整定を中央値に合わせて見積もってはいけない。どの単一の捕捉も、コンソールのタイミングとして扱ってはいけない。
トリガ
ESP32-C6 GPIO7 から 100 オームを通してスコープの背面の EXT TRIG へ (BNC、入力 1 M オーム、トリガレベルは 1.5 V、立ち上がり)。台本のラッチ番号で立ち上がりを一つ。パルスの長さは 1 ミリ秒。
2026-09-15 に実測: このベンチの DS1054Z には外部トリガの入力が無い (SCPI のソース EXT が拒まれる)。そこで v1b ではトリガを同じ抵抗を通して CH1 に入れ、2.5 V の立ち上がりでトリガする。CH1 はコンソールのマスタクロックのために取ってあったが、メイン基板にプローブを当てるまでは空いており、その後は二つが交代で使う。2026-10-24 にリードが動いてからは、CH1 がコンポジット映像を運び、トリガ線にはチャネルが無い (scope-leads.md)。
頭: Raspberry Pi 4
- USB で ESP32 へ (電源とシリアル回線のプロトコル)。v1b では同じケーブルが UNO へ行く。
- Ethernet でスコープがいる LAN へ。Pi とスコープのアドレスは
bench.local.mdにあり、git が無視する。 - GPIO17 を PC817 モジュールの INPUT + へ、INPUT - を Pi の GND へ (モジュールは自前の LED 抵抗を持つ)。モジュールの OUT をリセットボタンのプルアップされたパッドへ、その GND をボタンのグランドのパッドへ、VCC は未接続のまま。リセットは 100 ms 保持する。
- GPIO27 をリレーモジュールの IN へ。リレーのノーマルオープンの接点を、電源アダプタのケーブルからコンソールの DC ジャックへ行く片方の線に直列に入れる (NES-001 のアダプタは AC なので、片方の線の接点でどちらも切れる)。両方の線には決して入れない。商用電源の側には決して入れない。
- ジャンパは四本、ブレイクアウトは無し。 ヘッダがこのベンチに貸すピンはちょうど四本だ: GPIO17、GPIO27、5V (リレーモジュールのコイル)、そして GND 一本。ヘッダから Dupont の線を四本。40 ピンのブレイクアウトはここでは何も買わず、板の場所を食う (2026-09-10 に決定)。
- Pi からコンソールへのグランド線は無し。 Pi のグランドはその USB ケーブルと橋を通ってコンソールに届き、経路はそれだけであるべきだ。Pi の二つのスイッチがコンソールに触れるのは LED (PC817) と接点 (リレー) を通してだけで、この二つが選ばれた理由がまさにそれだ。三本目の線はその絶縁を捨て、二つ目のループ (Pi、USB、橋、ポート、コンソール、線、Pi) を閉じてしまう。「グランド」の節を参照。
グランド
コンソールの GND (ポートのピン 1)、橋の GND のプレーン、ESP32 の GND、そして (USB ケーブルを通した) Pi の GND は一つのネットだ。コンソールの +5 V と ESP32 の 3V3 は、そのグランドだけを共有する二つの電源である。スコープのプローブのグランドはすでにコンソールのグランドに乗っている。
まず測る
メーターで、橋を通して何かに電源が入る前に:
- コントローラのハーネスの線の色を、基板のヘッダ (
IMG_5666) でポートのピンに対して導通で確かめる。表はbench.local.mdに書く。色は証拠ではない。 回路から外して鳴らすこと。 2026-09-09 に実測: コンソールにまだ挿したままのケーブルに音を通すと、コンソール自身のプルアップとポートのバッファを通ってしまい、何も共有していないピンが鳴る。このベンチでの最初の一巡は、ポートの二つのピンを一本の線の上に置き、それが再現した。しゃべっていたのは計器で、ケーブルではなかった。 - コンソールを点け、何も挿さない状態で: ポートのピン 5 とピン 1 の間が 5 V を読み (上のピン配置の表、2026-09-09 に実測)、ピン 2 は高いまま待機し、ピン 3 は低いまま待機し、ピン 4 が高い (プルアップ) を読む。
- コンソールのもう一方のポートに元のパッド、ゲームを走らせて: 使っているポートのピン 2 とピン 3 にスコープを当て、ラッチのパルス幅、クロックのパルス幅と個数、そして D0 の待機と押された状態のレベルを見る。この数字が上の書き下ろしの値を置き換える。
- パッド単体を、ベンチの上で 3.3 V から電源を与え、橋自身のポーリングで: D0 がボタンに従う。2026-09-27 にパッドアダプタで実測 (
pad-usb-protocol.md): 純正パッドの MN4021B は 3.3 V でボタンに従う。30 秒に 27 回の押下、すべてのボタン。純正には二つ目の 74LVC245 は要らない。レプリカは測っていない。 - コンソールを点けた状態でリセットボタンのパッド: どちらのパッドがグランドか、そしてもう一方がどのレベルに座っているか (プルアップされているはずだ)。PC817 モジュールの GND はグランド側へ、OUT はもう一方へ行く。
- OUT0 を手で叩き、ESP32 に既知のバイトを持たせた状態での 165 の QH: パッドの順序どおりの八ビットがスコープに出る。
部品
| 数 | 部品 |
|---|---|
| 1 | ESP32-C6-DevKitC-1 (手元にある) |
| 1 | Raspberry Pi 4 Model B と、C6 の UART ポートへの USB-C ケーブル (手元にある) |
| 1 | 74HCT165 |
| 1 | 74HCT04 (または 1 ゲートの 74HCT1G04) |
| 1 | 74LVC245 |
| 1 | PC817 のフォトカプラモジュール (手元にある) |
| 1 | リレーモジュール、接点はアダプタの電流に耐える定格のもの (手元にあるのは 5 V コイル、アクティブ LOW のオプト入力) |
| 1 | コントローラのハーネスのヘッダ用のブレイクアウト、またはそれを引き出すための圧着ピン |
| 3 | 100 nF のセラミックコンデンサ |
| 1 | 100 オームの抵抗 (トリガ) |
| 1 | 空いているチャネルへ入れるプローブか BNC。v1b では CH1 (DS1054Z に EXT TRIG は無い) |
| ブレッドボードかユニバーサル基板、線材 |
ビルド時に nes-bench/docs/wiring.md から取り込まれる。写しはリポジトリの一つだけだ。報告は独自の作業用の言葉をいくつか使う: 報告書で使われる言葉。