シリアル通信ドライバ「GB-232」

GBCの赤外線通信ポート用レジスタ(0xFF56)のビット4にシリアルポートのP14入力が繋がっていることを利用して、GBCでPCのキーボードやパーコードスキャナなどのPS/2インターフェイスが繋がるようになりましたが、そのPS/2インターフェイスと並んで昔から現在までずっと使われてきているPCの基本的な I/Oの代表としてシリアルインターフェイスがあります。RS−232Cという規格で親しまれてきたインターフェイスです。最近ではUSBインターフェイスが大変普及してきていますが、まだまだ(レガシィ)シリアルインターフェイスは健在です。

P14の発見者であるKen Kaarvik氏がP14を利用したrs232.asmというシリアルインターフェイスの実験プログラムを公開されています。通信仕様は、9600bps、データビット8、ストップビット1、パリティなし専用のものです。PCに繋いで Tera Term Pro でそのプログラムの動作確認をしてみました。キーボード入力のような1バイト単位のアイドル時間の長いデータの受信については問題ありませんでしたが、通常のシリアル通信で要求される文字列を連続して送るような複数バイトデータの受信を行った場合は、大半のデータを取りこぼしてしまい使い物にはなりませんでした。ソースファイルを調べてみると、スタートビットの受信待ちループの中で割り込みを許可していることが原因のようです。

このソースコードは、RGBASM用に書かれていたので、ドライバ部分を切り出しGBDKのC言語から利用できるようにしました。そしてドライバ内では割り込みを禁止にしてみると連続したデータの受信が正常にできました。GPSレシーバはこの通信仕様(9600bps)のドライバで動作しました。次にこのドライバをベースにケータイとの通信用(600bps)を作りました。

今後もこんな調子で機器毎に専用ドライバを作って行ったのでは脳がないので、PCのシリアル通信ドライバのように一通りの通信パラメータが指定でき汎用的に使える本格的なシリアル通信ドライバを開発し、それを公開して多くの方に利用してもらおうと考えました。


GB-232のドライバソース
[ダウンロード] gb232.zip(3KB)(2001/09/08更新)

GB-232の特徴


GB-232の使い方
GB−232はGBDKのC言語から利用できる汎用シリアル通信ドライバです。
通常GBDKのC言語ソースから以下の関数をコールして使用してください。

(注意)receive_gb232()、send_gb232()は、リターン時に割り込みを許可にしているため、割り込みルーチン内からコールする場合は注意が必要です。(2001/08/30追記)

通信パラメータの設定・・・ボーレート微調整パラメータを追加(2001/09/08)
void set_gb232( UBYTE comm_parameter, UBYTE adjust_speed );

引数として各種通信パラメータを論理和した1バイトデータとボーレート微調整パラメータを指定します。
(例)set_gb232( SPEED_9600 | DATA_8 | STOP_1 | PARITY_NONE, ADJUST_0P );

なお、C言語ソースファイルに定義ファイル"gb232.h"をインクルードしてください。
"gb232.h"には以下の通信パラメータを定義してあります。
	#define SPEED_110   0x00U	// 0000 ****
	#define SPEED_300   0x10U	// 0001 ****
	#define SPEED_600   0x20U	// 0010 ****
	#define SPEED_1200  0x30U	// 0011 ****
	#define SPEED_2400  0x40U	// 0100 ****
	#define SPEED_4800  0x50U	// 0101 ****
	#define SPEED_9600  0x60U	// 0110 ****
	#define SPEED_14400 0x70U	// 0111 ****
	#define DATA_8      0x00U	// **** 0***
	#define DATA_7      0x01U	// **** 1***
	#define STOP_1      0x00U	// **** *0**
	#define STOP_2      0x04U	// **** *1**
	#define PARITY_NONE 0x00U	// **** **00
	#define PARITY_ODD  0x03U	// **** **11
	#define PARITY_EVEN 0x02U	// **** **10
	#define ADJUST_M3P  0x00U	// adjust -3%
	#define ADJUST_0P   0x01U	// adjust 0%
	#define ADJUST_P3P  0x02U	// adjust +3%
	
通信初期化
void init_gb232();

受信バッファgRcvData[127]をクリアします。
そして、ストップビットを一回送信して、送信ラインを念のためHighにします。

受信処理
UWORD receive_gb232( UBYTE byte_length, UBYTE timeout_count );

引数として受信するバイト数とタイムアウト時間(0.1秒単位)を指定してください。
(例)receive_gb232( 110, 1 );
受信バイト数:110バイト、タイムアウト時間:0.1秒

戻値(16バイト)の下位バイトに以下のエラーコードを返します。上位バイトには未受信バイト数を返します。よって正常受信であれば上下位バイトとも 0x00 となります。

    0x00:正常受信
    0x01:タイムアウトエラー(指定した時間待ったけどスタートビットが検出されなかった)
    0x02:オーバーランエラー(次のデータを読み出しする前にデータが到着してしまった)
    0x03:フレーミングエラー(ストップビットが検出されなかった)
    0x04:パリティエラー(付加したパリティビットによりエラーが検出された)

