Two messages display with delay for 4 bit LCD


; latest 6502 board
;
PORTB = $6000     ; 8 bits PB0-PB7
PORTA = $6001     ; 8 bits PA0-PA7
DDRB = $6002      ; data direction B bits
DDRA = $6003      ; data direction A bits
E =  %00001000    ; PB3 connected
RW = %00000100    ; PB2 connected
RS = %00000010    ; PB1 connected

keep = $0200      ; store A

        .org $8000

reset:
        ldx #$ff
        txs             ; init stack pointer

        lda #$0
        sta keep        ; keep = 0

        lda #%11111110  ; 7 outputs PB1 -PB7, PB0 free
        sta DDRB

        lda #%00000001  ; 7 pins input, 1 output (PA0 led)
        sta DDRA
        lda #%00000001
        sta PORTA       ; turn off led (sink)

        jsr short_delay ;  necessary?

        lda #%00000010  ; 4-bit mode
        jsr lcd_instruction
        lda #%00101000   ; 4-bit mode, 2-lines, 5x8 font
        jsr lcd_instruction
        lda #%00001110   ; display on, blink on, cursor off
        jsr lcd_instruction
        lda #%00000110   ; increment and shift cursor, no shift display
        jsr lcd_instruction
        lda #%00000001   ; clear screen
        jsr lcd_instruction
        lda #%10000000   ; cursor (0,0) line 1, pos 1
        jsr lcd_instruction
        jsr short_delay

print_msg1:
        lda #%10000000   ; cursor (0,0) line 1, pos 1
        jsr lcd_instruction
        jsr blink_led
        ldx #0
loop_msg1:
        lda msg1,x
        beq print_msg2  ; if msg1,x == zero
        jsr print_char
        inx
        jmp loop_msg1

print_msg2:
        jsr delay        ; here is a delay
        lda #%10000000   ; home
        jsr lcd_instruction
        jsr blink_led
        ldx #0
loop_msg2:
        lda msg2,x
        beq loop        ; if msg2,x == zero
        jsr print_char
        inx
        jmp loop_msg2


loop:
        jsr delay
        jmp print_msg1

msg1: .asciiz "Hello, Everybody"
msg2: .asciiz "Goodbye to you  "

short_delay:
        ldx  #$ff   ; (2 cycles)
        ldy  #$2f   ; (2 cycles)
short_loop:
        dex          ; (2 cycles)
        bne  short_loop   ; (3 cycles in loop, 2 cycles at end)
        dey
        bne  short_loop
        rts

delay:              ;  delay for 1MHz
        ldx  #$ff   ; (2 cycles)
        ldy  #$ff   ; (2 cycles)
        lda  #$0a   ; #$02 much faster
delay_loop:
        nop
        dex          ; (2 cycles)
        bne  delay_loop   ; (3 cycles in loop, 2 cycles at end)
        nop
        dey
        bne  delay_loop
        nop
        sbc #1
        bne  delay_loop
        rts

lcd_instruction:        ; 1. remove low nibble ; 2. move lnibble to high bit
        sta keep        ; save A in keep
        and #$F0        ; lda & 1111 0000
        sta PORTB
                        ; Clear RS/RW/E bits no necessary
                        ; Set E bit to send instruction
        ora #E          ; lda or E  xxxx 0000 or 0000 1000
        sta PORTB
                        ; Clear RS/RW/E bits
        and #$F0        ; lda & 1111 0000
        sta PORTB

        lda keep        ; load lda from memory
        asl             ; shift left 4x    0000 xxxx -> xxxx 0000
        asl
        asl
        asl
        sta PORTB
                        ; Set E bit to send instruction
        ora #E          ; lda or E xxxx 0000 or 0000 1000
        sta PORTB
                        ; Clear RS/RW/E bits
        and #$F0        ; lda & 1111 0000
        sta PORTB
        rts

print_char:
        sta keep        ; save A in keep
        and #$F0        ; lda & 1111 0000
        sta PORTB
                        ; clear E, set RS
        and #$f0        ; lda & 1111 0000
        ora #RS         ; lda or 0000 0010
        sta PORTB
                        ; set E, set RS
        ora #E          ; lda or 0000 1000
        ora #RS         ; lda or 0000 0010
        sta PORTB
                        ; clear E, set RS
        and #$f0        ; lda & 1111 0000
        ora #RS         ; lda or 0000 0010
        sta PORTB

        lda keep        ; load A from memory
        asl             ; shift left 4x
        asl
        asl
        asl
        sta PORTB
                        ; clear E, set RS
        and #$f0        ; lda & 1111 0000
        ora #RS         ; lda or 0000 0010
        sta PORTB
                        ; set E, set RS
        ora #E          ; lda or 0000 1000
        ora #RS         ; lda or 0000 0010
        sta PORTB
                        ; clear E, set RS
        and #$f0        ; lda & 1111 0000
        ora #RS         ; lda or 0000 0010
        sta PORTB
        rts

blink_led:

        lda PORTA
        and #%00000001  ; xxxx xxx0  & 0000 0001
        beq blink_on    ; if zero flag set
        lda #%00000000
        sta PORTA
        rts
blink_on:
        lda #%00000001
        sta PORTA
        rts


        .org $fffc
        .word reset
        .word $0000