FF01 - SB - シリアル転送データ (読み込み/書き込み可能)
この IO レジスタを通して、 8 ビットのデータを読み書きします。
FF02 - SC - シリアル転送コントロール (読み込み/書き込み可能)
Bit 7 - 転送開始フラグ (0 = 転送停止、 1 = 転送開始・送信中)
Bit 1 - クロック速度 (0 = 通常、 1 = 高速) ** [[ゲームボーイカラー]]のみ **
Bit 0 - クロックの選択 (0 = 外部クロック、 1 = 内部クロック)
SB レジスタ (FF01) で転送される、クロック信号の設定をします。
ゲームボーイ本体が他の本体 (または他のコンピュータ) と通信する時、
片方は内部クロックを使用し、もう一方は外部クロックを使用する必要があります。
内部クロック
ゲームボーイカラーモードでないゲームボーイは、 8,192 Hz 固定になります (1 KB 毎秒の速度です)。
ゲームボーイカラーモードでは、 SC レジスタのビット 1 を使用することで、 4 つの中からクロックを選択することができます。
8,192 Hz - 1KB/s - Bit 1 = 0 (通常速度)
16,384 Hz - 2KB/s - Bit 1 = 0 (倍速モード)
262,144 Hz - 32KB/s - Bit 1 = 1 (通常速度)
524,288 Hz - 64KB/s - Bit 1 = 1 (倍速モード)
外部クロック
外部クロックは通信相手のゲームボーイ (または別のコンピュータ) から提供され、スピードは任意になります。
モノクロのゲームボーイの場合、外部クロックの速度は 500 KHz まで認識できます。
一方、最小の通信速度は決まりがありません。
1 ビット / 1 か月の速度が指定されたとすると、次のビットが転送されるのを、ひたすら待ち続けることになります。
クロックが一定間隔で送信されない場合でも通信できます。
タイムアウト
外部クロックを使って通信している時、最後のビットが転送し終わらないとします。
相手方のゲームボーイの電源が切られるか、ケーブルが切断されてクロック信号が来ない時、通信は完了しないことになります。
この問題を解消するため、通信処理では、タイムアウトカウンタを使って、一定期間データを受信できない時には、通信を停止させる必要があります。
遅延と同期
内部クロックを使っている方のゲームボーイは、相手方のゲームボーイが、次の通信の準備をするための十分な時間を空けるために、
送信するごとに、常に少しの時間、遅延の処理を入れる必要があります。
言い換えると、外部クロックを使っている方のゲームボーイは、内部クロックを使っている方のゲームボーイが転送を開始する前に、
転送開始ビットをセットする必要があります。
ゲームボーイ同士が通信する時、内部クロック側、外部クロック側を 1 バイトの転送のたびに切り替えることで、同期させることができます。
転送開始フラグをセットすることで、転送の処理が開始されます。
このビットは転送終了後、自動的に 0 にセットされます。
このビットを読み込むことで、通信中かどうかを判断できます。
INT 58 - シリアル割り込み
転送が完了した時 (8 bit のデータの送信・受信が完了した後)、 IF レジスタ (FF0F) のビット 3 で、
割り込みリクエストがセットされます。
割り込みが有効になっている時、割り込みベクタの 0058 が呼び出されます。
その他
シリアル通信データの、送信と受信の処理は同時に発生します。
受信されたデータが、 SB レジスタへ自動的にセットされます。
ゲームボーイのシリアル I/O ポートは、 RS-232 (IBM-PC) や RS-485 (Macintosh) に比べて、
かなり簡素な構造になっていて、スタートビット、ストップビットがありません。
転送中、 SB レジスタの 1 バイトのデータはシフト入力されると同時に、シフト出力されます。
シフトの速度は、内部クロックまたは外部クロックで指定されます。
最上位ビットから順番に、シフト入力、シフト出力されます。
内部クロックが使われている場合、通信ポートのクロックピンは、未使用時に High になります。
転送中は、 1 ビットの入出力ごとに 8 回 Low になります。
最後のビットが出力された時の状態が、出力ラインの状態になります (次の転送が発生するまで)。
相手方のゲームボーイが接続されていない時、内部クロックを使用する側のゲームボーイは、
FFh の値を受信します。
次のコードは、シリアルポートから 75h の値をシフト出力し、 FF01 へシフト入力された値が入ります。
ld a, $75
ld ($FF01), a
ld a, $81
ld ($FF02), a
▼赤外線通信コントロールレジスタ
名前
RP
アドレス
FF56h
ビット
Bit 7-6 - 受信機能の有効/無効
00: 無効
11: 有効
Bit 5 - 未使用
Bit 4 - シリアル通信ポートのPin4端子の入力
0:Low
1:High
Bit 3-2 - 未使用
Bit 1 - 赤外線入力
0:OFF
1:ON
Bit 0 - 赤外線出力
0:OFF
1:ON
説明
赤外線通信ポートを制御するレジスタ。Bit0で、赤外線LEDをON/OFFし、Bit1で、赤外線の入力を読み取る。赤外線通信を利用しないときは、00hをセットし、消費電力を節減する。
赤外線の入力は、システムクロックの立ちあがり時に検出される。
通信機能の関数
▼シリアル通信の送信開始
構文
#include <gb.h>
void send_byte(void);
戻り値
なし。
説明
グローバル変数UBYTE _io_outの値をシリアル通信ポートから送信する。また、グローバル変数UBYTE _io_statusには、通信状況が代入される。尚、送信開始前に、相手機を受信開始にしておく必要がある。
■通信状況 UBYTE _io_status
IO_IDLE 待機中
IO_SENDING 送信中
IO_RECEIVING 受信中
IO_ERROR 送信エラー
関連項目
receive_byte
▼シリアル通信の受信開始
構文
#include <gb.h>
void receive_byte(void);
戻り値
なし。
説明
シリアル通信ポートからの受信を開始する。受信後は、グローバル変数UBYTE _io_inに値が代入される。また、グローバル変数UBYTE _io_statusには、通信状況が代入される。
■通信状況 UBYTE _io_status
IO_IDLE 待機中
IO_SENDING 送信中
IO_RECEIVING 受信中
IO_ERROR 送信エラー
関連項目
send_byte
■GBDKにおけるシリアル通信関数のプロトコル
send_byte関数とreceive_byte関数とは、独自のプロトコルにより1バイトデータを送受信している。データの送受信を行うとき、受信側で先にreceive_byte関数で受信待ち状態にし、その後、送信側でsend_byte関数を実行するようにしなければならない。それぞれの関数実行後は、io_statusを監視して送受信の完了を待つ。
送信側 通信 受信側 備考
■receive_byte 受信待ち
・io_status = IO_RECEIVING
・外部クロックを選択
・DT_RECEIVINGを送信(待機) 外部クロックを選択しているので、すぐには、DT_RECEIVINGが送信されない。
■send_byte 送信開始
・io_status = IO_SENDING
・内部クロックを選択
・送信データio_outを送信 内部クロックなのですぐにデータが送信される。
→クロック→
→送信データ→
←DT_RECEIVING← 送信側のクロックで、送信側からの送信と、受信側からの送信が同時に行われる。
■送信完了割り込み発生
・DT_RECEIVING受信の確認
io_status=IO_IDLE
エラー時は、
io_stauts=IO_ERROR
・外部クロックを選択
・DT_IDLEを送信(待機) ■送信完了割り込み発生
・io_inに受信データ代入
・io_status=IO_IDLE
・外部クロックを選択
・DT_IDLEを送信(待機) 送信側、受信側ともに、送信完了割り込みが同時に発生する。
正しく、送受信が行われていれば、送信側には、DT_RECEIVINGが受信され、受信側には、送信データが受信される。
■送信完了の確認
io_status=IO_IDLEなら
送受信成功。
io_status=IO_ERRORなら
送受信失敗。 ■受信完了の確認
io_status=IO_IDLEになれば、
受信完了。
データは、io_inに代入されている。 関数send_byteまたは、関数receive_byteの実行後は、io_statusを監視して、送受信の完了を待つ。
関数の使用例は、GBDKのexamplesディレクトリにあるcomm.cを参照のこと
最終更新:2017年08月28日 16:47