正常に受信されれば、gRcvData[127]に受信データが格納されています。

※受信バイト数が不明または不定の場合は、予想される最大バイト数を指定してください。受信したデータが指定したバイト数に満たない場合はタイムアウトエラーとなるので、エラー位置を調べて有効なデータを取るようにして下さい。エラー位置は、次項のサンプルソースのようにすれば調べることができます。

送信処理
void send_gb232( UBYTE send_data );

引数として1バイトの送信データを指定してください。

サンプルソース
#include <gb.h>
#include "gb232.h"
:
#define BYTE_LENGTH    127    // 127 bytes receive
#define TIMEOUT_COUNT  1      // 0.1 msec

extern UBYTE gRcvData[127];
:
unsigned char gMsgTest[] = { "GB-232 (c)2001 TeamKNOx" };
:
void send_msg( unsigned char *msg )
{
  while ( *msg ) {
    send_gb232( *msg );
    msg++;
  }
}
:
:
void main()
{
  UWORD error_result;
  UBYTE error_code, error_byte;
:
:
  set_gb232( SPEED_9600 | DATA_8 | STOP_1 | PARITY_NONE, ADJUST_0P );
  init_gb232();
:
  send_msg( gMsgTest );
:
  error_result = receive_gb232( BYTE_LENGTH, TIMEOUT_COUNT );
  error_code = (UBYTE)(error_result % 256);
  error_byte = BYTE_LENGHT - (UBYTE)(error_result / 256) + 1;
:
:
}

GB-232のしくみ
PC等で最も一般的に使われているシリアル通信は「非同期式」です。GBCにはシリアル通信機能が備わっているのですが「同期式」なので「非同期式」として使用することができません。しかし、Ken Kaarvik氏はこの難問題を解決してしまいました。彼自身のドキュメントはないのですが、彼のアセンブラソースコードが全てを物語っていますので、私なりにしくみを簡単に説明します。

受信処理
P14入力の信号レベル(High/Low)を通信速度に合ったタイミングで調べることによりビット列を受信します。無信号時(アイドル状態)の信号レベルはHighレベルとなっています。スタートビット(Lowレベル)の検出ができると、通信速度に合ったタイミングでデータビット及びストップビット(指定のある場合はパリティビットも)をサンプリングしていきます。このようにP14入力のような生の信号線は取り扱いが簡単です。

送信処理
P14入力のような生の信号線が出力線としても用意されていれば、受信処理と同様に問題ないのですが、残念ながらGBCの出力としては同期式シリアルのSoutしかありません。同期式を非同期として利用するには、GB−232の非同期式の1ビットをGBCの同期式シリアルの8ビットとして扱います。つまり、データ0を0x00、データ1を0xFFとして扱います。GBCの同期式通信は1バイト(8ビット)単位で完了するので、1バイトの送信中は同期式通信ですが1バイト単位では通信タイミングがコントロールできるわけです。ここがポイントです。

以下の記述は誤りです(取り消し線部分)。当初は8ビット送信が終わるまでは、次の送信開始ができないと思っていましたが、8ビット送信の途中でも次の送信開始ができることが確認できました。ということは、送信クロック周波数は8kHz、256KHzどちらでも問題ありません。(2002/02/14訂正)
GBCの同期式シリアルの通信速度は内部クロックの場合8KHzと256KHzの2種類から選択できますが、どちらを選択すればいいのでしょう。GB−232の通信速度は最高14400bpsまで対応しているので、8ビットを1ビットとして扱っても問題のない以下の条件を満足する必要があります。

     (GBCの同期式通信の8ビットの通信速度)>(GB−232の1ビットの通信速度)

GBCのの同期式通信の8ビットの通信速度は以下の値となります。

      8KHz÷8ビット= 1000bps
    256KHz÷8ビット=32000bps

これをGB−232の1ビットの通信速度と比較してみます。

       8KHz: 1000bps<14400bps
     256KHz:32000bps>14400bps

よって、GBCの同期式シリアルの通信速度は要求条件を満足する256KHzを選択します。


あとはスタートビット、データビット(指定のある場合はパリティビットも)、ストップビットの順に各1ビットを1バイトとして扱い、通信速度に合ったタイミングでGBCの同期シリアルの1バイト送信を実行してやれば良いのです。

このようにハードウェアに制限があってもソフトウェアで回避する技術に感動しました。Ken Kaarvik氏に感謝します。

通信パラメータについて
通信速度(ボーレート)
GBCの標準クロックCPU用にドライバを設計した結果、通信速度の上限は14400bpsとなり、以下9600、2400、4800、1200、600、300、110の8種類に対応した。もし倍速クロックで使うときは、指定した通信速度とタイムアウト時間がそのまま倍速となるので注意のこと。通信機器のボーレート誤差に対応するため、±3%の微調整機能を実装。

