;************************************************************
;SC1602BSLB for PIC16F84A
;************************************************************

      LIST    P=PIC16F84A;
      INCLUDE  "P16f84A.inc"    ;標準ヘッダ定義ファイル
      __CONFIG  _HS_OSC & _PWRTE_ON & _WDT_OFF

      ;------------タイマーループ用固定変数----------------
GPR1    EQU    0Ch                ;GPRの1バイト目:0.4msを生成
GPR2    EQU    0Dh                ;GPRの2バイト目:100msを生成
GPR3    EQU    0Eh                ;GPRの3バイト目:500msを生成
      ;------------LCD用固定変数----------------------
LCDDT    EQU    0Fh                ;LCD表示データ格納
LCDINST   EQU    10h                ;LCDインストラクション格納

    ORG    0
MAIN
    BSF    STATUS,RP0        ;バンク1へ切替えて
    CLRF    TRISA            ;ポートAと
    CLRF    TRISB            ;ポートBを出力モードに設定して
    BCF    STATUS,RP0        ;バンク0に戻す

    ;----------LCD初期化----------
    CALL    Timer100        ;「電源ONから20ms待機」との事なので面倒だから100msにする。
    MOVLW   038H            ;ファンクションセット値:8bit長,文字フォント5*7,1/8デューティ?
    MOVWF   PORTB            ;でLCDのデータピンをセットする。
    BCF    PORTA,1            ;RA1=R/W選択信号(5PIN)を0=Wモードにする。
    BCF    PORTA,2            ;RA2=レジスタ選択信号(4PIN)を0=コマンドにする。
    BSF    PORTA,0            ;RA0=動作起動信号(6PIN)を1=ストローブにする。
    CALL    Timer100        ;「ストローブのパルス幅を220ns以上確保する」との事なので面倒だから100msにする。
    BCF    PORTA,0            ;ストローブをイネーブル(ストローブ終了)にする。
    CALL    Timer100        ;上記実行から4.1msec以上待機との事なので面倒だから100msにする。

    MOVLW    01h            ;表示クリア
    CALL    LCDIni2
    MOVLW    06h            ;エントリーモード
    CALL    LCDIni2
    MOVLW    0Ch            ;表示ON
    CALL    LCDIni2

    ;--------------初期化終了。ここから文字表示へ---------------------

HYOUJI
    MOVLW    01h            ;表示クリア
    CALL    LCDIni2

    CALL    Timer500

    MOVLW    02h            ;1行目へ
    CALL    LCDIni2
    CALL    MOJI1

    MOVLW    0C0h            ;2行目へ
    CALL    LCDIni2
    CALL    MOJI2

    CALL    Timer500

;    MOVLW    18h
;    CALL    LCDIni2
;    CALL    MOJI1

    GOTO    HYOUJI

;----------------文字データ-----------------------
MOJI1
    MOVLW    43h                ;C
    CALL    LCDWR
    MOVLW    42h                ;B
    CALL    LCDWR
    MOVLW    0B2h                ;イ
    CALL    LCDWR
    MOVLW    0C1h                ;チ
    CALL    LCDWR
    MOVLW    0BBh                ;サ
    CALL    LCDWR
    MOVLW    0DDh                ;ン
    CALL    LCDWR
    MOVLW    43h                ;C
    CALL    LCDWR
    MOVLW    4Ch                ;L
    CALL    LCDWR
    MOVLW    55h                ;U
    CALL    LCDWR
    MOVLW    42h                ;B
    CALL    LCDWR
    RETURN
MOJI2
    MOVLW    31h                ;1
    CALL    LCDWR
    MOVLW    33h                ;3
    CALL    LCDWR
    MOVLW    30h                ;0
    CALL    LCDWR
    MOVLW    30h                ;0
    CALL    LCDWR
    MOVLW    53h                ;S
    CALL    LCDWR
    MOVLW    46h                ;F
    CALL    LCDWR
    RETURN

;タイマー管理ルーチン
    ;----------100ms*5=0.5sを作る------------
Timer500
    MOVLW    05h             ;W=5
    MOVWF    GPR3            ;Wの内容をデータ領域2バイト目に書き込む
TimeLoop3
    NOP
    CALL    Timer100
    DECFSZ    GPR3,1
    GOTO    TimeLoop3
    RETURN

    ;----------0.4ms*256=100msを作る------------
Timer100
    MOVLW    0F9h             ;W=249
    MOVWF    GPR2            ;Wの内容をデータ領域2バイト目に書き込む
TimeLoop2
    NOP                ;何もしない
    CALL    Timer1            ;999サイクルを249回呼ぶ
    DECFSZ    GPR2,1            ;W=W-1
    GOTO    TimeLoop2
    RETURN                ;もしW=0になら戻る

    ;----------0.4um*999サイクル=0.4msを作る------------
Timer1
    MOVLW    0F9h             ;W=249
    MOVWF    GPR1            ;Wの内容をデータ領域1バイト目に書き込む
TimeLoop1
    NOP                ;何もしない
    DECFSZ    GPR1,1            ;W=W-1
    GOTO    TimeLoop1
    RETURN                ;もしW=0になら戻る

    ;----------------LCD初期化--------------------------------------
LCDIni2
    MOVWF    PORTB            ;ワークWの内容をポートBへ
    BCF    PORTA,1            ;RA1を0=Wモードにする。
    BCF    PORTA,2            ;RA2を0=コマンドにする。
    BSF    PORTA,0            ;RA0を1=ストローブにする。
;    CALL    Timer100
    BCF    PORTA,0            ;RA0を0=イネーブルにする。
    CALL    LCDIni3
    RETURN

    ;----------LCD BUSYチェック------------    
LCDIni3
    BSF    STATUS,RP0        ;バンク1へ
    MOVLW    0FFh
    MOVWF    TRISB            ;ポートBを入力モードへ
    BCF    STATUS,RP0        ;バンク0へ

    BCF    PORTA,2            ;RA2を0=コマンドにする。
    BSF    PORTA,1            ;RA1を1=Rモードにする。
    BSF    PORTA,0            ;RA0を1=ストローブにする。
;    CALL    Timer100        ;ストローブ・ウェイト兼1文字表示間隔調整
    BCF    PORTA,0            ;RA0を0=イネーブルにする。
    MOVF    PORTB,W            ;ポートBの内容をワークWへ
    MOVWF    LCDINST            ;ワークWの内容を0Fhへ
    BTFSC    LCDINST,7        ;RB7=DB7=0ならループを抜ける
    GOTO    LCDIni3

    BCF    PORTA,1            ;RA1を0=Wモードにする。
    BSF    STATUS,RP0        ;バンク1へ切替えて
    CLRF    TRISB            ;ポートBを出力モードに設定する。
    BCF    STATUS,RP0        ;バンク0に戻す
    RETURN

    ;---------------データ書き込み---------------------------
LCDWR
    MOVWF    PORTB
    BCF    PORTA,1        ;R/WをW
    BSF    PORTA,2        ;RSをデータに
    BSF    PORTA,0        ;書き込みストローブ。
    BCF    PORTA,0        ;ストローブ終了。
    CALL    LCDIni3
    RETURN

;---------------------------------------
    END