6502-OS/system/lcd.s65

234 lines
5.9 KiB
Plaintext
Raw Normal View History

2023-12-08 22:56:35 +01:00
.include "system/lcd.h65"
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
.ifndef lcd::LCD_IO
.fatal "lcd::LCD_IO is not defined: set it to the base address of the IO chip of the LCD"
.endif
Export lcd,init,clear,print,print_char,set_position
2023-10-26 19:51:20 +02:00
; RAM VARIABLES
2023-12-08 22:56:35 +01:00
.bss
charcount: .res 1
.code
;;********************************************************************************
;; @function Initialize the lcd module
;; @details call before doing anything else
;; @modifies A
;;********************************************************************************
.proc init
2023-10-26 19:51:20 +02:00
; init IO
lda #$ff ; RB 0-7 output
2023-12-08 22:56:35 +01:00
sta lcd::LCD_IO+IO::DDRB
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
; UT_update_with_mask IO + IO::DDRA, (RS | LCD_RW | LCD_E), (LCD_RS | LCD_RW | LCD_E)
lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output
sta lcd::LCD_IO+IO::DDRA
2023-10-26 19:51:20 +02:00
; init lcd
2023-12-08 22:56:35 +01:00
lda #lcd::CMD_FUNCTION_SET
jsr _cmd
lda #lcd::CMD_DISPLAY_ON
jsr _cmd
lda #lcd::CMD_CLEAR
jsr _cmd
lda #lcd::CMD_ENTRY_MODE
jsr _cmd
stz charcount
2023-10-26 19:51:20 +02:00
rts
.endproc
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; PRINTING TO LCD
;;********************************************************************************
;;********************************************************************************
;; @function Clear the display
;; @see lcd_print
;; @modifies A
;;********************************************************************************
.proc clear
stz charcount
lda #lcd::CLEAR
jsr _cmd
lda #(lcd::CMD_SET_ADDRESS | lcd::LINE1)
jsr _cmd
2023-10-28 03:48:27 +02:00
rts
.endproc
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; @function Print a null-terminated string
;; @param ARG0-1 Address of the string to print
;; @modifies: A,Y
;;********************************************************************************
.proc print
2023-10-28 03:48:27 +02:00
ldy #$00
@lcd_print_loop:
2023-10-30 22:14:08 +01:00
lda (ARG0),y
2023-10-28 03:48:27 +02:00
beq @lcd_print_end
2023-12-08 22:56:35 +01:00
jsr print_char
2023-10-28 03:48:27 +02:00
iny
bra @lcd_print_loop
@lcd_print_end:
2023-10-26 19:51:20 +02:00
rts
2023-10-28 03:48:27 +02:00
.endproc
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; @macro Print a single character
;; @param A: Character to print
;;********************************************************************************
.proc print_char
2023-11-01 13:13:23 +01:00
pha
pha
; TODO use UT_update_with_mask?
2023-12-08 22:56:35 +01:00
jsr _wait_nbusy
2023-11-01 13:13:23 +01:00
pla
2023-12-08 22:56:35 +01:00
sta lcd::LCD_IO + IO::RB
lda #lcd::RS
sta lcd::LCD_IO + IO::RA
lda #(lcd::RS | lcd::E)
sta lcd::LCD_IO + IO::RA
lda #lcd::RS
sta lcd::LCD_IO + IO::RA
inc charcount
jsr _break_line
2023-11-01 13:13:23 +01:00
pla ; put char back in a
.endproc
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; Internal LCD Commands
;;********************************************************************************
2023-10-26 19:51:20 +02:00
; read busy flag
2023-12-08 22:56:35 +01:00
.proc _wait_nbusy
stz lcd::LCD_IO + IO::DDRB ; set IO1-IO + IO::RB to input
2023-10-26 19:51:20 +02:00
@lcd_wait_nbusy_loop: ; read the busy flag
2023-12-08 22:56:35 +01:00
lda #lcd::RW
sta lcd::LCD_IO + IO::RA
lda #(lcd::RW | lcd::E)
sta lcd::LCD_IO + IO::RA
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
lda lcd::LCD_IO + IO::RB
2023-10-26 19:51:20 +02:00
and #%10000000 ; and updates zero flag, if not set retry
bne @lcd_wait_nbusy_loop
lda #%00000000 ; TODO dont overwrite 0-4
2023-12-08 22:56:35 +01:00
sta lcd::LCD_IO + IO::RA
lda #%11111111 ; set IO1-IO + IO::RB to output
sta lcd::LCD_IO + IO::DDRB
2023-10-26 19:51:20 +02:00
rts
2023-11-01 13:13:23 +01:00
.endproc
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; @function Send a command to the lcd
;; @param A: command
;; @modifies A
;;********************************************************************************
.proc _cmd ; send cmd in acc
2023-10-26 19:51:20 +02:00
pha
2023-12-08 22:56:35 +01:00
jsr _wait_nbusy
2023-10-26 19:51:20 +02:00
pla
; TODO use UT_update_with_mask?
2023-12-08 22:56:35 +01:00
sta lcd::LCD_IO + IO::RB
lda #lcd::CLEAR
sta lcd::LCD_IO + IO::RA
lda #lcd::E
sta lcd::LCD_IO + IO::RA
lda #lcd::CLEAR
sta lcd::LCD_IO + IO::RA
2023-10-26 19:51:20 +02:00
rts
2023-10-28 03:48:27 +02:00
.endproc
2023-10-26 19:51:20 +02:00
2023-12-08 22:56:35 +01:00
;;********************************************************************************
;; @function Set the cursor to a position
;; @param A: cursor position: `(lcd::LINEX + offset)`, where offset € [$0, $f]
;; @details:
;; If the position is too large, it will be set to char 5 in line 2
;; @returns A: the cursor position
;;********************************************************************************
.proc set_position
2023-12-09 23:33:15 +01:00
pha
cmp #$60
bge @invalid
cmp #$50
bge @line4
2023-12-08 22:56:35 +01:00
cmp #$40
2023-12-09 23:33:15 +01:00
bge @line2
cmp #$20
2023-12-08 22:56:35 +01:00
bge @invalid
2023-12-09 23:33:15 +01:00
cmp #$10
bge @line3
bra @set
; @line1: ; starts at $00, charcount at $00
@line2: ; starts at $40, charcount at $10
sbc #$30 ; carry is already set
bra @set
@line3: ; starts at $10, charcount at $20
add #$10
bra @set
@line4: ; starts at $50, charcount at $30
sbc #$20
@set:
2023-12-08 22:56:35 +01:00
sta charcount
2023-12-09 23:33:15 +01:00
pla
2023-12-08 22:56:35 +01:00
ora #lcd::CMD_SET_ADDRESS
jsr _cmd
2023-12-09 23:33:15 +01:00
and #(<~lcd::CMD_SET_ADDRESS) ; return original argument
2023-12-08 22:56:35 +01:00
rts
@invalid:
lda $14
sta charcount
lda #(lcd::CMD_SET_ADDRESS | (lcd::LINE2 + 4))
jsr _cmd
lda #(lcd::LINE2 + 4)
2023-12-09 23:33:15 +01:00
rts
2023-12-08 22:56:35 +01:00
.endproc
;;********************************************************************************
;; @function Set the LCD DD-RAM Address so that text linebreaks after 16 chars
;;********************************************************************************
.proc _break_line
2023-10-26 19:51:20 +02:00
; check if checks are necessary
2023-12-08 22:56:35 +01:00
lda charcount
beq @line1
2023-10-26 19:51:20 +02:00
and #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
2023-12-08 22:56:35 +01:00
bne @rts
2023-10-26 19:51:20 +02:00
; checks necessary
2023-12-08 22:56:35 +01:00
lda charcount
beq @line1
2023-10-26 19:51:20 +02:00
cmp #$10
2023-12-08 22:56:35 +01:00
beq @line2
2023-10-26 19:51:20 +02:00
cmp #$20
2023-12-08 22:56:35 +01:00
beq @line3
2023-10-26 19:51:20 +02:00
cmp #$30
2023-12-08 22:56:35 +01:00
beq @line4
cmp #$40 ; set to line1 when full
bge @line1
@rts:
2023-10-26 19:51:20 +02:00
rts
2023-12-08 22:56:35 +01:00
@line1:
stz charcount
lda #(lcd::CMD_SET_ADDRESS | lcd::LINE1)
jsr _cmd
2023-10-26 19:51:20 +02:00
rts
2023-12-08 22:56:35 +01:00
@line2:
lda #(lcd::CMD_SET_ADDRESS | lcd::LINE2)
jsr _cmd
2023-10-26 19:51:20 +02:00
rts
2023-12-08 22:56:35 +01:00
@line3:
lda #(lcd::CMD_SET_ADDRESS | lcd::LINE3)
jsr _cmd
2023-10-26 19:51:20 +02:00
rts
2023-12-08 22:56:35 +01:00
@line4:
lda #(lcd::CMD_SET_ADDRESS | lcd::LINE4)
jsr _cmd
2023-10-26 19:51:20 +02:00
rts
2023-10-28 03:48:27 +02:00
.endproc
2023-12-08 22:56:35 +01:00