データビット
1バイトデータのビット数は一般に8ビットだが、昔の通信規格は7ビットだったらしい。メールは0x7Fより大きな文字コードを使うと文字化けすることがあることから解るように、現在でも7ビット規格のメールサーバが多いとのこと。5ビットという規格もあるそうだが、GB−232では8ビットと7ビットの2種類に対応とした。

ストップビット
ストップビットの規格は1ビット、1.5ビット、2ビットの3種類あるが、これは送信側の規格と思われる。ストップビット1で連続してデータを送信すると受信側の処理が遅い場合には受信側がデータを取りこぼす。このような場合にストップビット長を長めにしてやる必要があるのだろう。ストップビット長の選択は1ビットと2ビットの2種類としている。しかし、GB−232の送信ルーチンは1バイト送信仕様なのでストップビットの長さはコントロールしていない(できない)。そのため、通信パラメータの設定ルーチンでストップビット長を指定しても無効となっている。GB−232の送信ルーチンを送信バイト指定仕様に変更した場合にはストップビット長の指定を有効にできる。GB−232の受信ルーチンについては最短の1ビット長に対応している。(ストップビット長の全仕様に対応)

パリティチェック
GB−232のパリティチェックの選択は標準的な以下の3種類とした。
  • パリティなし
  • 偶数パリティ
  • 奇数パリティ
パリティチェックを有効にしていれば、送信時に指定(偶数または奇数)のパリティビットを付加する。受信時は受信したデータのパリティチェックを実行し、パリティエラーならエラーコード(0x04)を返す。

GB-232用シリアルケーブルのピンアサイン(2001/09/08追加)
    Pin1: +5v(必要により)
    Pin2: TxD
    Pin3: 接続しません
    Pin4: RxD
    Pin5: 接続しません
    Pin6: GND
    GBCのシリアルケーブルの図

GB-232用シリアルケーブルの標準化
GB-232を利用してGBCにいろいろなシリアルインターフェイス機器を接続できるようになったのですが、接続ケーブルの機器側は専用プラグを使用している場合が多く、機器毎にGBCとの接続ケーブルを製作することになりそうです。機器専用ケーブルとGBC専用通信ケーブル(任天堂純正品は不可:ゲームテック製推奨)の各々を切断して繋ぎ合わせるのですが、TeamKNOxでは双方切断したケーブルの接続を汎用部品であるMiniDIN4ピンプラグ&コネクタを用いることにしました。そうすることにより、GBC側のケーブルは各機器で共通に使えるようになりました。
GB-232用標準シリアルケーブルの結線図は
TeamKNOx WEB-Siteをご参照ください。
GB-232用標準シリアルケーブルの写真

GB-232の信号波形を検証通信速度の見直し及びボーレートの微調整機能を追加したので再検証を行いました。(2001/10/08)
GB-232の出力信号の波形の品質、電圧およびパルス幅等が問題ないかを秋月電子で購入したペン型オシロで検証してみた。
検証は通信パラメータは 9600,n,8,1、テストデータは 0x55、サンプリングレートは10usで行った。サンプリングした信号波形は以下のとおりである。電圧は約5.0Vで問題なし、通信速度は±3%も含め計算値とほぼピッタリであった。送信スタートビットは1ビット以上としており、正確にコントロールしていないが、9600bpsの場合スタートビットは2ビットほどになっている。

9600bps(-3%)

0.86ms / 8bits = 0.108ms

9600bps(0%)

0.83ms / 8bits = 0.104ms

9600bps(+3%)

0.81ms / 8bits = 0.101ms

通信速度と1ビット幅(時間)
(単位:msec)
bps-3%0%+3%
144000.0720.0690.067
96000.1070.1040.101
48000.2150.2080.202
24000.4290.4170.404
12000.8580.8330.808
6001.7171.6671.617
3003.4333.3333.233
1109.3649.0918.818

GB-232更新履歴
2001/09/08 ボーレートを±3%調整できるようにした(以前はマイナス側にずらし固定)。 受信サンプリング位置を全ポーレートともパルス中央に変更。
2001/05/06 受信ルーチンの戻値をワード型に変更し、上位バイトに未受信バイト数を取得できるようにした。
2001/04/28 初版公開

GB-232採用アプリ
TeamKNOxのO氏作のゲームボーイカラー用GPSレシーバソフト「GB-GPS」が初めてGB-232を使ったアプリです。
2作目が同じくO氏作のゲームボーイカラー用ケータイ・コントロールソフト「GB-PDC」です。
TeamKNOx WEB-Siteをご参照ください。
そして3作目が現在開発中のシリアル通信ソフト「GB−TERM」です。(2001/09/08)
INDEXに戻る

Copyright(C) 2001 Kiyoshi Izumi