LCDキャラクターディスプレイ / 4ビットモード / 1ポートだけ使う

pp.399-401
4ビットモードなら結局全部で6本つなげばいいだけなので1ポートでまかなえる。上位ニブルにデータを、下位ニブルに制御信号を割り振ることにする。制御信号(RS、EN)をいじるときはデータ(D7:4)には触らず、and vice versa
f:id:ti-nspire:20200612060949p:plain:h300 f:id:ti-nspire:20200612061027j:plain:h300

.EQU RS = PD0
.EQU EN = PD2

; スタックポインタの初期化マクロ
.MACRO INITSTACK
    LDI R16, HIGH(RAMEND)
    OUT SPH, R16
    LDI R16, LOW(RAMEND)
    OUT SPL, R16
.ENDMACRO

INITSTACK

; PD7:4をLCDのD7:4に接続して命令とデータとを書き込むことにする。
; PD0からRS信号を、PD2からEN信号を出すことにする。
LDI R16, 0xF0 | (1 << RS) | (1 << EN)
OUT DDRD, R16

LDI R16, 0b00110011
CALL COMMAND_W
CALL DELAY_2ms

LDI R16, 0b00110010
CALL COMMAND_W
CALL DELAY_2ms

LDI R16, 0b00101000
CALL COMMAND_W
CALL DELAY_2ms

LDI R16, 0b1111
CALL COMMAND_W

LDI R16, 0b0001
CALL COMMAND_W
CALL DELAY_2ms

LDI R16, 0b0110
CALL COMMAND_W

LDI R16, 0xA2 ;「
CALL DATA_W
LDI R16, 'ハ'
CALL DATA_W
LDI R16, 'ロ'
CALL DATA_W
LDI R16, 'ー'
CALL DATA_W
LDI R16, '、'
CALL DATA_W
LDI R16, 'ワ'
CALL DATA_W
LDI R16, 'ー'
CALL DATA_W
LDI R16, 'ル'
CALL DATA_W
LDI R16, 'ト'
CALL DATA_W
LDI R16, '゙'
CALL DATA_W
LDI R16, 0xA3 ; 」
CALL DATA_W

LDI R16, (1 << 7) | 0xC0 ; 2行目1文字目に移動して、
CALL COMMAND_W
LDI R16, '"'
CALL DATA_W
LDI R16, 'コ'
CALL DATA_W
LDI R16, '゙'
CALL DATA_W
LDI R16, 'チ'
CALL DATA_W
LDI R16, 'ヒ'
CALL DATA_W
LDI R16, '゚'
CALL DATA_W
LDI R16, 'タ'
CALL DATA_W
LDI R16, 'リ'
CALL DATA_W
LDI R16, '1'
CALL DATA_W
LDI R16, '0'
CALL DATA_W
LDI R16, '0'
CALL DATA_W
LDI R16, 0xFB ; 万
CALL DATA_W
LDI R16, 0xFC ; 円
CALL DATA_W
LDI R16, '"'
CALL DATA_W


MAIN:
    RJMP MAIN

; 上位ニブルを書き込むためのサブルーチン
HI_NIBBLE_W:
    ANDI R27, 0xF0
    IN R26, PORTD    ; ポートDの下位ニブル(制御線)に触りたくないので一旦全部取り込んで、
    ANDI R26, 0x0F
    OR R26, R27      ; 下位ニブルは変えないまま、
    OUT PORTD, R26   ; またポートDに書き込んで、
    SBI PORTD, EN
    CALL SHORT_DELAY
    CBI PORTD, EN    ; そのままLCDへ書き込む。
    CALL DELAY_100us
    RET

; 1バイトを書き込むためのサブルーチン
BYTE_W:
    MOV R27, R16
    CALL HI_NIBBLE_W
    MOV R27, R16
    SWAP R27
    CALL HI_NIBBLE_W
    RET

; 命令を書き込むためのサブルーチン
COMMAND_W:
    CBI PORTD, RS
    CALL BYTE_W
    RET

; データを書き込むためのサブルーチン
DATA_W:
    SBI PORTD, RS
    CALL BYTE_W
    RET

SHORT_DELAY:
    RET ; 4

DELAY_100us:
    PUSH R17          ; 2
    LDI R17 , 200     ; 1
DR0:
    RCALL SHORT_DELAY ; 3
    DEC R17           ; 1W
    BRNE DR0          ; falseで1, trueで2
    POP R17           ; 2
    RET               ; 4

DELAY_2ms:
    PUSH R17          ; 2 
    LDI R17, 20       ; 1
LDR0:
    RCALL DELAY_100us ; 3
    DEC R17           ; 1
    BRNE LDR0         ; falseで1, trueで2
    POP R17           ; 2
    RET               ; 4