出力に続けて入力も実装します。
SCIへの入出力が完成すればターミナルソフトを使ってHD6303との会話が可能になります。
プログラムの構成
一行入力を実行するには次のルーチンが必要です。
- SCIから一文字受信
- SCIから文字列受信
SCIから一文字受信(read_char)
SCIから受信したデータをBレジスタに保存します。
read_char:
.top tim #RDRF|ORFE,<TRCSR ; 受信データ有無のチェック
beq :top
tim #ORFE,<TRCSR ; エラーのチェック
beq :end
ldab <RDR ; 空読みしてステータスのリセット
bra :top
.end ldab <RDR ; SCIデータの読み込み
rts
まずはステータスレジスタ(TRCSR)のチェックです。
RDRF | ORFE | 状態 |
---|---|---|
0 | 0 | 受信データなし |
0 | 1 | 受信データあり |
1 | 0 | フレーミングエラー |
1 | 1 | オーバーランエラー |
2行目でRDRF、ORFE共にビットが立っていなければ受信データがありませんので、どちらかが立つまでループして待ちます。
4行目ではRDRFビットが立っていればフレーミングエラーかオーバーランエラーなので6行目で空読みしてステータスをリセットします。
オーバーランエラーはデータを取り込む前に次のデータが来てしまった時、フレーミングエラーはボーレートが異なっていたり誤差が大きすぎたりして、ストップビットが来るはずのところでHレベルが来ない時に発生します。
8行目でようやく受信したデータをBレジスタに保存して終了です。
SCIから文字列受信(read_line)
SCIから文字列を受信してバッファに保存していきます。
リターン(CR+LFまたはLF)することでルーチンを終了します。
バックスペースくらいは使いたいのでがんばって実装することにしました。
; 定数 Constants
NUL .eq $00 ; NUL
BS .eq $08 ; Backspace
SPACE .eq $20 ; Space
CR .eq $0d ; Carriage Return
LF .eq $0a ; Line Feed
DEL .eq $7f ; Delete
Rx_BUFFER .eq $0100 ; SCI Rx Buffer
Rx_BUFFER_END .eq $0148 ; 73byte(72文字分)
; 一行入力 改行コードは「CRLF」「LF」
read_line:
ldx #Rx_BUFFER
.loop bsr read_char
cmpb #BS ; 入力文字がBSならば…
beq :bs ; バックスペース処理へ
cmpb #LF ; LF?
beq :end
cmpb #DEL ; b >= DEL ?
bcc :loop ; なにもしない
cmpb #SPACE ; b < SPACE ?
bcs :loop ; なにもしない
cpx #Rx_BUFFER_END ; バッファ終端チェック
beq :loop ; 73文字目ならなにもしない
bsr write_char ; echo
stab 0,x ; バッファに文字を収納
inx ; ポインタを進める
bra :loop ; 次の文字入力
; ----- バックスペース処理 -----
.bs cpx #Rx_BUFFER ; ポインタ位置が一文字目ならば…
beq :loop ; なにもしない
bsr write_char ; 一文字後退
ldab #SPACE ; 空白を表示(文字を消去)
bsr write_char
dex ; バッファポインタ-
ldab #BS ; 一文字後退(カーソルを戻す)
bsr write_char
bra :loop
; ----- 終端処理 -----
; 文字数が72文字の時、次のアドレスを指していない。その場合はポインタを+1する。
.end cpx #Rx_BUFFER_END-1
bne :noinc
inx
.noinc clrb ; $00:終端記号
stab 0,x
bra write_crlf ; 改行してrts
12行目のread_char
で入力文字を読み込み、通常文字であればバッファに保存、write_char
でエコーバックしていきます。
通常文字ではない制御コードであれば無視して次の文字を読み込みます。
LF($0a
)を読み込むと、代わりにに$00
をバッファに書き込んで終了します。
BS($08
)を読み込むと、バックスペース処理に移ります。
バックスペースは一文字分カーソルが後退するだけなので、そのままでは文字が消えません。
そのため、後退→空白出力→後退して文字が削除されたように見せています。
メインルーチン
メインルーチンはメッセージとプロンプト「$
」を表示してからread_line
ルーチンを呼び出します。
入力が終わったらXレジスタに入力バッファを代入し、write_line
ルーチンを呼び出して入力された文字列を出力します。
出力したらプロンプトの表示に戻り、これを繰り返します。
ldx #MSG_TEST
jsr write_line
prompt: ldab #'$'
jsr write_char
jsr write_space
jsr read_line
ldx #Rx_BUFFER
jsr write_line
jsr write_crlf
bra prompt
MSG_TEST .az "*** Line Input Test ***",#CR,#LF
実行します
前回の出力ルーチンと合わせてROMに焼きます。
うまく表示されました!
入出力ができるようになったので、次はプログラムファイルの転送を実装します。
いちいちROMに焼き込む必要がなくなるのでかなり楽になるはずです。
コメント