通信

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