;------------------------------------------------------------------------------
; ポケコン用 EEPROMドライブ 「ポケメモ」
;------------------------------------------------------------------------------
; バージョン履歴
;
; Ver.1.11 2007/9/2
;  1278行目(BCF	FLAG,SECTOR2)が抜けていたため、mkfsをかけた後にdfをすると間違った数値を表示していた
;
; Ver.1.10 2007/8/29
;  ポケメモが返すエラーやメッセージに行番号をつけるオプションを実装
;  helpコマンドにコマンドごとのヘルプを表示するようにした
;
; Ver.1.00 2005/12/17
;  UARTのフレーミング/オーバーランエラーリカバリを実装
;  一応完成
;
; Ver.0.98 2005/12/3
;  overコマンドを実装
;  エラー発生時のバッファフラッシュ周りを統一
;
; Ver.0.97 2005/12/1
;  termコマンドの引数を大文字小文字どちらでも認識するようにした
;
; Ver.0.96 2005/11/30
;  PICプログラマキットVer.4購入のため、デバイスを変更(16F873A)
;  プログラムはデバイスに依存しないように作ってあるので、そのまま書き込んで使用できる
;
; Ver.0.95 2005/11/27
;  bcpy,mchkコマンドの廃止(使用頻度があまりにも少ない)
;  mchkを廃止したため、バッドセクタも廃止
;  df,helpコマンドを新設
;  sizeコマンド実装
;  コマンド終了後、エラー発生時のLED点灯パターンを統一化
;
; Ver.0.8 2005/11/23
;  putコマンドの実装完了
;  コマンド入力前半の行番号を無視するようにした
;
; Ver.0.7 2005/11/20早朝
;  get,del,ren,lsコマンド実装完了
;
; Ver.0.5 2005/11/17
;  ファイルシステムの最適化
;  1セクタ64バイト×512セクタになっていたところを128バイト×256セクタに変更。ファイル管理エリアが1kバイト減少
;  セクタ数の変更に伴い、ヘッダ構造の変更[00]インデックス[01]データサイズ[02]次セクタ[03〜7F]データ125バイト
;  ファイルサーチルーチンを作成
;  ボリュームラベル廃止、必要ならフォーマット直後に空のファイルを作ればよい
;  lsの-sオプションを廃止、標準でサイズを出力する
;
; Ver.0.1 2005/11/12
;  term,stat,set,cd,mkfsコマンド実装完了 何故かUSARTフレーミングエラーの解除ができない
;
; Ver.0.05 2005/11/11
;  プログラムを整理
;
; Ver.0.04 2005/11/9
;  コマンド解析ルーチン完成 以降各コマンドの処理に移る
;
; Ver.0.03 2005/11/8
;  バッファのコピーと照合ルーチンが完成
;
; Ver.0.02 2005/11/7
;  コマンドの引数分割ルーチンが完成
;
; Ver.0.01 2005/11/6
;  シリアル周りのルーチンが完成。ハイパーターミナルのバグに悩まされる(泣
;
; Ver.0.0 2005/11/3
;  基板完成
;  16F873を買ったつもりが16F873Aだったため、急遽手元にある16F876を使用することにした(泣

;------------------------------------------------------------------------------
; デバイス	PIC16F873,873A,876,876A
; 動作周波数	16MHz
;------------------------------------------------------------------------------
	LIST		P=PIC16F873A,R=DEC,N=0
	INCLUDE		"P16F873A.INC"
	ERRORLEVEL	0,-302,-306,-307
	__CONFIG	0x3F72	; FOSC	HS
				; WDTE	Disable
				; PWRTE	Enable
				; BODEN	Enable
				; RB3	I/O
				; CPD	Not Protect
				; WRT	Disable
				; DEBUG	Disable
				; CP	Not Protect
;------------------------------------------------------------------------------
; 変数宣言
;------------------------------------------------------------------------------
TMP00		EQU	0x20		; 一時使用変数
TMP01		EQU	0x21
TMP02		EQU	0x22
TMP03		EQU	0x23
TMP10		EQU	0x24
TMP11		EQU	0x25
TMP12		EQU	0x26
TMP13		EQU	0x27
TMP20		EQU	0x28
TMP21		EQU	0x29
TMP22		EQU	0x2A
TMP23		EQU	0x2B
TMP30		EQU	0x2C
TMP31		EQU	0x2D
TMP32		EQU	0x2E
TMP33		EQU	0x2F

SECTOR		EQU	0x30		; メモリセクタ番号
ARGC		EQU	0x31		; 引数の数
MAXDRIVE	EQU	0x32		; I2C EEPROMの最大ドライブ数(0〜7)


FLAG		EQU	0x40		; FLAG-0 改行コードのバイト数 0=1バイト(CRorLF) 1=2バイト(CR+LF)
					; FLAG-1 改行コードにCRを使う
					; FLAG-2 改行コードにLFを使う
					; FLAG-3 EOFコードを使う
					; FLAG-4 行番号を送信する
					; FLAG-5 1セクタ内の後半バイトを選択(64〜127)
					; FLAG-6 目的のセクタが見つからなかった
					; FLAG-7 目的のファイルが見つからなかった
FLAG2		EQU	0x41		; FLAG2-0 コマンド前の行ナンバー除去フラグ
					; FLAG2-1 オーバーライトコマンドを実行中
					; FLAG2-2 文字列照合の相違フラグ(1なら違う)

RXDATA		EQU	0x60		; シリアルから受信したデータ1バイト
TXOFFSET	EQU	0x61		; 送信時にバッファのオフセット位置から送信する(ファイル内容抽出のため)
TXSIZE		EQU	0x62		; 送信するデータのサイズ

EEPADDR		EQU	0x64		; 内蔵EEPROMアドレス
EEPDATA		EQU	0x65		; 内蔵EEPROMデータ

I2CCHIP		EQU	0x6B		; I2C EEPROMチップセレクト
I2CADRH		EQU	0x6C		; I2C EEPROMアドレス上8ビット
I2CADRL		EQU	0x6D		; I2C EEPROMアドレス下8ビット
I2CDATA		EQU	0x6E		; I2C EEPROMアクセスデータ
I2CSIZE		EQU	0x6F		; I2C EEPROMのページ読み書きで処理するサイズ

; 16F876では0x70〜0x7Fは0xF0〜0xFFと同じ内容になるため、使わない

DATABUF		EQU	0xA0		; シリアル、EEPROM用 64バイトデータバッファ
HEXBUF		EQU	0xA5		; 16進→10進テキスト変換バッファ
CMPBUF		EQU	0xD0		; 文字列照合バッファ 16バイト DATABUFと重なるが問題ない
ARGV1		EQU	0xE0		; 引数バッファ1 16バイト 文字列照合にも使用
ARGV2		EQU	0xF0		; 引数バッファ2 16バイト 文字列照合にも使用

;------------------------------------------------------------------------------
; 定数宣言
;------------------------------------------------------------------------------
LED_G		EQU	5		; PORTB-5 緑LED信号
LED_R		EQU	7		; PORTB-7 赤LED信号
SW_IN		EQU	1		; PORTC-1 スイッチ入力
RS_OUT		EQU	2		; PORTC-2 ポケコンCS端子への出力
CS_IN		EQU	5		; PORTC-5 ポケコンRS端子からの入力 アクティブロー
EOL		EQU	0		; FLAG-0 改行コードのバイト数 0=1バイト(CR,LF) 1=2バイト(CR+LF)
EOL_CR		EQU	1		; FLAG-1 改行コードにCRを使う
EOL_LF		EQU	2		; FLAG-2 改行コードにLFを使う
EOFCODE		EQU	3		; FLAG-3 EOFコードを使う
LINE_NUMBER	EQU	4		; FLAG-4 行番号を送信する
SECTOR2		EQU	5		; FLAG-5 1セクタ内の後半バイトを選択(64〜127)
NO_INDEX	EQU	6		; FLAG-6 目的のインデックスが見つからなかった
NO_FILE		EQU	7		; FLAG-7 目的のファイルが見つからなかった
NUMBER_SKIP	EQU	0		; FLAG2-0 コマンド前の行ナンバー除去フラグ
OVER_CMD	EQU	1		; FLAG2-1 オーバーライトコマンドを実行中
DIFF		EQU	2		; FLAG2-2 文字列照合の相違フラグ 1なら違う

EEP_SPBRG	EQU	0x00		; EEPROM内のSPBRGデータのアドレス
EEP_MAXDRIVE	EQU	0x01		; EEPROM内のMAXDRIVEデータのアドレス

SPBRG_1200	EQU	207		; 1200bpsのSPBRGレジスタ値
SPBRG_2400	EQU	103		; 2400bps
SPBRG_4800	EQU	51		; 4800bps
SPBRG_9600	EQU	25		; 9600bps
SPBRG_19200	EQU	12		; 19200bps
CHATTER		EQU	50		; チャタリング防止ウエイト定数
BUFSIZE		EQU	64		; DATABUFのサイズ
ARGVSIZE	EQU	16		; ARGVのサイズ
CMDLEN		EQU	4		; コマンドの最大の長さ(コマンド分割のエラーチェックに使用)
CR		EQU	0x0D		; CRコード
LF		EQU	0x0A		; LFコード
CAN		EQU	0x18		; CANCEL[Ctrl+X]コード
NULL		EQU	0x00		; ヌルコード
EOF		EQU	0x1A		; EOFコード
DEF_EOL		EQU	B'00011111'	; デフォルトの改行制御。CR+LF,EOF,行番号ON

INDEX_BLANK	EQU	0x00		; ブランクセクタ識別子
INDEX_START	EQU	0x10		; スタートセクタ識別子
INDEX_FRAGMENT	EQU	0x20		; フラグメントセクタ識別子

ADDR_SIZE	EQU	DATABUF+1	; DATABUFのサイズ識別子が入っているアドレス
ADDR_NEXT	EQU	DATABUF+2	; DATABUFの次セクタ識別子が入っているアドレス
OFST_SIZE	EQU	1		; ファイル先頭からサイズ識別子までのオフセット
OFST_NAME	EQU	3		; ファイル先頭からファイル名までのオフセット
OFST_DATA_S	EQU	19		; ファイル先頭からデータまでのオフセット(スタートセクタ)
OFST_DATA_F	EQU	3		; ファイル先頭からデータまでのオフセット(フラグメントセクタ)
NEXT_SECTOR	EQU	7		; 次のセクタが存在する

LED_GREEN	EQU	0x20		; 緑LEDの定数
LED_RED		EQU	0x80		; 赤LEDの定数
LED_ORANGE	EQU	0xA0		; 橙LEDの定数

;------------------------------------------------------------------------------
; メインプログラム
;------------------------------------------------------------------------------
		ORG	0x0000
;------------------------------------------------------------------------------
; 電源投入時の初期化
;------------------------------------------------------------------------------
POWER_ON				; 電源ON
	CLRF	PORTA			; I/O初期化
	CLRF	PORTB
	MOVLW	B'00000100'		; RS出力は負論理動作なので、ビットを立てておく
	MOVWF	PORTC

	BSF	STATUS,RP0
	MOVLW	B'00000000'		; RA[0-5]空
	MOVWF	TRISA
	MOVLW	B'00000000'		; RB[0-46]空 RB[5]緑LED RB[7]赤LED
	MOVWF	TRISB
	MOVLW	B'11111010'		; RC[0]空 RC[1]スイッチ入力 RC[2]RS-232C RS出力 RC[34]I2C RC[5]RS-232C CS入力 RC[67]USART
	MOVWF	TRISC

	MOVLW	B'00000110'		; 使わないがA/Dコンバータ初期化
	MOVWF	ADCON1			; ポートをデジタル出力に出来るように設定する(空きピン処理)

	MOVLW	B'00100000'		; USART初期化
	MOVWF	TXSTA

	MOVLW	B'00000000'		; I2C初期化
	MOVWF	SSPCON2
	MOVLW	9			; 4000000/(9+1)=400KHz
	MOVWF	SSPADD
	MOVLW	B'00000000'
	MOVWF	SSPSTAT

	BCF	STATUS,RP0
	MOVLW	B'10000000'		; USART初期化
	MOVWF	RCSTA			; 受信はとりあえずOFFにしておく

	MOVLW	B'00101000'
	MOVWF	SSPCON			; I2C初期化

;------------------------------------------------------------------------------
; ループ前処理
;------------------------------------------------------------------------------
BEFORE_MAIN
	MOVLW	DEF_EOL			; デフォルトの改行設定をロード、改行設定はEEPROMには保存しない
	MOVWF	FLAG			; (常にポケコンで使うことを前提にしているため)
	BTFSC	PORTC,SW_IN		; 電源投入時にスイッチが押されているか?
	GOTO	CONFIG_READ		; 押されていない場合は、EEPROMに保存された設定データで起動
	MOVLW	CHATTER			; チャタリング防止用ウエイトの後
	CALL	wait
	BTFSC	PORTC,SW_IN		; 再度確認
	GOTO	CONFIG_READ		; 確認後に押されていないならば、通常起動
CONFIG_RESET				; キーが押されていた場合は、設定データをリセットして起動
	MOVLW	LED_ORANGE		; キーが押されているならばオレンジを点灯させる
	MOVWF	PORTB
	CALL	keyrelease		; リリースを待つ
	MOVLW	LED_ORANGE		; すると、橙LEDが点滅するので、
	CALL	getkey			; キーを押すとEEPROMを初期化
	MOVLW	EEP_SPBRG		; リセットしたくない場合は、電源を抜く
	MOVWF	EEPADDR
	MOVLW	SPBRG_1200		; スピードの初期値は1200bps
	MOVWF	EEPDATA
	CALL	eepwrite
	MOVLW	EEP_MAXDRIVE
	MOVWF	EEPADDR
	CLRF	EEPDATA			; デフォルトのドライブ数は1 (最低でもチップは1個載っているという意味)
	CALL	eepwrite		; 必要ならばsetコマンドでチップの数を変更する
CONFIG_READ				; EEPROMからシステムの設定値を読み込む
	MOVLW	EEP_SPBRG		; setコマンドの後もこの場所にジャンプする
	MOVWF	EEPADDR			; シリアルスピードの値
	CALL	eepread
	MOVF	EEPDATA,W
	BSF	STATUS,RP0
	MOVWF	SPBRG			; EEPROMから読み込んだスピードでシリアルスピードを決定
	BCF	STATUS,RP0
	MOVLW	EEP_MAXDRIVE		; メモリドライブの最大値
	MOVWF	EEPADDR
	CALL	eepread
	MOVF	EEPDATA,W
	MOVWF	MAXDRIVE
	CLRF	I2CCHIP			; ドライブを1にセット

;------------------------------------------------------------------------------
; メインループ
;------------------------------------------------------------------------------
MAINLOOP
	BCF	PORTC,RS_OUT		; 受信可信号を出して送信側のバッファをフラッシュする
	MOVLW	LED_GREEN
	CALL	getkey			; 緑LED点滅でユーザ指示を待つ
CMD_RECEIVE
	BSF	PORTC,RS_OUT		; 受信可信号を元に戻す
	MOVLW	40			; 相手が送信中の場合を考えて、
	CALL	wait			; 送信が止まるであろう時間(1/120cps)以上ウエイトをとる
	MOVLW	LED_GREEN		; 緑LED点灯
	MOVWF	PORTB
	BSF	RCSTA,CREN		; キーの入力後から受信を開始する
	MOVLW	CMDLEN+ARGVSIZE*2+2	; コマンド自体の最大長は37バイトなので、それ以上は無効な文字が入っている場合があるとみなす
	MOVWF	TMP00			; TMP00は入力文字数カウンタ
	MOVWF	TMP30			; コマンド入力バッファをヌルでクリアする
	MOVLW	DATABUF
	MOVWF	TMP31
	MOVLW	NULL
	MOVWF	TMP32
	CALL	bufclear
	BSF	FLAG2,NUMBER_SKIP	; 行番号除去フラグをO
	BCF	FLAG2,OVER_CMD		; オーバーライトフラグをリセット
	MOVLW	DATABUF			; FSRはコマンド入力バッファの文字位置ポインタ
	MOVWF	FSR
	BSF	PORTB,LED_G		; コマンド入力待ちLED
CMDRECV_LOOP				; コマンド入力ループ
	CALL	rxserial
	BTFSS	FLAG2,NUMBER_SKIP	; 行番号スキップが解除されている場合は、コマンド入力
	GOTO	CMDRECV_LOOP2
	MOVLW	'0'			; '0'〜'9'がコマンドの初めに来た場合にスキップを解除して次に進む
	SUBWF	RXDATA,W		; RXDATA-'0'
	BTFSS	STATUS,C
	GOTO	CMDRECV_LOOP2
	MOVF	RXDATA,W		; '9'-RXDATA
	SUBLW	'9'
	BTFSC	STATUS,C
	GOTO	CMDRECV_LOOP

CMDRECV_LOOP2
	BCF	FLAG2,NUMBER_SKIP	; スキップを解除
	BCF	PORTB,LED_G		; 1文字受信した後は、それを知らせるために緑LEDを消灯させる

	MOVF	RXDATA,W		; CRコード(コマンド終端)が来たかチェック
	SUBLW	CR
	BTFSC	STATUS,Z
	GOTO	CMD_SPLIT		; CRコードならコマンド入力を中断してコマンド分割処理へ進む

	MOVF	RXDATA,W		; LFコード(コマンド終端)が来たかチェック
	SUBLW	LF
	BTFSC	STATUS,Z
	GOTO	CMD_SPLIT		; LFコードならコマンド入力を中断してコマンド分割処理へ進む

	MOVF	RXDATA,W		; CANコード(取り消し[Ctrl+X])が来たかチェック
	SUBLW	CAN
	BTFSC	STATUS,Z
	GOTO	CMD_RECEIVE		; CANコードならコマンド入力を取り消す(ターミナル使用中、デバッグ用)

	MOVF	RXDATA,W		; 文字を追加
	MOVWF	INDF
	INCF	FSR,F			; ポインタをインクリメント
	DECFSZ	TMP00,F			; 最大受信文字数-1
	GOTO	CMDRECV_LOOP		; コマンド最大長をオーバーする時はエラーを送信
CMDRECV_ERROR				; データ受信エラー
	BCF	RCSTA,CREN		; 受信を停止する
	BCF	PORTC,RS_OUT		; 受信可信号を出して送信側のバッファをフラッシュする
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_cmdorargover	; コマンドまたは引数が長すぎる
	CALL	txserial
	GOTO	MAINLOOP		; 再度待機状態からやり直し

CMD_SPLIT				; 正常に受信できた場合のコマンド分割処理
	BTFSC	FLAG,EOL		; 改行コードのバイト数によってダミー受信を入れる
	CALL	rxserial
	BTFSC	FLAG,EOFCODE		; コマンドの後に付くEOFを受信するために、ダミーを入れる
	CALL	rxserial
	BCF	RCSTA,CREN		; 受信を停止する

	CLRF	ARGC			; 引数の数をクリア
	MOVLW	ARGVSIZE*2		; 引数が代入されるバッファのクリア
	MOVWF	TMP30			; バッファは連続しているので、一気にクリアできる
	MOVLW	ARGV1
	MOVWF	TMP31
	MOVLW	0x00
	MOVWF	TMP32
	CALL	bufclear

	MOVLW	DATABUF			; FSRはコマンド本体を格納するバッファのポインタ
	MOVWF	FSR
	MOVLW	CMDLEN+1		; システムが使うコマンドの最大の長さをロード
	MOVWF	TMP01			; 無駄な分割ループを防ぐ
CMDSPLIT_LOOP				; コマンドを「コマンド本体」「引数1」「引数2」に分割する
	MOVF	INDF,W			; コマンド本体の後にあるスペースの場所まで移動する
	SUBLW	' '
	BTFSC	STATUS,Z		; スペースが見つかるまではループ
	GOTO	CMDSPLIT_ARG		; 見つかった場合は引数の処理へ

	MOVF	INDF,W			; コマンド本体の後にヌルがあるか?
	SUBLW	NULL
	BTFSC	STATUS,Z
	GOTO	CMD_ANALYSE		; 見つかった場合は分割終了

	MOVF	INDF,W			; コマンドの文字は'Z'以下か?
	SUBLW	'Z'
	BTFSS	STATUS,C
	GOTO	CMDSPLIT_LOOP2		; 'Z'以下なら大文字とみなして小文字に変換
	MOVF	INDF,W
	ADDLW	'a'-'A'			; 引いた値に'a'を足すと小文字になる
	MOVWF	INDF
CMDSPLIT_LOOP2
	INCF	FSR,F			; 見つからなかった場合は、次の文字へ進む
	DECFSZ	TMP01,F			; コマンドが異常に長い場合はコマンド入力エラーにする
	GOTO	CMDSPLIT_LOOP
	GOTO	CMDRECV_ERROR

CMDSPLIT_ARG				; 引数の処理
	MOVLW	2			; 処理する引数の数を指定
	MOVWF	TMP10
	MOVLW	ARGV1			; 引数を保存するバッファのポインタを取得
	MOVWF	TMP00
CMDSPLIT_ARG1
	INCF	ARGC,F			; 引数の数を+1
	CLRF	INDF			; 前回見つかったスペースをヌルで置換する
	INCF	FSR,F			; 1文字進める
	MOVLW	ARGVSIZE		; 引数の最大の長さをロード
	ADDLW	1			; +1して文字数オーバーを検出する
	MOVWF	TMP01			; 無駄な分割ループを防ぐ
CMDSPLIT_ARG1_LOOP
	MOVF	INDF,W			; 引数の後にあるスペースの場所まで移動する
	SUBLW	' '			; コマンド本体の後にスペースが2文字入っていた場合は誤動作する
	BTFSC	STATUS,Z		; スペースが見つかるまではループ
	GOTO	CMDSPLIT_ARG2		; 見つかった場合は引数2の処理へ
	MOVF	INDF,W			; 引数の後にヌルがあるか?
	SUBLW	NULL
	BTFSC	STATUS,Z
	GOTO	CMD_ANALYSE		; 見つかった場合は分割終了
	MOVF	INDF,W			; 現在の文字を保存
	MOVWF	TMP02
	CLRF	INDF			; 文字をヌルに置換
	MOVF	FSR,W			; コピー元のポインタを保存
	MOVWF	TMP03
	MOVF	TMP00,W			; コピー先のポインタを取得
	MOVWF	FSR
	MOVF	TMP02,W			; 文字をコピー
	MOVWF	INDF
	MOVF	TMP03,W			; コピー元の位置を復帰
	MOVWF	FSR
	INCF	FSR,F			; 位置をインクリメント
	INCF	TMP00,F
	DECFSZ	TMP01,F			; ARGVSIZE分だけループ
	GOTO	CMDSPLIT_ARG1_LOOP
	GOTO	CMDRECV_ERROR		; 引数が異常に長い場合は入力エラーにする

CMDSPLIT_ARG2				; 引数2の処理
	MOVLW	ARGV2			; 引数を保存するバッファのポインタを取得
	MOVWF	TMP00
	DECFSZ	TMP10,F			; 処理する引数の数をカウント
	GOTO	CMDSPLIT_ARG1		; 2個処理が終わったらループを抜ける

CMD_ANALYSE				; コマンドの解析、検索パターンをCMPBUFに入れ、DATABUFと照合する
	MOVLW	CMPBUF			; putコマンド
	BSF	PCLATH,3
	CALL	cmdput
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_PUT

	MOVLW	CMPBUF			; getコマンド
	BSF	PCLATH,3
	CALL	cmdget
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_GET

	MOVLW	CMPBUF			; delコマンド
	BSF	PCLATH,3
	CALL	cmddel
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_DEL

	MOVLW	CMPBUF			; renコマンド
	BSF	PCLATH,3
	CALL	cmdren
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_REN

	MOVLW	CMPBUF			; overコマンド
	BSF	PCLATH,3
	CALL	cmdover
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_OVER

	MOVLW	CMPBUF			; sizeコマンド
	BSF	PCLATH,3
	CALL	cmdsize
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_SIZE

	MOVLW	CMPBUF			; lsコマンド
	BSF	PCLATH,3
	CALL	cmdls
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_LS

	MOVLW	CMPBUF			; dfコマンド
	BSF	PCLATH,3
	CALL	cmddf
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_DF

	MOVLW	CMPBUF			; cdコマンド
	BSF	PCLATH,3
	CALL	cmdcd
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_CD

	MOVLW	CMPBUF			; mkfsコマンド
	BSF	PCLATH,3
	CALL	cmdmkfs
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_MKFS

	MOVLW	CMPBUF			; setコマンド
	BSF	PCLATH,3
	CALL	cmdset
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_SET

	MOVLW	CMPBUF			; numコマンド
	BSF	PCLATH,3
	CALL	cmdnum
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_NUM

	MOVLW	CMPBUF			; termコマンド
	BSF	PCLATH,3
	CALL	cmdterm
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_TERM

	MOVLW	CMPBUF			; statコマンド
	BSF	PCLATH,3
	CALL	cmdstat
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_STAT

	MOVLW	CMPBUF			; helpコマンド
	BSF	PCLATH,3
	CALL	cmdhelp
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcmp
	BTFSS	FLAG2,DIFF
	GOTO	CMD_HELP

	BCF	PORTC,RS_OUT		; 受信可信号を出して送信側のバッファをフラッシュする
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_invalidcommand	; どれにも当てはまらない場合は、コマンドエラーを送信
	CALL	txserial
	GOTO	MAINLOOP

;------------------------------------------------------------------------------
; メインループ終了
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; 各コマンド処理ルーチン
;------------------------------------------------------------------------------
; コマンド名と引数の間にはスペースを1文字入れる
; ファイル名/ボリューム名は1〜16文字のテキスト文字
;
; 各コマンドの書式
; 済	put ファイル名
; 済	get ファイル名
; 済	del ファイル名
; 済	ren 変更前ファイル名 変更後ファイル名
; 済	over ファイル名
; 済	size
; 済	ls
; 済	df [ドライブレター]
; 済	cd ドライブレター
; 済	mkfs
; 済	set 通信速度 EEPROM装着数
; 済	num 行番号の有無
; 済	term 改行コード EOFの有無
; 済	stat
; 済	help
;
; コマンド処理中のLEDの点滅パターン
;  緑 点滅 - 電源投入時のキー入力待ち、SETコマンドの終了時
;  緑 点灯 - コマンド入力待ち
;  消灯    - コマンド入力中
;  橙 点灯 - 情報あり、受信待ち
;  橙 点滅 - 処理継続のキー入力待ち、EEPROMアクセス
;  赤 点滅 - エラー情報あり、キー入力待ち
;  赤 点灯 - エラー情報送信中
;  赤緑    - UARTエラー発生 エラーから復帰処理中


CMD_PUT					; ファイルの書き込みルーチン
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	ARGV1			; 保存するファイルが存在するかチェック
	CALL	filesearch
	BTFSC	FLAG,NO_FILE
	GOTO	CMD_PUT1
	MOVLW	LED_RED
	CALL	getkey
	BSF	PCLATH,3
	CALL	err_fileexist		; ファイルがすでに存在する
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_PUT1
	CLRF	SECTOR			; セクタ0から空きセクタを探す
	MOVLW	INDEX_BLANK
	CALL	indexsearch
	BTFSS	FLAG,NO_INDEX
	GOTO	CMD_PUT2
	MOVLW	LED_RED
	CALL	getkey
	BSF	PCLATH,3
	CALL	err_diskfull		; ディスクがいっぱい(スタートセクタすら書けない)
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_PUT2
	MOVLW	LED_ORANGE		; キーの入力後から書き込み処理を開始する
	BTFSS	FLAG2,OVER_CMD		; オーバーライト中の時はすでにスイッチの入力があるので飛ばす
	CALL	getkey
	MOVF	SECTOR,W
	MOVWF	TMP00			; TMP00にスタートセクタを記録する

	MOVLW	INDEX_START		; スタートインデックスを書き込む
	MOVWF	I2CDATA
	CALL	i2cwrite

	MOVLW	ARGVSIZE		; ファイル名のデータバッファを用意
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	MOVLW	NULL
	MOVWF	TMP32
	CALL	bufclear
	MOVLW	ARGV1			; ファイル名を転送
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcopy
	MOVLW	OFST_NAME		; ファイル名を書き込む
	ADDWF	I2CADRL,F
	MOVLW	ARGVSIZE
	MOVWF	I2CSIZE
	CALL	i2cpwrite

	MOVLW	BUFSIZE-OFST_DATA_S	; スタートセクタのデータサイズをループ回数にセット
	MOVWF	TMP01			; TMP01は受信ループ回数
	CLRF	TMP02			; TMP02は受信したバイト数のカウント
	CLRF	TMP03			; TMP03はセクタあたりの有効バイト数
	MOVLW	OFST_DATA_S		; I2C EEPROMにデータを書き込むアドレスのオフセット、スタートセクタだけアドレスが違う
	MOVWF	TMP10			; TMP10はEEPROMに書き込むデータのアドレスオフセットを保持
	BSF	RCSTA,CREN
CMD_PUT_LOOP
	MOVLW	DATABUF			; 受信バッファに間接アクセス
	MOVWF	FSR
CMD_PUT_RECV				; 受信ループ
	CALL	rxserial
	MOVF	RXDATA,W		; EOFコード(データ終端)が来たかチェック
	SUBLW	EOF
	BTFSC	STATUS,Z
	GOTO	CMD_PUT_RECV_EOF	; EOFコードならデータ入力を中断して終了
CMD_PUT_RECV2				; SECTOR2=1の戻り場所
	MOVF	RXDATA,W		; 文字を追加
	MOVWF	INDF
	INCF	FSR,F			; ポインタをインクリメント
	INCF	TMP02,F			; データサイズをカウント
	DECFSZ	TMP01,F			; 最大受信文字数-1
	GOTO	CMD_PUT_RECV

	MOVF	TMP02,W			; 受信が終わったので書き込み
	MOVWF	I2CSIZE			; 受信したバイト数
	ADDWF	TMP03,F			; セクタサイズを計算
	CALL	sect2addr
	MOVF	TMP10,W			; 書き込みオフセットを計算
	ADDWF	I2CADRL,F
	CALL	i2cpwrite

	BTFSC	FLAG,SECTOR2		; SECTOR2フラグで次の受信バイト数とオフセットを切り替える
	GOTO	CMD_PUT_SECTOR2_1
CMD_PUT_SECTOR2_0			; SECTOR2が0の時は、フラグをONにしてサイズを64バイト、オフセットを0にする(後半ブロックの受信)
	MOVLW	BUFSIZE			; バッファサイズをロード
	MOVWF	TMP01
	CLRF	TMP02			; 受信データサイズをリセット
	CLRF	TMP10			; オフセットを0
	BSF	FLAG,SECTOR2
	GOTO	CMD_PUT_LOOP
CMD_PUT_SECTOR2_1			; SECTOR2が1の時は、次にEOFが来るかチェックして次のセクタを使うかを決める
	CALL	rxserial
	MOVF	RXDATA,W		; EOFコード(データ終端)が来たかチェック
	SUBLW	EOF
	BTFSC	STATUS,Z
	GOTO	CMD_PUT_NEXT_EOF	; EOFコードならデータ入力を中断して終了

	BCF	FLAG,SECTOR2		; データが続くならば、次のセクタをサーチ
	MOVF	SECTOR,W		; 現在のセクタアドレスをTMP11にバックアップ
	MOVWF	TMP11
	INCF	SECTOR,F		; セクタアドレス+1
	MOVLW	INDEX_BLANK		; ブランクインデックスをサーチ
	CALL	indexsearch
	BTFSC	FLAG,NO_INDEX		; ブランクインデックスが見つからなかった場合は、保存したデータを消去
	GOTO	CMD_PUT_FULL		; セクタアドレス+1でロールオーバーしたときも、理論的に空きセクタ無しになる

	MOVF	SECTOR,W		; TMP12に次のブランクセクタを保存
	MOVWF	TMP12
	MOVF	TMP11,W			; サイズと次のセクタを書き込まないといけないため、現在のセクタを復元
	MOVWF	SECTOR

	MOVLW	DATABUF			; 現在のセクタのサイズ、次アドレスを書き込み
	MOVWF	FSR
	MOVLW	0x80			; 次セクタありのフラグを付けて、セクタサイズをロード
	IORWF	TMP03,W			; 0〜125は次のセクタ無し、次のセクタがありの時は必ず237か253になるはず
	MOVWF	INDF			; サイズヘッダ確定
	INCF	FSR,F
	MOVF	TMP12,W			; 次のフラグメントセクタアドレスを確定
	MOVWF	INDF
	MOVLW	2			; 書き込むヘッダのサイズ
	MOVWF	I2CSIZE
	CALL	sect2addr		; セクタ前半のアドレスを計算
	INCF	I2CADRL,F		; サイズヘッダのオフセットを追加
	CALL	i2cpwrite		; サイズと次のアドレスを書き込み

	MOVF	TMP12,W
	MOVWF	SECTOR			; 次のセクタアドレスをロード
	CALL	sect2addr
	MOVLW	INDEX_FRAGMENT		; フラグメントセクタのインデックスを書き込み
	MOVWF	I2CDATA
	CALL	i2cwrite

	MOVLW	BUFSIZE-OFST_DATA_F	; フラグメントセクタ前半の受信バイト数をロード
	MOVWF	TMP01
	CLRF	TMP02			; 受信したバイト数をクリア
	CLRF	TMP03			; セクタあたりの有効バイト数をクリア
	MOVLW	OFST_DATA_F		; フラグメントセクタのアドレスオフセットをロード
	MOVWF	TMP10
	MOVLW	DATABUF
	MOVWF	FSR
	GOTO	CMD_PUT_RECV2		; フラグメントセクタの先頭1バイトはすでに受信しているため、受信後のループ中にジャンプ

CMD_PUT_FULL				; 書き込み中にメモリフルになってしまった場合の処理
	MOVF	TMP11,W			; 現在のセクタアドレスを復元
	MOVWF	SECTOR
	CALL	sect2addr
	MOVLW	OFST_SIZE		; 現在のセクタサイズに次セクタ無しを書き込む
	ADDWF	I2CADRL,F
	CLRF	I2CDATA
	CALL	i2cwrite
	MOVF	TMP00,W			; 保存しておいたスタートセクタにシークして、それまで保存したファイルの削除を行う
	MOVWF	SECTOR
CMD_PUT_DEL_LOOP			; 内容はdelコマンドと同じ
	CALL	sect2addr		; セクタ前半のヘッダ部分を読み出し
	MOVLW	OFST_NAME		; ファイル名までの3バイト分
	MOVWF	I2CSIZE
	CALL	i2cpread
	CALL	sect2addr		; セクタのインデックスにブランクを書き込み
	MOVLW	INDEX_BLANK
	MOVWF	I2CDATA
	CALL	i2cwrite
	BSF	STATUS,RP0
	BTFSS	ADDR_SIZE,NEXT_SECTOR	; 次のセクタが使用されているか?
	GOTO	CMD_PUT_FULL_END	; エラーを送信して終了
	MOVF	ADDR_NEXT,W		; 使われているならば、次のフラグメントセクタのアドレスを取得
	BCF	STATUS,RP0
	MOVWF	SECTOR
	GOTO	CMD_PUT_DEL_LOOP
CMD_PUT_FULL_END			; エラーを表示してキーの入力待ち
	BCF	STATUS,RP0
	BCF	PORTC,RS_OUT		; 受信可信号を出して送信側のバッファをフラッシュする
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_diskfull
	CALL	txserial
	GOTO	CMD_RECEIVE

CMD_PUT_RECV_EOF			; データの受信中にEOFが来た時の処理
	MOVF	TMP02,W			; 受信が終わったので書き込み
	MOVWF	I2CSIZE			; 受信したバイト数
	ADDWF	TMP03,F			; セクタサイズを計算
	CALL	sect2addr
	MOVF	TMP10,W			; 書き込みオフセットを計算
	ADDWF	I2CADRL,F
	CALL	i2cpwrite
CMD_PUT_NEXT_EOF			; データの書き込みが終わってるセクタ間のEOFに関しては、ここにジャンプする
	BCF	FLAG,SECTOR2		; セクタ前半を選択して、サイズとダミーセクタを書き込む
	MOVLW	DATABUF
	MOVWF	FSR
	MOVF	TMP03,W			; TMP03の7ビット目はONになることは無いため、次のセクタは無効になる
	MOVWF	INDF
	INCF	FSR,F
	MOVF	SECTOR,W		; 無効になる次セクタは自分のアドレスを入れておく
	MOVWF	INDF
	CALL	sect2addr
	MOVLW	OFST_SIZE
	ADDWF	I2CADRL,F
	MOVLW	2
	MOVWF	I2CSIZE
	CALL	i2cpwrite
	GOTO	CMD_RECEIVE


CMD_GET				; ファイルの読み出しルーチン
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	ARGV1			; ファイル名の入っているポインタを
	CALL	filesearch		; ファイルサーチに渡す
	BTFSS	FLAG,NO_FILE
	GOTO	CMD_GET_STANDBY
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_filenotfound	; ファイルが見つからなかった
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_GET_STANDBY
	MOVLW	LED_ORANGE		; 橙LED点滅
	CALL	getkey			; 送信スタンバイ
CMD_GET_LOOP
	MOVLW	BUFSIZE
	MOVWF	I2CSIZE
	CALL	sect2addr		; セクタ前半を64バイト読み出し
	CALL	i2cpread
	MOVLW	OFST_DATA_F		; フラグメントセクタのデータオフセットを格納
	MOVWF	TXOFFSET
	BSF	STATUS,RP0
	MOVF	DATABUF,W		; スタートセクタのインデックスがあるときだけ、データオフセットを変更する
	BCF	STATUS,RP0
	SUBLW	INDEX_START
	MOVLW	OFST_DATA_S
	BTFSC	STATUS,Z
	MOVWF	TXOFFSET
	BSF	STATUS,RP0
	MOVF	ADDR_SIZE,W		; セクタ内のデータサイズをチェック
	BCF	STATUS,RP0
	MOVWF	TMP00			; 後半セクタ処理のために保存、次セクタ有効ビットを含めた値
	ANDLW	0x7F			; 最上位ビットはフラグメントビットのため除外
	MOVWF	TMP01			; 後半セクタ処理のために保存、次セクタ有効ビットを含まない値

	MOVLW	61			; 前半セクタの最大送信バイト数を計算
	MOVWF	TMP02			; フラグメントセクタの場合データサイズが61バイト以上ある場合
	BSF	STATUS,RP0
	MOVF	DATABUF,W		; スタートセクタのインデックスがあるときだけ、データサイズを変更する
	BCF	STATUS,RP0
	SUBLW	INDEX_START
	MOVLW	45
	BTFSC	STATUS,Z
	MOVWF	TMP02

	MOVF	TMP01,W			; 送信サイズを決定
	MOVWF	TXSIZE
	MOVF	TMP01,W			; 最大サイズからデータサイズを引き、
	SUBWF	TMP02,W			; 最大サイズを超えていたら、送信するバイト数を強制変更
	MOVF	TMP02,W
	BTFSS	STATUS,C
	MOVWF	TXSIZE			; 変更
	CALL	txserial		; 送信!

	MOVF	TMP01,W			; 前半の最大バイト数からセクタ内のデータサイズを引く
	SUBWF	TMP02,W
	BTFSC	STATUS,C		; データサイズが前半セクタで終わっている場合は、EOFを送出して終了
	GOTO	CMD_GET_EOF

	MOVF	TMP02,W			; 後半のバイト数を計算
	SUBWF	TMP01,W
	MOVWF	TXSIZE			; 後半のバイト分送信
	MOVWF	I2CSIZE			; 後半のバイト分読み出し
	BSF	FLAG,SECTOR2
	CALL	sect2addr
	CALL	i2cpread
	CLRF	TXOFFSET		; 後半セクタは0バイト目から送信
	CALL	txserial		; 送信!

	BTFSS	TMP00,NEXT_SECTOR	; 次セクタ有効ビットがONの場合はループ
	GOTO	CMD_GET_EOF
	INCF	SECTOR,F
	BCF	FLAG,SECTOR2
	GOTO	CMD_GET_LOOP
CMD_GET_EOF
	BTFSS	FLAG,EOFCODE		; 行末にEOFを使わないとき
	GOTO	CMD_RECEIVE
	MOVLW	EOF
	BSF	STATUS,RP0
	MOVWF	DATABUF
	BCF	STATUS,RP0
	MOVLW	1
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	txserial		; EOF送信
	GOTO	CMD_RECEIVE


CMD_DEL					; ファイルの削除ルーチン
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	ARGV1			; ファイル名の入っているポインタを
	CALL	filesearch		; ファイルサーチに渡す
	BTFSS	FLAG,NO_FILE
	GOTO	CMD_DEL_LOOP
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_filenotfound	; ファイルが見つからなかった
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_DEL_LOOP
	CALL	sect2addr		; セクタ前半のヘッダ部分を読み出し
	MOVLW	OFST_NAME		; ファイル名までの3バイト分
	MOVWF	I2CSIZE
	CALL	i2cpread
	CALL	sect2addr		; セクタのインデックスにブランクを書き込み
	MOVLW	INDEX_BLANK
	MOVWF	I2CDATA
	CALL	i2cwrite
	BSF	STATUS,RP0
	BTFSS	ADDR_SIZE,NEXT_SECTOR	; 次のセクタが使用されているか?
	GOTO	CMD_DEL_END
	MOVF	ADDR_NEXT,W		; 使われているならば、次のフラグメントセクタのアドレスを取得
	BCF	STATUS,RP0
	MOVWF	SECTOR
	GOTO	CMD_DEL_LOOP
CMD_DEL_END
	BCF	STATUS,RP0
	BTFSC	FLAG2,OVER_CMD		; オーバーライトコマンド中なら書き込みルーチンへジャンプ
	GOTO	CMD_PUT1
	GOTO	CMD_COMPLETE


CMD_REN					; ファイル名の変更ルーチン
	MOVLW	2			; 引数は2個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	ARGV1			; 変更前のファイルが存在するかチェック
	CALL	filesearch
	BTFSS	FLAG,NO_FILE
	GOTO	CMD_REN1
	MOVLW	LED_RED
	CALL	getkey
	BSF	PCLATH,3
	CALL	err_filenotfound	; ファイルが見つからなかった
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_REN1
	MOVF	SECTOR,W		; 見つかったファイルのセクタ番号を保存
	MOVWF	TMP00
	MOVLW	ARGV2			; 変更後のファイルが存在するかチェック
	CALL	filesearch
	BTFSC	FLAG,NO_FILE
	GOTO	CMD_REN2
	MOVLW	LED_RED
	CALL	getkey
	BSF	PCLATH,3
	CALL	err_fileexist		; ファイルがすでに存在する
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_REN2
	MOVLW	ARGVSIZE		; ファイル名の空き文字をヌルでクリア
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	MOVLW	NULL
	MOVWF	TMP32
	CALL	bufclear

	MOVLW	ARGV2			; 変更後のファイル名バッファに転送
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcopy

	MOVLW	ARGVSIZE		; 16バイト書き込み
	MOVWF	I2CSIZE
	MOVF	TMP00,W			; セクタ番号を呼び出し
	MOVWF	SECTOR
	CALL	sect2addr		; 書き込むアドレスをファイル名の部分にずらす
	MOVLW	OFST_NAME
	ADDWF	I2CADRL,F
	CALL	i2cpwrite
	GOTO	CMD_COMPLETE


CMD_OVER				; ファイルの上書きルーチン
	MOVLW	LED_ORANGE		; ファイルが上書きされるので、確認スイッチの入力をつけておく
	CALL	getkey
	BSF	FLAG2,OVER_CMD		; オーバーライトコマンド中を指示
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	ARGV1			; 保存するファイルが存在するかチェック
	CALL	filesearch
	BTFSC	FLAG,NO_FILE
	GOTO	CMD_PUT1		; 存在しないならそのまま書き込み
	GOTO	CMD_DEL_LOOP		; 存在するならファイルを消去した後に書き込み


CMD_SIZE
	CLRF	TMP20
	CLRF	TMP21
	MOVLW	LED_ORANGE
	CALL	getkey
	BSF	RCSTA,CREN		; キーの入力後から受信を開始する
CMD_SIZE_RECV				; 受信ループ
	MOVLW	125			; データを吸い込んでいるのか分からないので、125バイトごとにオレンジLEDを点滅させる
	MOVWF	TMP00
CMD_SIZE_RECV2
	CALL	rxserial
	MOVF	RXDATA,W		; EOFコード(データ終端)が来たかチェック
	SUBLW	EOF
	BTFSC	STATUS,Z
	GOTO	CMD_SIZE_END		; EOFコードならデータ入力を中断して終了

	INCF	TMP21,F			; サイズ+1
	BTFSS	STATUS,Z
	GOTO	CMD_SIZE_RECV3
	INCF	TMP20,F
CMD_SIZE_RECV3				; LED点滅カウント
	DECFSZ	TMP00,F
	GOTO	CMD_SIZE_RECV2		; カウンタ満了で無い場合は普通にループ
	BTFSS	PORTB,LED_G
	GOTO	CMD_SIZE_LED1
	CLRF	PORTB
	GOTO	CMD_SIZE_RECV		; 満了した場合は、カウンタをリセットしてループ
CMD_SIZE_LED1
	MOVLW	LED_ORANGE
	MOVWF	PORTB
	GOTO	CMD_SIZE_RECV
CMD_SIZE_END
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB

	BTFSS	FLAG,LINE_NUMBER	; 行番号を送る?
	GOTO	CMD_SIZE_END2
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	'1'			; 行番号は1のみ
	MOVWF	INDF
	MOVLW	1			; 1文字送信
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	txserial
CMD_SIZE_END2
	BSF	PCLATH,3
	CALL	msg_size
	CALL	txserial
	BSF	PCLATH,3		; msg_sizeでバンク0に戻されるので再度バンク1へ移動
	CALL	hex2text
	CALL	txserial
	BSF	PCLATH,3		; hex2textでバンク0に戻されるので再度バンク1へ移動
	CALL	msg_bytes
	CALL	txserial
	GOTO	CMD_RECEIVE


CMD_LS					; ファイルリスト送信
	CLRF	TMP12			; ファイル数カウンタH
	CLRF	TMP13			; ファイル数カウンタL
	CLRF	SECTOR			; セクタ0から検索
CMD_LS_LOOP
	MOVLW	INDEX_START
	CALL	indexsearch
	BTFSS	FLAG,NO_INDEX		; ファイルが見つからなかったとき
	GOTO	CMD_LS_LOOP2
	MOVF	TMP13,W
	BTFSS	STATUS,Z
	GOTO	CMD_LS_EOF_END
	MOVF	TMP12,W
	BTFSS	STATUS,Z
	GOTO	CMD_LS_EOF_END
	BSF	PCLATH,3		; 一つもファイルが見つからなかったときは別の表示に変える
	CALL	err_filenotfound
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB
	CALL	txserial
	GOTO	CMD_COMPLETE
CMD_LS_LOOP2
	MOVLW	1			; ファイル発見
	ADDWF	TMP13,F
	BTFSC	STATUS,C
	INCF	TMP12,F
	CLRF	TMP10			; ファイルサイズカウンタH 初期化
	CLRF	TMP11			; ファイルサイズカウンタL
	MOVLW	OFST_DATA_S		; サイズ表示に使うため、インデックスからファイル名までを一度に読み出す
	MOVWF	I2CSIZE
	CALL	i2cpread

	MOVLW	ARGVSIZE		; ファイル名の空き文字をスペースでクリア
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	MOVLW	' '
	MOVWF	TMP32
	CALL	bufclear
	MOVLW	DATABUF+OFST_NAME	; ファイル名をバッファに転送&退避(ヌルをスペースに置換する)
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcopy
	MOVF	SECTOR,W		; フラグメントセクタの検索をするため、スタートセクタの位置を記憶しておく
	MOVWF	TMP22
CMD_LS_LOOP3
	BSF	STATUS,RP0		; ファイルサイズをカウント
	MOVF	ADDR_SIZE,W
	ANDLW	0x7F			; サイズを抽出
	BCF	STATUS,RP0
	ADDWF	TMP11,F
	BTFSC	STATUS,C		; 桁上がりした場合は上位をインクリメント
	INCF	TMP10,F

	BSF	STATUS,RP0		; ファイルサイズをカウント
	BTFSS	ADDR_SIZE,NEXT_SECTOR	; フラグメントセクタがあるか?
	GOTO	CMD_LS_LOOP4		; 無ければ転送処理
	MOVF	ADDR_NEXT,W		; あればフラグメントセクタのサイズを加算
	BCF	STATUS,RP0
	MOVWF	SECTOR
	CALL	sect2addr
	MOVLW	OFST_DATA_F		; サイズ表示に使うため、インデックスから次セクタアドレスまで読み出す
	MOVWF	I2CSIZE
	CALL	i2cpread
	GOTO	CMD_LS_LOOP3
CMD_LS_LOOP4
	BCF	STATUS,RP0
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB
	BTFSS	FLAG,LINE_NUMBER	; 行番号を送る?
	GOTO	CMD_LS_LOOP5
	MOVF	TMP12,W			; 行番号を5桁で送信
	MOVWF	TMP20
	MOVF	TMP13,W
	MOVWF	TMP21
	BSF	PCLATH,3
	CALL	hex2text
	CALL	txserial
CMD_LS_LOOP5
	BSF	STATUS,RP0
	MOVLW	' '
	MOVWF	DATABUF+ARGVSIZE	; ファイル名とサイズ表示の間にスペースを挿入
	BCF	STATUS,RP0
	MOVLW	ARGV1			; スペースを付けて退避したファイル名を送信
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	CALL	bufcopy
	MOVLW	ARGVSIZE+1
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	txserial
	BSF	PCLATH,3
	MOVF	TMP10,W
	MOVWF	TMP20
	MOVF	TMP11,W
	MOVWF	TMP21
	CALL	hex2text
	CALL	txserial
	BSF	PCLATH,3
	CALL	CR_LF_SEND
	INCF	TMP22,W
	MOVWF	SECTOR
	GOTO	CMD_LS_LOOP
CMD_LS_EOF_END
	BSF	PCLATH,3
	CALL	EOF_SEND
	GOTO	CMD_RECEIVE


CMD_DF
	MOVLW	2			; 引数の有無によって動作を切り替える
	SUBWF	ARGC,W
	BTFSC	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG		; 2個ある場合はエラー
	MOVLW	'1'			; 行番号カウンタを初期値にセット
	MOVWF	TMP03
	MOVLW	1
	SUBWF	ARGC,W
	BTFSS	STATUS,Z
	GOTO	CMD_DF_ALL		; 0個の時は全ドライブ検索

	BSF	STATUS,RP0
	MOVF	ARGV1+1,W		; 2バイト目がNULLなら引数は1文字になる(引数の文字数チェック)
	BCF	STATUS,RP0
	SUBLW	0
	BTFSS	STATUS,Z
	GOTO	CMD_WRONGARG
	MOVLW	'1'			; 引数が1個の時は、ドライブレターを調べて装着されているドライブより大きくないかをチェック
	BSF	STATUS,RP0		; '*'-'1'をする
	SUBWF	ARGV1,W
	MOVWF	ARGV1
	BCF	STATUS,RP0
	SUBWF	MAXDRIVE,W
	BTFSS	STATUS,C		; MAXDRIVEより大きい数が入っている時はエラー
	GOTO	CMD_WRONGARG

	BSF	STATUS,RP0		; 検索スタートドライブを引数のものにセット
	MOVF	ARGV1,W
	BCF	STATUS,RP0
	MOVWF	TMP00
	MOVLW	1			; ループ回数をセット、ドライブ指定なので1回だけ
	MOVWF	TMP01
	GOTO	CMD_DF_CALC

CMD_DF_ALL				; 全てのドライブの容量チェック
	CLRF	TMP00			; 検索スタートドライブを1に設定
	INCF	MAXDRIVE,W		; 装着されているドライブの数の分だけループ
	MOVWF	TMP01
CMD_DF_CALC				; 容量の計算
	MOVF	I2CCHIP,W		; カレントドライブをセーブ
	MOVWF	TMP02
	MOVF	TMP00,W			; 検索したいドライブをセット
	MOVWF	I2CCHIP
CMD_DF_LOOP				; 計算ループ
	CLRF	SECTOR			; 0セクタから検索
	BCF	FLAG,SECTOR2		; 後半セクタフラグをリセットしておく
	CLRF	TMP10			; 使用H
	CLRF	TMP11			; 使用L
	CLRF	TMP12			; 空きH
	CLRF	TMP13			; 空きL
CMD_DF_LOOP2
	CALL	sect2addr		; セクタの1バイト目だけを読み込む
	CALL	i2cread
	MOVLW	INDEX_BLANK
	SUBWF	I2CDATA,W
	BTFSC	STATUS,Z		; ブランクセクタの時の容量をプラス
	GOTO	CMD_DF_BLANK
	MOVLW	INDEX_START
	SUBWF	I2CDATA,W
	BTFSC	STATUS,Z		; スタートセクタの時の容量をプラス
	GOTO	CMD_DF_START
	MOVLW	INDEX_FRAGMENT
	SUBWF	I2CDATA,W
	BTFSC	STATUS,Z		; フラグメントセクタの時の容量をプラス
	GOTO	CMD_DF_FRAGMENT
CMD_DF_LOOP3				; プラス後の後処理
	INCF	SECTOR,F		; セクタ番号をインクリメント
	BTFSS	STATUS,Z		; 最後のセクタまで検索
	GOTO	CMD_DF_LOOP2

	MOVLW	OFST_DATA_S-OFST_DATA_F	; 空き容量は、実際にファイルを書き込むとファイル名の分だけ小さくなるので、
	SUBWF	TMP13,F			; 実際のサイズを計算しておく
	BTFSC	STATUS,C		; 桁下がりするなら、上位をデクリメント
	GOTO	CMD_DF_LOOP4
	MOVLW	1
	SUBWF	TMP12,F
	BTFSC	STATUS,C		; 上位も桁下がりをする(=空き容量カウントが0のとき)
	GOTO	CMD_DF_LOOP4
	CLRF	TMP12			; 空き容量を0に戻す
	CLRF	TMP13
CMD_DF_LOOP4
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB

	BTFSS	FLAG,LINE_NUMBER	; 行番号を送る?
	GOTO	CMD_DF_LOOP5
	MOVLW	DATABUF
	MOVWF	FSR
	MOVF	TMP03,W			; 行番号をロード
	MOVWF	INDF
	MOVLW	1			; 1文字送信
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	txserial
CMD_DF_LOOP5
	BSF	PCLATH,3
	CALL	df_used			; ドライブレターと"Used="の表示
	CALL	txserial
	MOVF	TMP10,W			; 使用容量の表示
	MOVWF	TMP20
	MOVF	TMP11,W
	MOVWF	TMP21
	BSF	PCLATH,3
	CALL	hex2text
	CALL	txserial
	BSF	PCLATH,3
	CALL	df_free			; " Free="の表示
	CALL	txserial
	MOVF	TMP12,W			; 空き容量の表示
	MOVWF	TMP20
	MOVF	TMP13,W
	MOVWF	TMP21
	BSF	PCLATH,3
	CALL	hex2text
	CALL	txserial
	BSF	PCLATH,3
	CALL	CR_LF_SEND		; 改行コードの送信

	DECF	TMP01,F			; ループ回数をデクリメント
	BTFSC	STATUS,Z
	GOTO	CMD_DF_END		; ループ回数満了時は終了
	INCF	I2CCHIP,F		; 満了していない時は、ドライブ番号をインクリメント
	INCF	TMP03,F			; 行番号をインクリメント
	GOTO	CMD_DF_LOOP
CMD_DF_BLANK				; ブランクセクタの容量プラス
	MOVLW	128-OFST_DATA_F
	ADDWF	TMP13,F
	BTFSS	STATUS,C
	GOTO	CMD_DF_LOOP3
	INCF	TMP12,F			; 桁上がりしたら上位をインクリメント
	GOTO	CMD_DF_LOOP3

CMD_DF_START
	MOVLW	128-OFST_DATA_S		; スタートセクタの容量プラス
	ADDWF	TMP11,F
	BTFSS	STATUS,C
	GOTO	CMD_DF_LOOP3
	INCF	TMP10,F			; 桁上がりしたら上位をインクリメント
	GOTO	CMD_DF_LOOP3

CMD_DF_FRAGMENT
	MOVLW	128-OFST_DATA_F		; フラグメントセクタの容量プラス
	ADDWF	TMP11,F
	BTFSS	STATUS,C
	GOTO	CMD_DF_LOOP3
	INCF	TMP10,F			; 桁上がりしたら上位をインクリメント
	GOTO	CMD_DF_LOOP3

CMD_DF_END				; 終了処理
	MOVF	TMP02,W			; カレントドライブを復元
	MOVWF	I2CCHIP
	BSF	PCLATH,3
	CALL	EOF_SEND		; EOFを送信
	GOTO	CMD_RECEIVE


CMD_CD					; カレントドライブの変更
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	BSF	STATUS,RP0
	MOVF	ARGV1+1,W		; 1バイト目がNULLなら引数は1文字になる
	BCF	STATUS,RP0
	SUBLW	0
	BTFSS	STATUS,Z
	GOTO	CMD_WRONGARG
	MOVLW	'1'			; '*'-'1'をする
	BSF	STATUS,RP0
	SUBWF	ARGV1,F
	MOVLW	8
	SUBWF	ARGV1,W
	BCF	STATUS,RP0
	BTFSC	STATUS,C		; 'i'より大きい数が入っている時はエラー
	GOTO	CMD_WRONGARG

	BSF	STATUS,RP0
	MOVF	ARGV1,W
	BCF	STATUS,RP0
	SUBWF	MAXDRIVE,W
	BTFSC	STATUS,C		; MAXDRIVEよりも大きい場合はエラーを表示
	GOTO	CMD_CD_GET
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_driveover
	CALL	txserial
	GOTO	CMD_RECEIVE
CMD_CD_GET
	BSF	STATUS,RP0
	MOVF	ARGV1,W
	BCF	STATUS,RP0
	MOVWF	I2CCHIP			; チップセレクトにロード
	GOTO	CMD_COMPLETE


CMD_MKFS				; ファイルシステムの作成
	MOVLW	LED_ORANGE		; データを初期化する前に、確認のスイッチ入力を設ける
	CALL	getkey
	MOVLW	BUFSIZE			; ファイルシステムの作成とは言ったものの、
	MOVWF	I2CSIZE			; 空きセクタは先頭が0x00なので、単に領域をゼロクリアするだけ
	MOVWF	TMP30
	MOVLW	DATABUF
	MOVWF	TMP31
	MOVLW	0x00
	MOVWF	TMP32
	CALL	bufclear
	CLRF	SECTOR			; セクタ数がロールオーバーするまでループ(=256)
CMD_MKFS_LOOP
	BCF	FLAG,SECTOR2		; 各セクタを0x00でクリアする
	CALL	sect2addr		; セクタ前半
	CALL	i2cpwrite
	BSF	FLAG,SECTOR2		; セクタ後半
	CALL	sect2addr
	CALL	i2cpwrite

	INCF	SECTOR,F
	BTFSS	STATUS,Z		; ロールオーバーしたなら終了
	GOTO	CMD_MKFS_LOOP
	GOTO	CMD_RECEIVE


CMD_SET					; システムパラメータの変更
	MOVLW	2			; 引数は2個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG
CMD_SET_1200
	MOVLW	CMPBUF			; USARTスピードのチェック
	BSF	PCLATH,3
	CALL	argset_1200		; "1200"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_SET_2400
	MOVLW	SPBRG_1200		; 一致していたならば所定の数値をセット
	MOVWF	TMP20
	GOTO	CMD_SET_DRIVE
CMD_SET_2400
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argset_2400		; "2400"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_SET_4800
	MOVLW	SPBRG_2400
	MOVWF	TMP20
	GOTO	CMD_SET_DRIVE
CMD_SET_4800
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argset_4800		; "4800"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_SET_9600
	MOVLW	SPBRG_4800
	MOVWF	TMP20
	GOTO	CMD_SET_DRIVE
CMD_SET_9600
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argset_9600		; "9600"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_SET_19200
	MOVLW	SPBRG_9600
	MOVWF	TMP20
	GOTO	CMD_SET_DRIVE
CMD_SET_19200
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argset_19200		; "19200"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_WRONGARG
	MOVLW	SPBRG_19200
	MOVWF	TMP20
CMD_SET_DRIVE				; MAXDRIVEの値
	BSF	STATUS,RP0
	MOVF	ARGV2+1,W		; 2バイト目がNULLなら2番目の引数は1文字になる(引数の文字数チェック)
	BCF	STATUS,RP0
	SUBLW	0
	BTFSS	STATUS,Z
	GOTO	CMD_WRONGARG
	MOVLW	'1'			; '*'-'1'をする
	BSF	STATUS,RP0
	SUBWF	ARGV2,F
	MOVLW	8
	SUBWF	ARGV2,W
	BCF	STATUS,RP0
	BTFSC	STATUS,C		; '8'より大きい数が入っている時はエラー
	GOTO	CMD_WRONGARG		; '1'より小さい数の時も、'1'を基準に大小を判別しているので、自動的にエラーとなる
	BSF	STATUS,RP0
	MOVF	ARGV2,W
	BCF	STATUS,RP0
	MOVWF	TMP21

	MOVLW	EEP_SPBRG
	MOVWF	EEPADDR
	MOVF	TMP20,W
	MOVWF	EEPDATA
	CALL	eepwrite
	MOVLW	EEP_MAXDRIVE
	MOVWF	EEPADDR
	MOVF	TMP21,W
	MOVWF	EEPDATA
	CALL	eepwrite
	GOTO	CONFIG_READ


CMD_NUM					; 行番号追加を変更
	MOVLW	1			; 引数は1個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	3			; 引数を小文字に変換する(引数は最大3文字)
	MOVWF	TMP00
	MOVLW	ARGV1
	MOVWF	FSR
	CALL	to_lower		; 引数を小文字に変換
CMD_NUM_LN				; 行番号使用を確認
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	arg_off			; "off"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_NUM_LN_ON
	BCF	FLAG,LINE_NUMBER
	GOTO	CMD_NUM_END

CMD_NUM_LN_ON
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	arg_on			; "on"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_WRONGARG
	BSF	FLAG,LINE_NUMBER
CMD_NUM_END
	GOTO	CMD_COMPLETE


CMD_TERM				; 改行コードの変更
	MOVLW	2			; 引数は2個
	SUBWF	ARGC,W
	BTFSS	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_WRONGARG

	MOVLW	B'11110000'		; FLAGの上位4ビットが破壊されないようにTMP21にバックアップする
	ANDWF	FLAG,W
	MOVWF	TMP21

	MOVLW	4			; 改行コードの引数を小文字に変換する(改行コードは最大4文字)
	MOVWF	TMP00
	MOVLW	ARGV1
	MOVWF	FSR
	CALL	to_lower

	MOVLW	3			; 改行コードの引数を小文字に変換する(改行コードは最大4文字)
	MOVWF	TMP00
	MOVLW	ARGV2
	MOVWF	FSR
	CALL	to_lower
CMD_TERM_CR
	MOVLW	CMPBUF			; 改行コードのチェック
	BSF	PCLATH,3
	CALL	argterm_cr		; "cr"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_TERM_LF
	MOVLW	B'00000010'		; 一致していたならば改行コードをセット
	MOVWF	TMP20
	GOTO	CMD_TERM_EOF_OFF

CMD_TERM_LF
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argterm_lf		; "lf"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_TERM_CRLF
	MOVLW	B'00000100'
	MOVWF	TMP20
	GOTO	CMD_TERM_EOF_OFF

CMD_TERM_CRLF
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	argterm_crlf		; "crlf"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_WRONGARG
	MOVLW	B'00000111'
	MOVWF	TMP20

CMD_TERM_EOF_OFF			; 行末EOFの使用を確認
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	arg_off			; "off"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV2
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_TERM_EOF_ON
	BCF	TMP20,EOFCODE
	GOTO	CMD_TERM_END

CMD_TERM_EOF_ON
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	arg_on			; "on"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV2
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_WRONGARG
	BSF	TMP20,EOFCODE
CMD_TERM_END
	MOVF	TMP20,W
	IORWF	TMP21,W			; バックアップしたFLAGの上位4ビットを併合
	MOVWF	FLAG
	GOTO	CMD_COMPLETE


CMD_STAT
	BSF	PCLATH,3
	CALL	msg_status
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB
	CALL	txserial
	GOTO	CMD_COMPLETE


CMD_HELP
	MOVLW	2			; 引数の有無によって動作を切り替える
	SUBWF	ARGC,W
	BTFSC	STATUS,Z		; 引数の個数チェック
	GOTO	CMD_HELP_CMDLIST	; 2個ある場合はコマンドリスト
	MOVLW	1
	SUBWF	ARGC,W
	BTFSS	STATUS,Z
	GOTO	CMD_HELP_CMDLIST	; 0個の時はコマンドリスト

	MOVLW	4			; 引数を小文字に変換する(引数は最大4文字)
	MOVWF	TMP00
	MOVLW	ARGV1
	MOVWF	FSR
	CALL	to_lower
CMD_HELP_PUT
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdput			; "put"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_GET
	BSF	PCLATH,3
	CALL	help_put
	GOTO	CMD_HELP_SEND

CMD_HELP_GET
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdget			; "get"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_DEL
	BSF	PCLATH,3
	CALL	help_get
	GOTO	CMD_HELP_SEND

CMD_HELP_DEL
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmddel			; "del"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_REN
	BSF	PCLATH,3
	CALL	help_del
	GOTO	CMD_HELP_SEND

CMD_HELP_REN
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdren			; "ren"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_OVER
	BSF	PCLATH,3
	CALL	help_ren
	GOTO	CMD_HELP_SEND

CMD_HELP_OVER
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdover			; "over"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_SIZE
	BSF	PCLATH,3
	CALL	help_over
	GOTO	CMD_HELP_SEND

CMD_HELP_SIZE
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdsize			; "size"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_LS
	BSF	PCLATH,3
	CALL	help_size
	GOTO	CMD_HELP_SEND

CMD_HELP_LS
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdls			; "ls"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_DF
	BSF	PCLATH,3
	CALL	help_ls
	GOTO	CMD_HELP_SEND

CMD_HELP_DF
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmddf			; "df"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_CD
	BSF	PCLATH,3
	CALL	help_df
	GOTO	CMD_HELP_SEND

CMD_HELP_CD
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdcd			; "cd"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_MKFS
	BSF	PCLATH,3
	CALL	help_cd
	GOTO	CMD_HELP_SEND

CMD_HELP_MKFS
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdmkfs			; "mkfs"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_SET
	BSF	PCLATH,3
	CALL	help_mkfs
	GOTO	CMD_HELP_SEND

CMD_HELP_SET
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdset			; "set"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_NUM
	BSF	PCLATH,3
	CALL	help_set
	GOTO	CMD_HELP_SEND

CMD_HELP_NUM
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdnum			; "num"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_TERM
	BSF	PCLATH,3
	CALL	help_num
	GOTO	CMD_HELP_SEND

CMD_HELP_TERM
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdterm			; "term"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_STAT
	BSF	PCLATH,3
	CALL	help_term
	GOTO	CMD_HELP_SEND

CMD_HELP_STAT
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdstat			; "stat"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_HELP
	BSF	PCLATH,3
	CALL	help_stat
	GOTO	CMD_HELP_SEND

CMD_HELP_HELP
	MOVLW	CMPBUF
	BSF	PCLATH,3
	CALL	cmdhelp			; "help"?
	MOVLW	CMPBUF
	MOVWF	TMP30
	MOVLW	ARGV1
	MOVWF	TMP31
	CALL	bufcmp
	BTFSC	FLAG2,DIFF
	GOTO	CMD_HELP_CMDLIST
	BSF	PCLATH,3
	CALL	help_help
	GOTO	CMD_HELP_SEND

CMD_HELP_CMDLIST			; コマンドリスト送信
	BSF	PCLATH,3
	CALL	help_cmdlist
CMD_HELP_SEND
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB
	CALL	txserial
	GOTO	CMD_COMPLETE


CMD_WRONGARG				; 引数のチェックエラーを送信
	MOVLW	LED_RED			; 赤LED点滅
	CALL	getkey			; エラー解除キー入力待ち
	BSF	PCLATH,3
	CALL	err_wrongarguments
	CALL	txserial
	GOTO	CMD_RECEIVE


CMD_COMPLETE
	BCF	STATUS,RP0
	MOVLW	LED_ORANGE		; 処理がすぐ終わるコマンドだと緑の点滅が見えないため、橙を一瞬つける
	MOVWF	PORTB
	MOVLW	1
	CALL	lwait
	GOTO	CMD_RECEIVE


indexsearch				; インデックスサーチ
	BCF	FLAG,NO_INDEX		; フラグをクリアしておく
	MOVWF	TMP30			; Wレジスタに検索したいインデックスの属性を入れておく
	BCF	FLAG,SECTOR2		; SECTORに保存されているアドレスから検索をかける
INDEXSEARCH_LOOP
	CALL	sect2addr		; セクタの1バイト目だけを読み込む
	CALL	i2cread
	MOVF	I2CDATA,W
	SUBWF	TMP30,W			; 照合
	BTFSC	STATUS,Z		; インデックスが見つかったならそのままリターン
	RETURN				; SECTOR、I2CADRH、I2CADRLには見つかったセクタの番号が保存されて戻る
	INCF	SECTOR,F		; セクタ番号をインクリメント
	BTFSS	STATUS,Z		; 最後のセクタまで行ったらエラーでリターンする
	GOTO	INDEXSEARCH_LOOP
	BSF	FLAG,NO_INDEX		; セクタが見つからなかった
	RETURN


filesearch				; ファイルサーチルーチン
	BCF	FLAG,NO_FILE		; フラグをクリアしておく
	MOVWF	TMP20			; Wレジスタに対象ファイル名の保存されているバッファのポインタを入れておく
	CLRF	SECTOR			; セクタ0から検索
FILESEARCH_LOOP
	MOVLW	INDEX_START
	CALL	indexsearch		; スタートセクタを検索
	BTFSS	FLAG,NO_INDEX		; スタートセクタが見つからなかった場合
	GOTO	FILESEARCH_LOOP2
	BSF	FLAG,NO_FILE		; ファイルが見つからなかった
	RETURN
FILESEARCH_LOOP2				; スタートセクタが見つかった場合
	MOVLW	OFST_NAME		; ファイル名を読み出す
	ADDWF	I2CADRL,F
	MOVLW	ARGVSIZE		; 16バイト読み込み
	MOVWF	I2CSIZE
	CALL	i2cpread

	MOVF	TMP20,W			; 比較パターンのポインタをセット
	MOVWF	TMP30
	MOVLW	DATABUF			; ファイル名をセット
	MOVWF	TMP31
	CALL	bufcmp			; 比較
	BTFSS	FLAG2,DIFF		; 名前が同じならリターン
	RETURN				; SECTORには見つかったファイルのセクタ番号が保存されて戻る
	INCF	SECTOR,F		; セクタ番号をインクリメント
	BTFSS	STATUS,Z		; 最後のセクタまで行ったらエラーでリターンする
	GOTO	FILESEARCH_LOOP
	BSF	FLAG,NO_FILE		; 最後のセクタまで行ってもファイルが見つからなかった
	RETURN

;------------------------------------------------------------------------------
; 文字列処理ルーチン群
;------------------------------------------------------------------------------
bufclear				; バッファを指定した値でクリアする
	MOVF	TMP31,W			; TMP30にクリアする領域のサイズを入れる
	MOVWF	FSR			; TMP31にクリアする領域の先頭ポインタを入れる(ページ0,1固定)
BUFCLEAR_LOOP				; TMP32に埋める値を指定する
	MOVF	TMP32,W
	MOVWF	INDF			; 相対書き込みなので、IRP=0(ページ0,1)の領域に書き込める
	INCF	FSR,F
	DECFSZ	TMP30,F
	GOTO	BUFCLEAR_LOOP
	RETURN

bufcopy					; バッファの内容のコピー
	MOVLW	ARGVSIZE		; TMP30にコピー元のポインタを入れる
	MOVWF	TMP32			; TMP31にコピー先のポインタを入れる
BUFCOPY_LOOP				; コピー中の文字にヌルが来るかARGVSIZEになるまでコピーする
	MOVF	TMP30,W
	MOVWF	FSR
	MOVF	INDF,W			; 文字を読み出し
	MOVWF	TMP33
	SUBLW	NULL			; 文字がヌルだったかチェック
	BTFSC	STATUS,Z
	RETURN				; ヌルだったら無条件でリターン
	MOVF	TMP31,W
	MOVWF	FSR
	MOVF	TMP33,W
	MOVWF	INDF			; 相対書き込みなので、IRP=0(ページ0,1)の領域に書き込める
	INCF	TMP30,F			; ポインタをインクリメント
	INCF	TMP31,F
	DECFSZ	TMP32,F			; ARGVSIZE文字数分ループ
	GOTO	BUFCOPY_LOOP
	RETURN

bufcmp					; バッファの内容の比較
	MOVLW	ARGVSIZE		; TMP30に比較パターンのポインタを入れる
	MOVWF	TMP32			; TMP31に検査対象の文字列のポインタを入れる
	BCF	FLAG2,DIFF		; 比較パターンの文字にヌルが来るかARGVSIZEになるまで比較する
BUFCMP_LOOP
	MOVF	TMP30,W
	MOVWF	FSR
	MOVF	INDF,W			; 文字を読み出し
	MOVWF	TMP33
	MOVF	TMP31,W
	MOVWF	FSR
	MOVF	INDF,W
	SUBWF	TMP33,W
	BTFSC	STATUS,Z
	GOTO	BUFCMP_LOOP2
	BSF	FLAG2,DIFF		; 違っていたならば、フラグをセットしてリターン
	RETURN
BUFCMP_LOOP2
	MOVF	TMP33,W
	SUBLW	NULL			; 文字がヌルだったかチェック
	BTFSC	STATUS,Z		; ヌルだったらリターン
	RETURN				; パターン側のヌルを見ているので、1文字目にヌルが来ることは無い
	INCF	TMP30,F			; ポインタをインクリメント
	INCF	TMP31,F
	DECFSZ	TMP32,F			; ARGVSIZE文字数分ループ
	GOTO	BUFCMP_LOOP
	RETURN

to_lower				; ポインタで指定された文字列を小文字に変換する
	MOVF	INDF,W			; TMP00に変換する最大文字数、FSRに変換する文字列のポインタを代入
	SUBLW	'Z'			; 文字は'Z'以下か?
	BTFSS	STATUS,C
	GOTO	TO_LOWER2		; 'Z'以下なら大文字とみなして小文字に変換

	MOVF	INDF,W			; 文字はヌルか?
	SUBLW	NULL
	BTFSC	STATUS,Z
	RETURN				; ヌルなら変換終了

	MOVF	INDF,W
	ADDLW	'a'-'A'			; 引いた値に'a'を足すと小文字になる
	MOVWF	INDF
TO_LOWER2
	INCF	FSR,F			; 次の文字へ進む
	DECFSZ	TMP00,F			; 4文字処理する
	GOTO	to_lower

;------------------------------------------------------------------------------
; I2C EEPROMアクセスルーチン群
;   MC-8で使用したものに、チップセレクトとページアクセスのバイト数指定を追加
;------------------------------------------------------------------------------
i2cstart				; スタートコンディション送信
	MOVLW	LED_ORANGE		; オレンジLED点灯
	MOVWF	PORTB
	BSF	STATUS,RP0
	BSF	SSPCON2,SEN

i2csspif				; I2Cコマンド終了待ち
	BCF	STATUS,RP0
	BCF	PIR1,SSPIF		; SSPIFリセット
i2csspif1				; SSPIFポーリング
	BTFSS	PIR1,SSPIF
	GOTO	i2csspif1
	RETURN

i2crestart				; 再スタートコンディション送信
	BSF	STATUS,RP0
	BSF	SSPCON2,RSEN
	GOTO	i2csspif

i2cstop					; ストップコンディション送信
	CLRF	PORTB			; LED消灯
	BSF	STATUS,RP0
	BSF	SSPCON2,PEN
	GOTO	i2csspif

i2cack					; アクノリッジビット送信
	BSF	STATUS,RP0
	BSF	SSPCON2,ACKEN
	GOTO	i2csspif

i2caddr					; EEPROMアドレス送信
	CALL	i2cstart
	RLF	I2CCHIP,W		; EEPROMのチップ番号をロード
	ANDLW	B'00001110'		; 最下位のビットはR/Wフラグなのでシフトしてロードする
	IORLW	B'10100000'		; '1010'を頭につける
	MOVWF	SSPBUF
	CALL	i2csspif		; 送信待ち
	BSF	STATUS,RP0
	BTFSS	SSPCON2,ACKSTAT
	GOTO	I2CADDR1		; EEPROMが反応した
	CALL	i2cstop			; 反応しない(=書き込み中)は再送信
	GOTO	i2caddr			; EEPROMが存在しない場合は、ここで無限ループになる
I2CADDR1
	BCF	STATUS,RP0
	MOVF	I2CADRH,W		; 上位アドレス送信
	MOVWF	SSPBUF
	CALL	i2csspif		; アドレス書き込み時にACK検査をクリアしているので検査省略

	BCF	STATUS,RP0
	MOVF	I2CADRL,W		; 下位アドレス送信
	MOVWF	SSPBUF
	CALL	i2csspif

	BCF	STATUS,RP0
	RETURN

i2cread					; EEPROMからデータの読み出し
	CALL	i2caddr
	CALL	i2crestart		; データ方向切り替えのため再スタート
	RLF	I2CCHIP,W		; EEPROMのチップ番号をロード
	ANDLW	B'00001110'		; 最下位のビットはR/Wフラグなのでシフトしてロードする
	IORLW	B'10100001'		; '1010'を頭につける、Readフラグを末尾につける
	MOVWF	SSPBUF			; 読みこみモードへ突入
	CALL	i2csspif
	BSF	STATUS,RP0
	BSF	SSPCON2,RCEN		; 読みこみ開始
I2CREADPOLL
	BTFSS	SSPSTAT,BF		; 読み込み中?
	GOTO	I2CREADPOLL
	BCF	STATUS,RP0
	MOVF	SSPBUF,W		; データをI2CDATAへ入れる
	MOVWF	I2CDATA

	CALL	i2cstop
	RETURN

i2cwrite				; EEPROMにデータの書き込み
	CALL	i2caddr
	MOVF	I2CDATA,W
	MOVWF	SSPBUF
	CALL	i2csspif
	CALL	i2cstop
	RETURN

i2cpread				; EEPROM 複数バイトページ読み込み
	CALL	i2caddr
	CALL	i2crestart		; データ方向切り替えのため再スタート
	RLF	I2CCHIP,W		; EEPROMのチップ番号をロード
	ANDLW	B'00001110'		; 最下位のビットはR/Wフラグなのでシフトしてロードする
	IORLW	B'10100001'		; '1010'を頭につける、Readフラグを末尾につける
	MOVWF	SSPBUF			; 読みこみモードへ突入
	CALL	i2csspif

	MOVLW	DATABUF
	MOVWF	FSR
	MOVF	I2CSIZE,W		; 読み込みバイト数をロード
	MOVWF	TMP30
	BTFSC	STATUS,Z		; 例外処理、処理バイト数が0のときは256バイトになってしまうため、強制リターン
	GOTO	I2CPREADEND

I2CPREADLOOP
	BSF	STATUS,RP0
	BSF	SSPCON2,RCEN		; 読みこみ開始
I2CPREADPOLL
	BTFSS	SSPSTAT,BF		; 読み込み中?
	GOTO	I2CPREADPOLL
	BCF	STATUS,RP0
	MOVF	SSPBUF,W		; データをデータバッファへ間接入力
	MOVWF	INDF

	INCF	FSR,F
	DECF	TMP30,F
	BTFSC	STATUS,Z		; 指定回ループしたら(Z=0)
	GOTO	I2CPREADEND		; リターン
	CALL	i2cack
	GOTO	I2CPREADLOOP
I2CPREADEND
	CALL	i2cstop
	RETURN

i2cpwrite				; EEPROM 複数バイトページ書き込み
	CALL	i2caddr

	MOVLW	DATABUF
	MOVWF	FSR
	MOVF	I2CSIZE,W		; 書き込みバイト数をロード
	MOVWF	TMP30
	BTFSC	STATUS,Z		; 例外処理、処理バイト数が0のときは256バイトになってしまうため、強制リターン
	GOTO	I2CPWRITEEND
I2CPWRITELOOP
	MOVF	INDF,W
	MOVWF	SSPBUF
	CALL	i2csspif

	INCF	FSR,F
	DECFSZ	TMP30,F
	GOTO	I2CPWRITELOOP
I2CPWRITEEND
	CALL	i2cstop
	RETURN

sect2addr				; セクタ番号からメモリのアドレスを生成する
	CLRF	I2CADRL
	BTFSC	FLAG,SECTOR2		; 後半セクタが選択されているならばビットを立てる
	BSF	I2CADRL,6
	BCF	STATUS,C		; 最下位ビットをCフラグに送るため、フラグをリセットしておく
	RRF	SECTOR,W		; 上位バイト
	MOVWF	I2CADRH
	BTFSS	STATUS,C		; Cフラグが立っているなら
	RETURN
	BSF	I2CADRL,7		; 下位アドレスのビットを立てる
	RETURN

;------------------------------------------------------------------------------
; RS-232C送受信ルーチン群
;------------------------------------------------------------------------------
txserial				; データバッファの内容を送信バイト数だけ送信する
	MOVLW	DATABUF
	ADDWF	TXOFFSET,W		; ファイル送信のために備えてオフセットを加える
	MOVWF	FSR
	MOVF	TXSIZE,W		; 送信するバイト数をロード
	MOVWF	TMP30
	BTFSC	STATUS,Z		; 例外処理、送信バイト数が0のときは256バイト送信になってしまうため、強制リターン
	RETURN
TXSERIAL
	CALL	CS_WAIT			; 送信先の受信準備が整っているかをチェック
	MOVF	INDF,W			; バッファから読み出し
	MOVWF	TXREG			; データ送信
	CALL	TXBUSY			; 送信完了待ち
TXREPEAT				; 送信バイト数だけループ
	INCF	FSR,F
	DECFSZ	TMP30,F
	GOTO	TXSERIAL
	RETURN

TXBUSY					; シリアル送信待ちポーリング
	BSF	STATUS,RP0
	BTFSS	TXSTA,TRMT
	GOTO	TXBUSY
	BCF	STATUS,RP0
	RETURN

CS_WAIT					; CS端子が受信可を示すまでウエイト
	BTFSC	PORTC,CS_IN		; CS端子はアクティブロー
	GOTO	CS_WAIT
	RETURN

rxserial				; シリアルから1バイトを受信する
	BTFSC	PIR1,RCIF		; 既にバッファにデータがあるかチェック
	GOTO	RXLOAD
	BCF	PORTC,RS_OUT		; RS信号をONにして受信許可を出す
RXEMPTY					; MIDI受信バッファエンプティをポーリング
	BTFSS	PIR1,RCIF		; 空(=0)の間ループ
	GOTO	RXEMPTY
	BSF	PORTC,RS_OUT		; 受信が終わったらRS信号をOFFにする

	BTFSC	RCSTA,OERR		; オーバーランエラーチェック
	GOTO	uarterror
	BTFSC	RCSTA,FERR		; フレーミングエラーチェック
	GOTO	uarterror
RXLOAD					; もし送信側の反応が遅れてもFIFOは空なので1文字だけは受信できる
	MOVF	RCREG,W
	MOVWF	RXDATA
	RETURN

uarterror
	MOVF	PORTB,W			; 現在のLED点灯状態をセーブ
	MOVWF	TMP33
	MOVLW	0x80			; エラー中はLED交互点灯
	MOVWF	PORTB
	MOVLW	1
	CALL	lwait
	MOVLW	0x20
	MOVWF	PORTB
	MOVLW	1
	CALL	lwait
	MOVF	TMP33,W			; LEDの点灯状態を戻す
	MOVWF	PORTB

	MOVF	RCREG,W			; フレーミングエラーのリセット
	BTFSC	PIR1,RCIF		; UARTエラーが起きたときは、FIFOが空になるまでループ
	GOTO	uarterror

	BCF	RCSTA,CREN		; オーバーランエラーのリセット
	BSF	RCSTA,CREN

	GOTO	rxserial

;------------------------------------------------------------------------------
; ボタン入力ルーチン	入力待ちのLEDの点滅パターンはコール時にWに入れておく
;------------------------------------------------------------------------------
getkey
	MOVWF	TMP23			; パターン保存	TMP30〜32はlwaitで使用しているため使えない
	CALL	keyrelease		; キーのリリースを待つ
GETKEY
	MOVLW	5			; LED点灯中ループ
	MOVWF	TMP33
	MOVF	TMP23,W			; LEDを点灯させる
	MOVWF	PORTB
GETKEY1
	BTFSS	PORTC,SW_IN		; スイッチから入力する(プルアップ入力)
	GOTO	KEYTEST
	MOVLW	1			; LED用ウエイト
	CALL	lwait
	DECFSZ	TMP33,F
	GOTO	GETKEY1

	MOVLW	5			; LED消灯中ループ
	MOVWF	TMP33
	CLRF	PORTB			; LEDを消灯させる
GETKEY2
	BTFSS	PORTC,SW_IN		; スイッチから入力する(プルアップ入力)
	GOTO	KEYTEST
	MOVLW	1			; LED用ウエイト
	CALL	lwait
	DECFSZ	TMP33,F
	GOTO	GETKEY2
	GOTO	GETKEY

KEYTEST
	MOVLW	CHATTER			; チャタリング防止用ウエイト
	CALL	wait
	BTFSC	PORTC,SW_IN		; 再度入力する
	GOTO	GETKEY
	CLRF	PORTB			; LEDを消してリターンする
	RETURN

keyrelease				; キーのリリースを待つ
	BTFSS	PORTC,SW_IN		; スイッチが押されていないならば
	GOTO	keyrelease
	MOVLW	CHATTER			; チャタリング防止用ウエイトの後
	CALL	wait
	BTFSS	PORTC,SW_IN		; 再度確認
	GOTO	keyrelease
	RETURN				; それでも押されていないならばリターン

;------------------------------------------------------------------------------
; 内蔵EEPROMアクセスルーチン群
;------------------------------------------------------------------------------
eepread
	BCF	STATUS,RP1
	BCF	STATUS,RP0
	MOVF	EEPADDR,W		; アドレスはプログラム中のページ切り替えが面倒なので、別に用意しておく
	BSF	STATUS,RP1
	MOVWF	EEADR
	BSF	STATUS,RP0
	BCF	EECON1,EEPGD		; データEEPROMを選択
	BSF	EECON1,RD		; 読み出し
	BCF	STATUS,RP0
	MOVF	EEDATA,W
	BCF	STATUS,RP1
	MOVWF	EEPDATA
	RETURN

eepwrite
	BCF	STATUS,RP1
	BCF	STATUS,RP0
	MOVF	EEPADDR,W		; 書き込みアドレスのロード
	BSF	STATUS,RP1
	MOVWF	EEADR
	BCF	STATUS,RP1
	MOVF	EEPDATA,W		; 書き込みデータのロード
	BSF	STATUS,RP1
	MOVWF	EEDATA
	BSF	STATUS,RP0
	BCF	EECON1,EEPGD		; データEEPROMを選択
	BSF	EECON1,WREN
	MOVLW	0x55			; 書き込みパターン
	MOVWF	EECON2
	MOVLW	0xAA
	MOVWF	EECON2
	BSF	EECON1,WR		; 書き込み
EEPWRITEPOLL
	BTFSC	EECON1,WR		; 書き込みが終わるまでループ
	GOTO	EEPWRITEPOLL
	BCF	EECON1,WREN		; 書き込み保護
	BCF	STATUS,RP1
	BCF	STATUS,RP0
	RETURN

;------------------------------------------------------------------------------
; ウエイトルーチン群
;------------------------------------------------------------------------------
lwait					; 長時間ウエイト
	MOVWF	TMP32
lwait1
	MOVLW	255
	CALL	wait
	DECFSZ	TMP32,F
	GOTO	lwait1
	RETURN

wait					; ミリ秒ウエイト
	MOVWF	TMP30			; Wにループ回数をセット後CALL
wait1
	MOVLW	255
	MOVWF	TMP31
wait2
	NOP
	DECFSZ	TMP31,F
	GOTO	wait2
	DECFSZ	TMP30,F
	GOTO	wait1
	RETURN

;------------------------------------------------------------------------------
; ページ1プログラム領域
; ページ1のルーチンは、原則的にリターンする時にページ0にセットすること
;------------------------------------------------------------------------------
	ORG	0x0800
;------------------------------------------------------------------------------
; テキストセットルーチン Wレジスタにバッファのポインタを入れておく
;------------------------------------------------------------------------------
; コマンド名	文字の後にはヌルが付く
; cmdput	"put"		5
; cmdget	"get"		5
; cmddel	"del"		4
; cmdren	"ren"		4
; cmdover	"over"		5
; cmdsize	"size"		5
; cmdls		"ls"		3
; cmddf		"df"		3
; cmdcd		"cd"		3
; cmdmkfs	"mkfs"		5
; cmdset	"set"		4
; cmdnum	"num"		4
; cmdterm	"term"		5
; cmdstat	"stat"		5
; cmdhelp	"help"		5

cmdput					; "put"
	MOVWF	FSR
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	GOTO	NULL_RETURN

cmdget					; "get"
	MOVWF	FSR
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	GOTO	NULL_RETURN

cmddel					; "del"
	MOVWF	FSR
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	GOTO	NULL_RETURN

cmdren					; "ren"
	MOVWF	FSR
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	GOTO	NULL_RETURN

cmdover					; "over"
	MOVWF	FSR
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	GOTO	NULL_RETURN

cmdsize					; "size"
	MOVWF	FSR
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'z'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	NULL_RETURN

cmdls					; "ls"
	MOVWF	FSR
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	GOTO	NULL_RETURN

cmddf					; "df"
	MOVWF	FSR
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	GOTO	NULL_RETURN

cmdcd					; "cd"
	MOVWF	FSR
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	GOTO	NULL_RETURN

cmdmkfs					; "mkfs"
	MOVWF	FSR
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'k'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	GOTO	NULL_RETURN

cmdset					; "set"
	MOVWF	FSR
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	GOTO	NULL_RETURN

cmdnum					; "num"
	MOVWF	FSR
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	GOTO	NULL_RETURN

cmdterm					; "term"
	MOVWF	FSR
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	GOTO	NULL_RETURN

cmdstat					; "stat"
	MOVWF	FSR
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	GOTO	NULL_RETURN

cmdhelp					; "help"
	MOVWF	FSR
	MOVLW		'h'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	GOTO	NULL_RETURN

NULL_RETURN
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		NULL
	MOVWF	INDF
	BCF	PCLATH,3
	RETURN

;------------------------------------------------------------------------------
; 引数の固定文字	文字の後にはヌルが付く
; argset_1200	"1200"		5
; argset_2400	"2400"		5
; argset_4800	"4800"		5
; argset_9600	"9600"		5
; argset_19200	"19200"		6
; arg_off	"off"		4
; arg_on	"on"		3
; argterm_cr	"cr"		3
; argterm_lf	"lf"		3
; argterm_crlf	"crlf"		5

argset_1200				; "1200"
	MOVWF	FSR
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'2'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	GOTO	NULL_RETURN

argset_2400				; "2400"
	MOVWF	FSR
	MOVLW		'2'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'4'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	GOTO	NULL_RETURN

argset_4800				; "4800"
	MOVWF	FSR
	MOVLW		'4'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'8'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	GOTO	NULL_RETURN

argset_9600				; "9600"
	MOVWF	FSR
	MOVLW		'9'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'6'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	GOTO	NULL_RETURN

argset_19200				; "19200"
	MOVWF	FSR
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'9'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'2'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	GOTO	NULL_RETURN

arg_off					; "off"
	MOVWF	FSR
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	GOTO	NULL_RETURN

arg_on					; "on"
	MOVWF	FSR
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	GOTO	NULL_RETURN

argterm_cr				; "cr"
	MOVWF	FSR
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	GOTO	NULL_RETURN

argterm_lf				; "lf"
	MOVWF	FSR
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	GOTO	NULL_RETURN

argterm_crlf				; "crlf"
	MOVWF	FSR
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	GOTO	NULL_RETURN

;------------------------------------------------------------------------------
; メッセージ	文字の後にはCR、LF、EOFが付く
; err_cmdorargover	"CMD or ARG is too long."	23
; err_invalidcommand	"Invalid command."		16
; err_driveover		"Drive number is too big."	24
; err_wrongarguments	"Wrong arguments."		16
; err_filenotfound	"File not found."		15
; err_fileexist		"File already exist."		19
; err_diskfull		"Disk full."			10
; df_used		"(*)Used="			8
; df_free		" Free="			6
; msg_size		"Size="				5
; msg_bytes		"Bytes"				5
; help_put		"put filename"			14
; help_get		"get filename"			14
; help_del		"del filename"			14
; help_ren		"ren before after"		16
; help_over		"over filename"			13
; help_size		"byte count."			11
; help_ls		"list directory contents."	24
; help_df		"df [drive]"			10
; help_cd		"cd drive"			8
; help_mkfs		"build a new file system."	24
; help_set		"set speed memorys"		17
; help_num		"num LN"			6
; help_term		"term EOL EOF"			12
; help_stat		"display system settings."	24
; help_help		"help [command]"		14


err_cmdorargover			; "CMD or ARG is too long."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	23
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'C'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'M'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'D'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'A'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'R'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'G'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_invalidcommand			; "Invalid command."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	16
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'I'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_driveover				; "Drive number is too big."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	24
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'D'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'b'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'b'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_wrongarguments			; "Wrong arguments."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	16
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'W'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_filenotfound			; "File not found."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	15
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_fileexist				; "File already exist."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	19
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'x'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

err_diskfull				; "Disk full."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	10
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'D'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'k'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

df_used					; "(*)Used="
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	8
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	MOVLW		'('
	MOVWF	INDF
	INCF	FSR,F
	MOVF	I2CCHIP,W		; ドライブレターの計算
	ADDLW	'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		')'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'U'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	BCF	PCLATH,3
	RETURN

df_free					; " Free="
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	6
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	BCF	PCLATH,3
	RETURN

msg_size				; "Size="
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	5
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	MOVLW		'S'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'z'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	BCF	PCLATH,3
	RETURN

msg_bytes				; "Bytes"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	5
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	MOVLW		'B'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	GOTO	CR_LF_EOF_RETURN

help_put				; "put filename"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	12
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	CR_LF_EOF_RETURN

help_get				; "get filename"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	12
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	CR_LF_EOF_RETURN

help_del				; "del filename"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	12
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	CR_LF_EOF_RETURN

help_ren				; "ren before after"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	16
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'b'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	GOTO	CR_LF_EOF_RETURN

help_over				; "over filename"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	13
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	CR_LF_EOF_RETURN

help_size				; "byte count."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	11
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'b'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

help_ls					; "list directory contents."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	24
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

help_df					; "df [drive]"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	10
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'['
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		']'
	GOTO	CR_LF_EOF_RETURN

help_cd					; "cd drive"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	8
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	GOTO	CR_LF_EOF_RETURN

help_mkfs				; "build a new file system."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	24
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'b'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'w'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

help_set				; "set speed memorys"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	17
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	GOTO	CR_LF_EOF_RETURN

help_num				; "num LN"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	6
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'L'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'N'
	GOTO	CR_LF_EOF_RETURN

help_term				; "term EOL EOF"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	12
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'E'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'L'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'E'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'F'
	GOTO	CR_LF_EOF_RETURN

help_stat				; "display system settings."
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	24
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'y'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	GOTO	CR_LF_EOF_RETURN

help_help				; "help [command]"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	14
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'h'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'['
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		']'
	GOTO	CR_LF_EOF_RETURN

help_cmdlist				; "put get del ren over size ls df cd mkfs set num term stat help"
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	62
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'g'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'o'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'z'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'c'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'k'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'f'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'n'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'u'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'm'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		's'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'a'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		't'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'h'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'l'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	GOTO	CR_LF_EOF_RETURN


add_line_number				; 行番号フラグをチェックして、行番号をつける
	BTFSS	FLAG,LINE_NUMBER	; このルーチンは行番号が増加しないエラー等に使用する
	RETURN
	INCF	TXSIZE,F		; 行番号分文字数を増やす
	MOVLW	'1'			; 行番号は1のみ
	MOVWF	INDF
	INCF	FSR,F
	RETURN


CR_LF_EOF_RETURN
	MOVWF	INDF
	CLRF	TXOFFSET
	BTFSS	FLAG,EOL_CR		; 改行コードにCRを使わない時
	GOTO	LF_EOF_RETURN
	INCF	TXSIZE,F		; 文字数+1
	INCF	FSR,F
	MOVLW		CR
	MOVWF	INDF
LF_EOF_RETURN
	BTFSS	FLAG,EOL_LF		; 改行コードにLFを使わない時
	GOTO	EOF_RETURN
	INCF	TXSIZE,F		; 文字数+1
	INCF	FSR,F
	MOVLW		LF
	MOVWF	INDF
EOF_RETURN
	BCF	PCLATH,3
	BTFSS	FLAG,EOFCODE		; 行末にEOFを使わないとき
	RETURN
	INCF	TXSIZE,F		; 文字数+1
	INCF	FSR,F
	MOVLW		EOF
	MOVWF	INDF
	RETURN

CR_LF_SEND				; CR,LFを送信する
	CLRF	TXOFFSET
	CLRF	TXSIZE
	MOVLW	DATABUF
	MOVWF	FSR
	BTFSS	FLAG,EOL_CR		; 改行コードにCRを使わない時
	GOTO	LF_SEND
	INCF	TXSIZE,F		; 文字数+1
	MOVLW		CR
	MOVWF	INDF
LF_SEND
	BTFSS	FLAG,EOL_LF		; 改行コードにLFを使わない時
	GOTO	_SEND
	INCF	TXSIZE,F		; 文字数+1
	INCF	FSR,F
	MOVLW		LF
	MOVWF	INDF
_SEND
	BCF	PCLATH,3
	CALL	txserial
	RETURN

EOF_SEND				; EOFを送信する
	CLRF	TXOFFSET
	CLRF	TXSIZE
	BTFSS	FLAG,EOFCODE		; 行末にEOFを使わないとき
	GOTO	_SEND
	INCF	TXSIZE,F		; 文字数+1
	MOVLW		EOF
	BSF	STATUS,RP0
	MOVWF	DATABUF
	BCF	STATUS,RP0
	GOTO	_SEND

;------------------------------------------------------------------------------
; ステータスメッセージ生成
; Ver.*.** Speed=**** Drive=*/* LN=*** EOL=**/** EOF=***
msg_status
	MOVLW	DATABUF
	MOVWF	FSR
	MOVLW	54
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	CALL	add_line_number
	MOVLW		'V'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'.'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'S'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'p'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'd'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	INCF	FSR,F

	MOVLW	SPBRG_1200		; スピードの判定
	BSF	STATUS,RP0
	SUBWF	SPBRG,W
	BCF	STATUS,RP0
	BTFSS	STATUS,Z
	GOTO	msg_status24
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'2'
	GOTO	msg_status00
msg_status24
	MOVLW	SPBRG_2400
	BSF	STATUS,RP0
	SUBWF	SPBRG,W
	BCF	STATUS,RP0
	BTFSS	STATUS,Z
	GOTO	msg_status48
	MOVLW		'2'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'4'
	GOTO	msg_status00
msg_status48
	MOVLW	SPBRG_4800
	BSF	STATUS,RP0
	SUBWF	SPBRG,W
	BCF	STATUS,RP0
	BTFSS	STATUS,Z
	GOTO	msg_status96
	MOVLW		'4'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'8'
	GOTO	msg_status00
msg_status96
	MOVLW	SPBRG_9600
	BSF	STATUS,RP0
	SUBWF	SPBRG,W
	BCF	STATUS,RP0
	BTFSS	STATUS,Z
	GOTO	msg_status192
	MOVLW		'9'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'6'
	GOTO	msg_status00
msg_status192
	INCF	TXSIZE,F
	MOVLW		'1'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'9'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'2'
msg_status00
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'0'
	MOVWF	INDF

	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF

	INCF	FSR,F
	MOVLW		'D'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'r'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'i'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'v'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'e'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'1'		; ドライブの計算
	ADDWF	I2CCHIP,W
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'/'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'1'
	ADDWF	MAXDRIVE,W
	MOVWF	INDF
	INCF	FSR,F

	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F

	MOVLW		'L'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'N'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	BTFSC	FLAG,LINE_NUMBER	; 行番号の有無
	GOTO	msg_status_ln_on
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	MOVWF	INDF
	GOTO	msg_status_eol
msg_status_ln_on
	MOVLW		'N'
	MOVWF	INDF
	DECF	TXSIZE,F

msg_status_eol
	INCF	FSR,F
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'E'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'L'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF			; 改行コードの生成
	INCF	FSR,F
	BTFSS	FLAG,EOL_CR
	GOTO	msg_status_lf
	MOVLW		'C'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'R'
	MOVWF	INDF
	INCF	FSR,F
	BTFSS	FLAG,EOL
	GOTO	msg_status_space
	MOVLW		'/'
	MOVWF	INDF
	INCF	FSR,F
msg_status_lf
	MOVLW		'L'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	BTFSC	FLAG,EOL
	GOTO	msg_status_eof
msg_status_space
	DECF	TXSIZE,F
	DECF	TXSIZE,F
	DECF	TXSIZE,F

msg_status_eof
	MOVLW		' '
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'E'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'='
	MOVWF	INDF
	INCF	FSR,F
	MOVLW		'O'
	MOVWF	INDF
	INCF	FSR,F
	BTFSC	FLAG,EOFCODE		; EOFの有無
	GOTO	msg_status_eof_on
	MOVLW		'F'
	MOVWF	INDF
	INCF	FSR,F
	GOTO	CR_LF_EOF_RETURN
msg_status_eof_on
	MOVLW		'N'
	DECF	TXSIZE,F
	GOTO	CR_LF_EOF_RETURN


hex2text				; 16進→10進テキスト変換
	MOVLW	HEXBUF			; TMP20に上位 TMP21に下位を入れておく
	MOVWF	FSR
	CALL	HEX2TEXT		; 最下位変換
	CALL	HEX2TEXT
	CALL	HEX2TEXT
	CALL	HEX2TEXT
	CALL	HEX2TEXT		; 最上位変換
	MOVLW	5			; 文字数は5文字に固定
	MOVWF	TXSIZE
	CLRF	TXOFFSET
	BCF	PCLATH,3
	RETURN
HEX2TEXT				; ÷10サブルーチン(10で除算)
	MOVLW	16			; 16ビットくり返し
	MOVWF	TMP30
	CLRF	TMP31
HEX2TEXT1
	BCF	STATUS,C
	RLF	TMP21,1
	RLF	TMP20,1
	RLF	TMP31,1
	MOVLW	11110110B
	ADDWF	TMP31,W
	BTFSC	STATUS,C
	MOVWF	TMP31
	BTFSC	STATUS,C
	INCF	TMP21,F
	DECFSZ	TMP30,F
	GOTO	HEX2TEXT1
	DECF	FSR,F
	MOVF	TMP31,W
	MOVWF	INDF			; 余り
	MOVLW	'0'
	ADDWF	INDF,F

	RETURN

	END
