自作CPU向けメッセージングプロトコル
複数の自作CPU(自作コンピュータ)をリング状につなぎ、メッセージの送受信をしたい。
プトロコル名は MSMP とする。Make-cpu Simple Messaging Protocol 方針
貧弱なCPUでもメッセージングの輪に参加できるよう、なるべくシンプルな仕様にする。
そのためにかっちょいい利便性などが犠牲になることは仕方ない。
データバス幅が8ビットのCPUでも簡単に実装できる仕様とする。
駆動電圧の違いやリレーコンピュータの存在も考慮した仕様とする。
ノード間の接続
リング状に接続する
自身の送信端子を次のノードの受信端子へ。
https://gyazo.com/22a5bc79983cc1b28dd34cfb8d03fbc1
物理層
MIDIのようなオプトアイソレータを電流駆動する方式とする。
電気的に絶縁することで、リレーコンピュータが発する強いノイズの影響を緩和できる。
電流駆動とすることで、制御電圧の違いを吸収しやすい。
電線を直結するより複雑だが、他参加者の大事な自作CPUを壊さない仕様にしておけば、かえって参加ハードルが下がるのではないか(ちぇりーさん談)。
基本はMIDIの電気仕様に従えばよい。
uchanはこの回路でインターフェース基板を作る予定。 信号の仕様はUART 9600bpsとする。
スタートビット:1ビット
データ:8ビット
パリティ:無し
ストップビット:1ビット
参加者同士が合意すれば速度は変えても良い。
論理0を電流が流れている状態、論理1を無電流とする。
UARTの無信号時は論理1→電流は流れない。
UARTのスタートビットは論理0→電流が流れる。
このように定義しておけば、無信号時に電流が流れず消費電力を抑えられる。
MIDIの電気仕様と同じ。
コネクタJ1、J2ともにJSTのXHコネクタとする。
3ピンで、ピンアサインは次の通り。
1:VDD
2:SIG
3:シールド
https://gyazo.com/52d5e774a30483fdb1508135a1b1932f
コネクタJ3は自分のCPUとの接続なので仕様では規定しない。何でも良い。
ケーブルはシールド付き2芯ケーブルとする。
可能ならツイストペアケーブルを使う。
論理層
メッセージはヘッダと本文で構成される
code:メッセージの構成
byte 7 4 3 0 意味
0 dddd ssss dddd=宛先アドレス(DST)、ssss=送信元アドレス(SRC)
1 ttll llll tt=メッセージ種別(TYPE)、llllll=メッセージ長(LEN)
2 xxxx xxxx これ以降がメッセージ本文
アドレス0は未使用、アドレス15はブロードキャスト
TYPE=0は通常のメッセージ、TYPE=1~3は予約
自身のアドレス宛のメッセージを受け取ったら受信し、次のノードには何も送らない。
自身のアドレス宛ではないメッセージなら次のノードにまったく同じバイト列を送る。
本文長は0~63バイト。
本文に0x00が現れてはいけない。
0x00はメッセージ同期信号
もし本文の受信中に0x00が検出されたらそこで本文受信を中止し、次のバイトを新しいメッセージの先頭として扱う。
TSM: メッセージ同期用メッセージ
0xFx 0x00 という2バイトをタイミング同期用メッセージ(TSM: Timing Synchronization Message)とする。
DST=15としてブロードキャスト
SRC=xは最初にメッセージ同期用メッセージを送出したノードのアドレス
LEN=0なので、本文は無し
正常に受信できているノードは特段何も気にしなくて良い。
本文が空のブロードキャストとして、単に次のノードに同じ2バイトを送るだけで良い。
もしバイト欠落などの理由で、予期しないタイミングで0x00が受信されてしまったノードは、次のバイトから新しいメッセージとしてタイミングを補正する。
このノードは 0xFx 0x00 を次のノードに転送することができない可能性がある。
なぜなら、0x00を読み出した時点でその1つ前の受信データを破棄しているかもしれないから。
TSMを最初に送ったノードが、いつまで経っても同じメッセージを受信することがない場合、タイミングが壊れたノードがリング上に存在した可能性がある。
同じメッセージを受信するまでTSMを再送することで、全ノードのタイミングがリセットされる。
送信待ち時間
自作CPUの作りによっては潤沢なUART受信バッファを持たないため、続けて何バイトも送るとデータを取りこぼす可能性がある。
物理層ではハンドシェイク機能を提供しないため、ソフトウェア的に対処する。
ノードは、連続してバイト列を送る際、間隔を空けて送信する。
送信間隔は、できれば設定可能にしておくこと。デフォルト値20ms。
ハードコードする場合は送信間隔を20ms以上とする。
参加者間で合意すれば短い送信間隔でも良い。
静的アドレス割り当て
自身のアドレスを手動設定できるようにしておく。
「自作CPUを語る会」などの展示会場では、用意されたアドレス割り当て表に従って自身の作品のアドレスを設定する。
アドレス割り当て表は何らかの方法で用意する。
典型的には、展示会当日、リングバスを実演したい参加者のうち誰かが作成する。
あらかじめ参加者が判明している場合、事前に表を作ることもできる。
table:アドレス割り当て表の例
名前 アドレス
NLP-16A(ちぇりーさん) 2
ComProc(uchan) 3
展示会場でぱっと手動設定できる仕組みがどうしても作れない場合、展示の参加者間で相談し、アドレスの事前割当をしてもらうこと。
アドレス重複確認
これは仕様ではないが、やることをおすすめする。
自身のアドレス宛のメッセージに乱数列を載せ、送出する。
同じメッセージが戻ってくれば、リング上に同一アドレスのノードが居ないことが確認できる。
code:アドレス重複確認メッセージ
byte 7 4 3 0 意味
0 ssss ssss DST=SRC とする
1 0000 0010 通常メッセージ、長さ 2
2 rrrr rrrr 16 ビットの乱数列
3 rrrr rrrr
自身宛だがByte2,3が異なる値のメッセージが受信されたら、アドレス重複が起きている。
あるいは、身に覚えの無い自分宛メッセージが受信されてもアドレス重複が起きていることが分かる。
受信された自分宛メッセージは、たとえ自分が送ったものでなくとも、次ノードへは流さず、読み捨てる。