231 lines
6.2 KiB
Plaintext
231 lines
6.2 KiB
Plaintext
;********************************************************************************
|
|
; @module LCD-W164B
|
|
; @type driver
|
|
; @device ELECTRONIC ASSEMBLY - W164B-NLW
|
|
; @details
|
|
; The LCD must be connected to a W65C22N Interface Chip:
|
|
; - IO.RB0-7 -> LCD.D0-7 data lines
|
|
; - IO.RA5 -> LCD.RS register select
|
|
; - IO.RA6 -> LCD.R/W read/write
|
|
; - IO.RA7 -> LCD.E enable
|
|
;
|
|
; @requires LCD_IO: Base Address of IO Chip
|
|
; @optparam LCD_MEM: Memory address for a runtime variable. Default = $300
|
|
; @depends IO-W65C22N
|
|
;********************************************************************************
|
|
|
|
.ifndef LCD_IO
|
|
.fatal "LCD_IO is not defined: set it to the base address of the IO chip of the LCD"
|
|
.endif
|
|
|
|
.ifndef INCLUDE_IOW65C22
|
|
.error "IO-W65C22 module is not included"
|
|
.endif
|
|
|
|
.include "utility.h65"
|
|
|
|
|
|
; RAM VARIABLES
|
|
.ifndef LCD_MEM
|
|
LCD_MEM = $300
|
|
.endif
|
|
LCD_CHARCOUNT = LCD_MEM
|
|
|
|
; PIN MASKS
|
|
LCD_E = %10000000
|
|
LCD_RW = %01000000
|
|
LCD_RS = %00100000
|
|
; .local LCD_E,LCD_RW,LCD_RS
|
|
|
|
; LCD Instructions (see datasheet for more)
|
|
LCD_CMD_CLEAR = %00000001 ; clear display
|
|
LCD_CMD_ENTRY_MODE = %00000110 ; auto-shift cursor
|
|
LCD_CMD_DISPLAY_ON = %00001111 ; everything on, with blinking cursor
|
|
LCD_CMD_FUNCTION_SET = %00111000 ; 8-bit, 4 lines, 5x7 font
|
|
LCD_CMD_SET_ADDRESS = %10000000 ; or with the address
|
|
; LCD Constants
|
|
LCD_LINE1 = $00
|
|
LCD_LINE2 = $40
|
|
LCD_LINE3 = $10
|
|
LCD_LINE4 = $50
|
|
|
|
LCD_CLEAR = %00000000
|
|
|
|
|
|
;********************************************************************************
|
|
; @function Initialize the lcd module
|
|
; @details call before doing anything else
|
|
;********************************************************************************
|
|
.proc lcd_init
|
|
; init IO
|
|
lda #$ff ; RB 0-7 output
|
|
sta LCD_IO+IO::DDRB
|
|
|
|
; UT_update_with_mask LCD_IO + IO::DDRA, (LCD_RS | LCD_RW | LCD_E), (LCD_RS | LCD_RW | LCD_E)
|
|
lda #(LCD_RS | LCD_RW | LCD_E) ; RA 5-7 output
|
|
sta LCD_IO+IO::DDRA
|
|
|
|
; init lcd
|
|
lda #LCD_CMD_FUNCTION_SET
|
|
jsr _lcd_cmd
|
|
lda #LCD_CMD_DISPLAY_ON
|
|
jsr _lcd_cmd
|
|
lda #LCD_CMD_CLEAR
|
|
jsr _lcd_cmd
|
|
lda #LCD_CMD_ENTRY_MODE
|
|
jsr _lcd_cmd
|
|
|
|
stz LCD_CHARCOUNT
|
|
rts
|
|
.endproc
|
|
|
|
;********************************************************************************
|
|
; PRINTING TO LCD
|
|
;********************************************************************************
|
|
|
|
;********************************************************************************
|
|
; @function Clear the display
|
|
; @see lcd_print
|
|
;********************************************************************************
|
|
.proc lcd_clear
|
|
stz LCD_CHARCOUNT
|
|
lda #LCD_CLEAR
|
|
jsr _lcd_cmd
|
|
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE1)
|
|
jsr _lcd_cmd
|
|
rts
|
|
.endproc
|
|
|
|
;********************************************************************************
|
|
; @function Print a null-terminated string
|
|
; @param ARG0-1 Address of the string to print
|
|
;********************************************************************************
|
|
.proc lcd_print
|
|
ldy #$00
|
|
@lcd_print_loop:
|
|
lda (ARG0),y
|
|
beq @lcd_print_end
|
|
jsr lcd_char
|
|
iny
|
|
bra @lcd_print_loop
|
|
@lcd_print_end:
|
|
rts
|
|
.endproc
|
|
|
|
;********************************************************************************
|
|
; @macro Print a null-terminated string
|
|
; @param message: Address of the message
|
|
;********************************************************************************
|
|
.macro Print message
|
|
jsr lcd_clear
|
|
lda #.LOBYTE(message)
|
|
sta ARG0
|
|
lda #.HIBYTE(message)
|
|
sta ARG1
|
|
jsr lcd_print
|
|
.endmacro
|
|
|
|
;********************************************************************************
|
|
; @macro Print a single character
|
|
; @param A: Character to print
|
|
;********************************************************************************
|
|
.proc lcd_char
|
|
pha
|
|
pha
|
|
; TODO use UT_update_with_mask?
|
|
jsr _lcd_wait_nbusy
|
|
pla
|
|
sta LCD_IO + IO::RB
|
|
lda #LCD_RS
|
|
sta LCD_IO + IO::RA
|
|
lda #(LCD_RS | LCD_E)
|
|
sta LCD_IO + IO::RA
|
|
lda #LCD_RS
|
|
sta LCD_IO + IO::RA
|
|
inc LCD_CHARCOUNT
|
|
jsr _lcd_set_address
|
|
pla ; put char back in a
|
|
.endproc
|
|
|
|
|
|
;********************************************************************************
|
|
; Internal LCD Commands
|
|
;********************************************************************************
|
|
; read busy flag
|
|
.proc _lcd_wait_nbusy
|
|
stz LCD_IO + IO::DDRB ; set IO1-LCD_IO + IO::RB to input
|
|
@lcd_wait_nbusy_loop: ; read the busy flag
|
|
lda #LCD_RW
|
|
sta LCD_IO + IO::RA
|
|
lda #(LCD_RW | LCD_E)
|
|
sta LCD_IO + IO::RA
|
|
|
|
lda LCD_IO + IO::RB
|
|
and #%10000000 ; and updates zero flag, if not set retry
|
|
bne @lcd_wait_nbusy_loop
|
|
|
|
lda #%00000000 ; TODO dont overwrite 0-4
|
|
sta LCD_IO + IO::RA
|
|
lda #%11111111 ; set IO1-LCD_IO + IO::RB to output
|
|
sta LCD_IO + IO::DDRB
|
|
rts
|
|
.endproc
|
|
|
|
.proc _lcd_cmd ; send cmd in acc
|
|
pha
|
|
jsr _lcd_wait_nbusy
|
|
pla
|
|
|
|
; TODO use UT_update_with_mask?
|
|
sta LCD_IO + IO::RB
|
|
lda #LCD_CLEAR
|
|
sta LCD_IO + IO::RA
|
|
lda #LCD_E
|
|
sta LCD_IO + IO::RA
|
|
lda #LCD_CLEAR
|
|
sta LCD_IO + IO::RA
|
|
rts
|
|
.endproc
|
|
|
|
|
|
;********************************************************************************
|
|
; Set the LCD DD-RAM Address so that text linebreaks after 16 chars
|
|
;********************************************************************************
|
|
.proc _lcd_set_address
|
|
; check if checks are necessary
|
|
lda LCD_CHARCOUNT
|
|
beq @lcd_line1
|
|
and #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
|
|
bne @lcd_set_address_done
|
|
; checks necessary
|
|
lda LCD_CHARCOUNT
|
|
beq @lcd_line1
|
|
cmp #$10
|
|
beq @lcd_line2
|
|
cmp #$20
|
|
beq @lcd_line3
|
|
cmp #$30
|
|
beq @lcd_line4
|
|
cmp #$40 ; set to line1 when full ; set to line1 when full
|
|
beq @lcd_line1
|
|
@lcd_set_address_done:
|
|
rts
|
|
@lcd_line1:
|
|
stz LCD_CHARCOUNT
|
|
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE1)
|
|
jsr _lcd_cmd
|
|
rts
|
|
@lcd_line2:
|
|
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE2)
|
|
jsr _lcd_cmd
|
|
rts
|
|
@lcd_line3:
|
|
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE3)
|
|
jsr _lcd_cmd
|
|
rts
|
|
@lcd_line4:
|
|
lda #(LCD_CMD_SET_ADDRESS | LCD_LINE4)
|
|
jsr _lcd_cmd
|
|
rts
|
|
.endproc
|