Compare commits

...

2 Commits

Author SHA1 Message Date
fcdedd02dc add custom chars 2023-12-16 02:44:47 +01:00
68df62164b split header-source 2023-12-16 02:41:19 +01:00
16 changed files with 510 additions and 472 deletions

View File

@ -15,5 +15,5 @@ leading underscors `_` indicate a "private" label/variable, that is meant for in
### Labels
- **scopes**: snake case
- **subroutines** and **variables**: snake case (`scope::(_)fname_snake_case` or `scope::(_)varname_2`)
- **macros**: camel case (`(_)GoodMacroname`)
- **macros**: camel case (`(_)GoodMacroname` or `scope_GoodMacroname`)
- **constants** (eg. in ROM): upper case (`scope::(_)NICE_SYMBOLNAME`)

View File

@ -1,5 +1,5 @@
.include "system/system.h65"
.export home
.export home,homeloop
.import printer:absolute
.import spi_menu:absolute
@ -36,6 +36,7 @@
; .include "utility.asm6502"
; LCD_IO = IO1
.include "system/lcd.h65"
.include "chars.h65"
; Keypad Reading
; KP_IO = IO2
.include "system/keypad.h65"
@ -43,7 +44,7 @@
.include "system/spi.h65"
; Printer
; .include "programs/printer.s65"
.include "programs/print_slow.s65"
.include "programs/print_slow.h65"
; .include "programs/spi-menu.s65"
; Digital Humidity and Temerature Sensor
; .include "dht.s65"
@ -107,6 +108,10 @@ reset:
jsr kp::init
SetCustomChar chars::CAT,0
SetCustomChar chars::SMILEY,1
SetCustomChar chars::SMILEY_XD,2
; ; INIT DHT
; lda #%11000010 ; enable interrupt for Timer 1 and CA1 on IO2
@ -126,6 +131,9 @@ reset:
.proc home
Print message_menu
; jsr rb_keypad_read
bra homeloop
.endproc
.proc homeloop
@loop:
lda kp::_DEBUG_VAL
beq @loop

25
programs/print_slow.h65 Normal file
View File

@ -0,0 +1,25 @@
.ifndef INCLUDE_PRINT_SLOW
INCLUDE_PRINT_SLOW = 1
.import print_slow
;********************************************************************************
; @macro Print a null-terminated string
; @param message: Address of the message
; @param time_cs: time to sleep in centiseconds
;********************************************************************************
.macro PrintSlow message,time_cs
jsr lcd::clear
lda #<message
sta ARG0
lda #>message
sta ARG1
phx
ldx #time_cs
jsr print_slow
plx
.endmacro
.endif ; guard

View File

@ -1,10 +1,9 @@
.ifndef INCLUDE_PRINT_SLOW
INCLUDE_PRINT_SLOW = 1
.include "system.h65"
.include "sleep.s65"
.include "sleep.h65"
.include "lcd.h65"
.export print_slow
.code
;********************************************************************************
; @function Print a null-terminated string
@ -25,22 +24,3 @@ INCLUDE_PRINT_SLOW = 1
@print_end:
rts
.endproc
;********************************************************************************
; @macro Print a null-terminated string
; @param message: Address of the message
; @param time_cs: time to sleep in centiseconds
;********************************************************************************
.macro PrintSlow message,time_cs
jsr lcd::clear
lda #<message
sta ARG0
lda #>message
sta ARG1
phx
ldx #time_cs
jsr print_slow
plx
.endmacro
.endif ; guard

20
programs/sleep.h65 Normal file
View File

@ -0,0 +1,20 @@
.ifndef INCLUDE_SLEEP
INCLUDE_SLEEP = 1
.import sleep
.code
;********************************************************************************
; @macro Sleep
; @param time_cs: Time to sleep in centiseconds (10^-2s = 10ms)
; @details
; Interrupts might change the actual time to finish
;********************************************************************************
.macro Sleep time_cs
phx
ldx #time_cs
jsr sleep
plx
.endmacro
.endif ; guard

View File

@ -1,20 +1,8 @@
.ifndef INCLUDE_SLEEP
INCLUDE_SLEEP = 1
.include "system.h65"
.code
;********************************************************************************
; @macro Sleep
; @param time_cs: Time to sleep in centiseconds (10^-2s = 10ms)
; @details
; Interrupts might change the actual time to finish
;********************************************************************************
.macro Sleep time_cs
phx
ldx #time_cs
jsr sleep
plx
.endmacro
.export sleep
.code
;********************************************************************************
; @function sleep
; @param x: Time to sleep in centiseconds (10^-2s = 10ms)
@ -41,4 +29,3 @@ _VAR_1 = ARG15
rts
; so T = N * 0,010244s - (1(last bne) + 4(jsr) + 6(rts)) * (1/1MHz)
.endproc
.endif ; guard

View File

@ -2,6 +2,7 @@
.include "string.h65"
.include "keypad.h65"
.include "lcd.h65"
.include "chars.h65"
.import home:absolute
.import SPI_IO
@ -22,10 +23,10 @@ status_str: .res 17 ; 16 + null
jsr lcd::clear
Print MENU
@print_status:
Strf FMT_STATUS,status_str,trans_pages,trans_bytes,status
lda #lcd::LINE4
jsr lcd::set_position
Print status_str
Strf FMT_STATUS,status_str,trans_pages,trans_bytes,status
PrintNC status_str
@loop:
; check if a byte has been transferred
@check_byte:
@ -82,7 +83,7 @@ status_str: .res 17 ; 16 + null
.rodata
MENU:
.byte "A> Beg. Transfer"
.byte chars::DOT, "A Beg. Transfer"
.byte "B> Stop Transfer"
.asciiz "C> Jump Home <*"
; .asciiz "0b0p Status: X"

View File

@ -1,282 +1,154 @@
.include "system.h65"
.include "string.h65"
.include "lcd.h65"
.include "math.h65"
.include "keypad.h65"
.include "chars.h65"
.import homeloop:absolute
.import home:absolute
.segment "SPI"
.export CODE_START
CODE_START:
.assert * = $5000, error, "SPI Code not at $5000"
lda '$'
jsr lcd::clear
lda #'>'
jsr lcd::print_char
lda #<TEST_FMT
sta ARG0
lda #>TEST_FMT
sta ARG1
lda #<TEST_OUT
sta ARG2
lda #>TEST_OUT
sta ARG3
lda #$a9
sta ARG4
lda #$3c
sta ARG5
lda #$10
sta ARG6
jsr strf
Print TEST_OUT
jsr rb_test_init
stz kp::_DEBUG_VAL
ldy #0
@loop:
lda kp::_DEBUG_VAL
jeq home
pha
stz kp::_DEBUG_VAL
pla
beq @loop
cmp #'*'
jeq homeloop
cmp #'#'
beq @print
tya
pha
iny
jsr rb_test_write
pla
ora #$30
jsr lcd::print_char
bra @loop
fmt_idx = $30
out_idx = $31
fmt_digit = $32
.proc strf
stz out_idx
stz fmt_idx
stz fmt_digit
ldx #0 ; index of format args
@loop:
ldy fmt_idx
lda (ARG0),y
beq @null
cmp #'%'
beq @percent
@normal_char: ; store A in output string
ldy out_idx
sta (ARG2),y
inc fmt_idx
inc out_idx
beq @out_overflow
bra @loop
@percent: ; check for format in next position
iny
sty fmt_idx
lda (ARG0),y ; next char
beq @null
; formats
cmp #'9'
ble @percent_number ; numbers < letters
cmp #'x'
beq @format_hex1
bra @normal_char
@percent_number:
cmp #'1'
blt @normal_char ; NaN or zero
; todo covert from char
jsr hex_char_to_int ; only 0-9 supported
; A is now number of digits to convert
sta fmt_digit
iny
sty fmt_idx
lda (ARG0),y ; next char
beq @null
cmp #'x'
beq @format_hexN
bra @normal_char
@format_hexN:
lda fmt_digit
jsr int_to_hex_str
bra @format_return
@print:
@printloop:
lda #'r'
jsr lcd::print_char
jsr @print_state
@format_hex1: ; 1 byte hex -> 2 chars
lda ARG4,x
phx
jsr int8_to_hex_str
ldy out_idx
sta (ARG2),y ; most sig digit
iny
beq @out_overflow
txa
sta (ARG2),y ; least sig digit
iny
beq @out_overflow
sty out_idx
plx
inx ; 1 byte of args handeled
; bra @format_return
@format_return: ; increment fmt_idx to swallow the formating char
inc fmt_idx
bra @loop
@out_overflow: ; store 0 in last position
ldy #$ff
sty out_idx
@store_null:
lda #0
@null: ; store and return
ldy out_idx
sta (ARG2),y
@rts:
jsr rb_test_read
beq @empty
ora #$30
jsr lcd::print_char
lda #';'
jsr lcd::print_char
bra @printloop
@empty:
lda #'E'
jsr lcd::print_char
lda #';'
jsr lcd::print_char
bra @loop
@print_state:
lda #'('
jsr lcd::print_char
lda RB_READ
ora #$30
jsr lcd::print_char
lda RB_WRITE
ora #$30
jsr lcd::print_char
lda #')'
jsr lcd::print_char
rts
.endproc
;********************************************************************************
; @function Convert a 1 byte number into two hex characters
; @param A: Number to convert
; @returns A: Most significant digit
; @returns X: Least significant digit
; @modifies A,X,Y
;********************************************************************************
.proc int8_to_hex_str
pha
and #%00001111
tay
ldx HEX_CHARS_UPPER,y
pla
div A,16
and #%00001111
tay
lda HEX_CHARS_UPPER,y
rts
.endproc
;********************************************************************************
; @function Convert any int into hex
; @param ARG2-3: Address of output string
; @param Y: Offset onto output string
; @param A: Number of digits to convert
; @param X: Offset onto ARG4 = start of int (big endian)
; @returns Y: New offset onto output string
; @returns A: 0
; @returns X: Offset onto ARG4 = past the end of number
; @modifies X,Y,A
;********************************************************************************
.proc int_to_hex_str
bit
beq @rts ; check done
@loop:
; load next byte
pha
lda ARG4,x
inx
phx
pha ; copy byte
div A,16 ; get first 4 bits = first digit
and #%00001111
phy
tay
lda HEX_CHARS_LOWER,y
ply
sta (ARG2),y
iny
pla ; get copy
and #%00001111 ; lower 4 bits = second digit
phy
tay
lda HEX_CHARS_LOWER,y
ply
sta (ARG2),y
iny
plx
pla
dec
bne @loop
@rts:
rts
.endproc
;********************************************************************************
; @function Convert a hex char into a binary number
; @details
; The char must be one of [0-9,a-f,A-F].
; All results are only valid if N == 0.
; @param A: Char to convert
; @returns N: 0 == success, 1 == invalid char
; @returns A: The converted number
;********************************************************************************
.proc hex_char_to_int
sec
sbc #'0'
bmi @invalid ; char was in [0, '0')
cmp #10
bcc @rts ; A in [0, 10)
; char higher than '9'
sbc #('A' - '0')
bmi @invalid ; char was in ('0', 'A')
cmp #7
bcc @hex_char ; A in [0, 6]
; char higher than 'F'
sbc #('a' - 'A')
bmi @invalid ; char was in ('F', 'a')
cmp #17
bcc @hex_char ; A in [0, 6]
; char was in ('f', $ff]
@invalid:
lda #$ff ; sets N flag
rts
@hex_char:
; carry is not set
adc #10
@rts:
rts
.endproc
;********************************************************************************
; @function Convert a number encoded as hexadecimal string to a binary number
; @details
; The string must only consist of [0-9,a-f,A-F].
; All results are only valid if N == 0.
; @param ARG0-1: Address of string
; @param A: Number of chars to convert
; @param Y: Offset onto string so that first char = (ARG0) + Y
; @returns N: 0 => success, 1 => invalid string
; @returns A: 0
; @returns X: Size of the number in bytes
; @returns Y: Offset onto string, past the end of the number
; @modifies X,Y,A
;********************************************************************************
.proc hex_to_int
bit #%11111111 ; check if accumulator is zero
beq @rts
ldx #0
bit #%00000001 ; check if accumulator is even
beq @loop ; even
; not even
stz ARG2
pha
bra @less_sig_char
@loop:
pha
; more significant char
lda (ARG0),y ; load next char
iny
jsr hex_char_to_int
bmi @invalid
rol
rol
rol
rol
sta ARG2,x
@less_sig_char:
; less significant char
lda (ARG0),y ; load next char
iny
jsr hex_char_to_int
bmi @invalid
ora ARG2,x
sta ARG2,x
inx
pla
dec
bne @loop
@invalid:
@rts:
rts
.endproc
TEST_FMT: .asciiz "%x -> %x -> %x:)"
TEST_OUT: .asciiz "TESTOUT"
HEX_CHARS_UPPER: .byte "0123456789ABCDEF"
HEX_CHARS_LOWER: .byte "0123456789abcdef"
TEST_MEMSIZE = $A
RBUF_MEM_START:
.res TEST_MEMSIZE
RBUF_MEM_END:
.define RBUF_NAME "test"
.define _RBUF_NAME .concat("rb_", RBUF_NAME)
RB_WRITE = RBUF_MEM_START ; write pointer, relative to RB_WRITE
RB_READ = RBUF_MEM_START + 1 ; read ponter, relative to RB_START
RB_START = RBUF_MEM_START + 2
RB_LENGTH = RBUF_MEM_END - RBUF_MEM_START - 2
.if RB_LENGTH < 1
.fatal "buffer size too small, must be at least 1"
.endif
.if RB_LENGTH > $ff
.fatal "buffer size too large, must be <= $ff"
.endif
; .out .sprintf("Buffer: %x -> %x (len=%x)", RBUF_MEM_START, RBUF_MEM_END, RB_LENGTH)
.proc rb_test_init
stz RB_WRITE
stz RB_READ
rts
.endproc
.proc rb_test_read
ldx RB_READ
cpx RB_WRITE
beq @rb_read_rts ; if buffer empty
lda RB_START,x
inx ; increment RB_READ pointer, not using macro bec. of unknown Pz
cpx #RB_LENGTH
beq @read_wrap
stx RB_READ
@rb_read_rts:
rts
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0
stz RB_READ
; make sure Pz is not set
ldx #$01
rts
.endproc
.proc rb_test_write
; lda kp_VALUES, x ; load the char in a
ldx RB_WRITE
sta RB_START,x
inx ; increment write pointer
cpx #RB_LENGTH
beq @write_wrap
stx RB_WRITE
@check_buf_full: ; increment read if buffer is full
cpx RB_READ
beq @read_inc
rts
@write_wrap: ; ptr == RB_LENGTH -> ptr = 0
stz RB_WRITE
ldx #0
bra @check_buf_full
@read_inc:
ldx RB_READ
inx
cpx #RB_LENGTH
beq @read_wrap
stx RB_READ
rts
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0
stz RB_READ
rts
.endproc

26
system/chars.h65 Normal file
View File

@ -0,0 +1,26 @@
.ifndef INCLUDE_CHARS
INCLUDE_CHARS = 1
.include "system.h65"
.scope chars
ARROW_RIGHT = $7E
ARROW_LEFT = $7F
DOT = $A5
Import chars, CAT, SMILEY, SMILEY_XD
.macro SetCustomChar charaddr,asciinr
lda #<charaddr
sta ARG0
lda #>charaddr
sta ARG1
lda #asciinr
jsr lcd::set_custom_char
.endmacro
.endscope
.endif

34
system/chars.s65 Normal file
View File

@ -0,0 +1,34 @@
.include "chars.h65"
Export chars, CAT, SMILEY, SMILEY_XD
.rodata
CAT:
.byte %00000
.byte %10001
.byte %11111
.byte %11111
.byte %01110
.byte %11111
.byte %01110
.byte %00000
SMILEY_XD:
.byte %00000
.byte %01010
.byte %00100
.byte %01010
.byte %00000
.byte %11111
.byte %01110
.byte %00000
SMILEY:
.byte %00000
.byte %00000
.byte %01010
.byte %00000
.byte %11111
.byte %01110
.byte %00000
.byte %00000

View File

@ -10,7 +10,6 @@
; - IO.RA7 -> LCD.E enable
;
; @requires IO: Base Address of IO Chip
; @optparam MEM: Memory address for a runtime variable. Default = $300
; @depends IO-W65C22N
;********************************************************************************
.ifndef INCLUDE_LCD
@ -20,14 +19,28 @@ INCLUDE_LCD = 1
.scope lcd
LCD_IO = IO1
Import lcd,init,clear,print,print_char,set_position
Import lcd,init,clear,print,print_char,set_position,set_custom_char
Import lcd,_cmd,_wait_nbusy,_write_ram,_read_ram
;********************************************************************************
; @macro Clear the screen and print a null-terminated string
; @param message: Address of the message
;********************************************************************************
.macro Print message
jsr lcd::clear
lda #<message
sta ARG0
lda #>message
sta ARG1
jsr lcd::print
.endmacro
;********************************************************************************
; @macro Print a null-terminated string
; @param message: Address of the message
;********************************************************************************
.macro Print message
jsr lcd::clear
.macro PrintNC message
lda #<message
sta ARG0
lda #>message
@ -40,11 +53,18 @@ E = %10000000
RW = %01000000
RS = %00100000
RA_MASK = %11100000
; LCD Instructions (see datasheet for more)
CMD_CLEAR = %00000001 ; clear display
CMD_ENTRY_MODE = %00000110 ; auto-shift cursor
CMD_DISPLAY_ON = %00001111 ; everything on, with blinking cursor
CMD_SHIFT_CUR_LEFT = %00101000 ; shift the display to the left
CMD_SHIFT_DIS_LEFT = %00111000 ; shift the display to the left
CMD_SHIFT_DIS_RIGHT = %00110000 ; shift the display to the right
CMD_SHIFT_CUR_RIGHT = %00100000 ; shift the display to the right
CMD_FUNCTION_SET = %00111000 ; 8-bit, 4 lines, 5x7 font
CMD_SET_CG_ADDRESS = %01000000 ; or with the address
CMD_SET_ADDRESS = %10000000 ; or with the address
; LCD Constants
LINE1 = $00
@ -52,9 +72,5 @@ LINE2 = $40
LINE3 = $10
LINE4 = $50
CLEAR = %00000000
.ifndef KEEPSCOPE
.endscope
.endif
.endif ; guard

View File

@ -4,12 +4,13 @@
.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
Export lcd,init,clear,print,print_char,set_position,set_custom_char
Export lcd,_cmd,_wait_nbusy,_write_ram,_read_ram
; RAM VARIABLES
.bss
charcount: .res 1
; TODO when clockspeeds are more than 1MHz, _cmd, _write_ram and _read_ram might need to be adjusted
.code
;;********************************************************************************
;; @function Initialize the lcd module
@ -21,9 +22,9 @@ charcount: .res 1
lda #$ff ; RB 0-7 output
sta lcd::LCD_IO+IO::DDRB
; 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
MaskedWrite lcd::LCD_IO+IO::DDRA, (lcd::RS | lcd::RW | lcd::E), lcd::RA_MASK
; lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output
; sta lcd::LCD_IO+IO::DDRA
; init lcd
lda #lcd::CMD_FUNCTION_SET
@ -40,115 +41,11 @@ charcount: .res 1
.endproc
;;********************************************************************************
;; 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
rts
.endproc
;;********************************************************************************
;; @function Print a null-terminated string
;; @param ARG0-1 Address of the string to print
;; @modifies: A,Y
;;********************************************************************************
.proc print
ldy #$00
@lcd_print_loop:
lda (ARG0),y
beq @lcd_print_end
jsr print_char
iny
bra @lcd_print_loop
@lcd_print_end:
rts
.endproc
;;********************************************************************************
;; @macro Print a single character
;; @param A: Character to print
;;********************************************************************************
.proc print_char
pha
pha
; TODO use UT_update_with_mask?
jsr _wait_nbusy
pla
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
pla ; put char back in a
.endproc
;;********************************************************************************
;; Internal LCD Commands
;;********************************************************************************
; read busy flag
.proc _wait_nbusy
stz lcd::LCD_IO + IO::DDRB ; set IO1-IO + IO::RB to input
@lcd_wait_nbusy_loop: ; read the busy flag
lda #lcd::RW
sta lcd::LCD_IO + IO::RA
lda #(lcd::RW | lcd::E)
sta lcd::LCD_IO + IO::RA
lda lcd::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::LCD_IO + IO::RA
lda #%11111111 ; set IO1-IO + IO::RB to output
sta lcd::LCD_IO + IO::DDRB
rts
.endproc
;;********************************************************************************
;; @function Send a command to the lcd
;; @param A: command
;; @modifies A
;;********************************************************************************
.proc _cmd ; send cmd in acc
pha
jsr _wait_nbusy
pla
; TODO use UT_update_with_mask?
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
rts
.endproc
;;********************************************************************************
;; @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
;; If the position is too large, it will be set to char 4 in line 2
;; @returns A: the cursor position
;;********************************************************************************
.proc set_position
@ -176,16 +73,209 @@ charcount: .res 1
@set:
sta charcount
pla
pha
ora #lcd::CMD_SET_ADDRESS
jsr _cmd
and #(<~lcd::CMD_SET_ADDRESS) ; return original argument
; and #(<~lcd::CMD_SET_ADDRESS) ; return original argument
pla
rts
@invalid:
lda $14
pla ; otherwise stack corruption
lda #$13
sta charcount
lda #(lcd::CMD_SET_ADDRESS | (lcd::LINE2 + 4))
lda #(lcd::CMD_SET_ADDRESS | (lcd::LINE2 + 3))
jsr _cmd
lda #(lcd::LINE2 + 4)
lda #(lcd::LINE2 + 3)
rts
.endproc
;;********************************************************************************
;; PRINTING TO LCD
;;********************************************************************************
;;********************************************************************************
;; @function Clear the display
;; @see lcd_print
;; @modifies A
;;********************************************************************************
.proc clear
stz charcount
lda #lcd::CMD_CLEAR
jsr _cmd
rts
.endproc
;;********************************************************************************
;; @function Print a null-terminated string
;; @param ARG0-1 Address of the string to print
;; @modifies: A,Y
;; @returns Y: Length of the string
;;********************************************************************************
.proc print
ldy #$00
@lcd_print_loop:
lda (ARG0),y
beq @lcd_print_end
jsr print_char
iny
bra @lcd_print_loop
@lcd_print_end:
rts
.endproc
;;********************************************************************************
;; @function Print a single character
;; @param A: Character to print
;;********************************************************************************
.proc print_char
pha
jsr _write_ram
inc charcount
jsr _break_line
pla ; put char back in a
.endproc
;;********************************************************************************
;; @function Write a custom character to the lcds CharacterGenerator (CG) RAM
;; @param A: The ASCII code: 0-7
;; @param ARG0-1: Start address of the 8 bytes describing the character
;; @returns: C: 0 => success, 1 => invalid argument
;; @modifies: A,Y
;;********************************************************************************
.proc set_custom_char
cmp #8
bcs @rts ; >= 8
rol ; address is bytes 3-5
rol
rol
ora #lcd::CMD_SET_CG_ADDRESS
jsr lcd::_cmd
ldy #0
@loop:
lda (ARG0),y
jsr lcd::_write_ram
iny
cpy #8
bne @loop
clc
@rts:
rts
.endproc
;;********************************************************************************
;; Internal LCD Commands
;;********************************************************************************
;; @function Wait until the lcd is no longer busy
;; @details
;; Reads from the address until the busy flag is no longer set.
;; After reading, the VIA will be set to output mode again
;;********************************************************************************
.proc _wait_nbusy
pha
stz lcd::LCD_IO + IO::DDRB ; set IO1-IO + IO::RB to input
@lcd_wait_nbusy_loop: ; read the busy flag
; TODO use update_with_mask
lda #lcd::RW
sta lcd::LCD_IO + IO::RA
lda #(lcd::RW | lcd::E)
sta lcd::LCD_IO + IO::RA
lda lcd::LCD_IO + IO::RB
bmi @lcd_wait_nbusy_loop ; msb set
; and #%10000000 ; and updates zero flag, if not set retry
; bne @lcd_wait_nbusy_loop
lda #%00000000 ; TODO dont overwrite 0-4
sta lcd::LCD_IO + IO::RA
lda #%11111111 ; set IO1-IO + IO::RB to output
sta lcd::LCD_IO + IO::DDRB
pla
rts
.endproc
;;********************************************************************************
;; @function Send a command to the lcd
;; @param A: command
;; @modifies A
;;********************************************************************************
.proc _cmd
jsr _wait_nbusy
sta lcd::LCD_IO + IO::RB
; while preserve bits 0-4: unset E, set RS
; unset E, RW and RS
lda lcd::LCD_IO + IO::RA
and #(<~lcd::RA_MASK)
sta lcd::LCD_IO + IO::RA
; set E
ora #lcd::E
sta lcd::LCD_IO + IO::RA
; unset E
eor #lcd::E
sta lcd::LCD_IO + IO::RA
rts
.endproc
;;********************************************************************************
;; @function Write a byte to the lcd
;; @details
;; Set the CG or DD address first
;; @param A: data
;; @modifies A
;;********************************************************************************
.proc _write_ram
jsr _wait_nbusy
sta lcd::LCD_IO + IO::RB
; while preserve bits 0-4: unset E and RW, set RS
lda lcd::LCD_IO + IO::RA
and #(<~lcd::RA_MASK)
ora #lcd::RS
sta lcd::LCD_IO + IO::RA
; set E
ora #lcd::E
sta lcd::LCD_IO + IO::RA
; unsert E
eor #lcd::E
sta lcd::LCD_IO + IO::RA
rts
.endproc
;;********************************************************************************
;; @function Read a byte from the lcd
;; @details
;; Set the CG or DD address first
;; @returns A: byte
;;********************************************************************************
.proc _read_ram
jsr _wait_nbusy
; set IO1-IO + IO::RB to input
stz lcd::LCD_IO + IO::DDRB
; while preserve bits 0-4: unset E, set RW and RS
lda lcd::LCD_IO + IO::RA
and #(<~lcd::RA_MASK)
ora #(lcd::RW | lcd::RS)
sta lcd::LCD_IO + IO::RA
; set E
ora #lcd::E
sta lcd::LCD_IO + IO::RA
; load the byte
lda lcd::LCD_IO + IO::RB
pha
; unset E
lda lcd::LCD_IO + IO::RA
eor #lcd::E
sta lcd::LCD_IO + IO::RA
; set IO1-IO + IO::RB to output
lda #$ff
sta lcd::LCD_IO + IO::DDRB
pla
rts
.endproc
@ -197,11 +287,11 @@ charcount: .res 1
; check if checks are necessary
lda charcount
beq @line1
and #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
bne @rts
bit #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
beq @check
rts
@check:
; checks necessary
lda charcount
beq @line1
cmp #$10
beq @line2
cmp #$20
@ -210,7 +300,6 @@ charcount: .res 1
beq @line4
cmp #$40 ; set to line1 when full
bge @line1
@rts:
rts
@line1:
stz charcount
@ -230,4 +319,3 @@ charcount: .res 1
jsr _cmd
rts
.endproc

View File

@ -32,6 +32,7 @@ ARG4 = $14
ARG5 = $15
ARG6 = $16
ARG7 = $17
ARG8 = $18
ARG9 = $19
ARG10 = $1a
ARG11 = $1b

View File

@ -11,7 +11,8 @@ INCLUDE_STRING = 1
.scope str
Import str, strf, int8_to_hex_str
Import str, strf
Import str, hex_char_to_uint8, hex_str_to_uint, uint8_to_hex_str
.macro _StrfStoreArg arg

View File

@ -1,6 +1,5 @@
.include "string.h65"
.include "math.h65"
Export str, strf, int8_to_hex_str
Export str, strf
.code
;********************************************************************************
@ -50,7 +49,7 @@ fmt_idx := str::fmt_idx
@format_hex1: ; 1 byte hex -> 2 chars
lda ARG4,x
phx
jsr int8_to_hex_str
jsr str::uint8_to_hex_str
ldy out_idx
sta (ARG2),y ; most sig digit
iny
@ -79,27 +78,3 @@ fmt_idx := str::fmt_idx
.endproc
;********************************************************************************
; @function Convert a 1 byte number into two hex characters
; @param A: Number to convert
; @returns A: Most significant digit
; @returns X: Least significant digit
; @modifies A,X,Y
;********************************************************************************
.proc int8_to_hex_str
pha
and #%00001111
tay
ldx HEX_CHARS_UPPER,y
pla
div A,16
and #%00001111
tay
lda HEX_CHARS_UPPER,y
rts
.endproc
.rodata
HEX_CHARS_UPPER: .byte "0123456789ABCDEF"
HEX_CHARS_LOWER: .byte "0123456789abcdef"

View File

@ -4,22 +4,26 @@ INCLUDE_UTILITY = 1
.macpack longbranch ; jeq, jge...
.macpack generic ; bge, add, sub
.feature string_escapes
.feature underline_in_numbers
;********************************************************************************
; @macro Update a byte in memory using a mask
; @param orignal Address of the byte to update
; @param new New value
; @param addr Address of the byte to update
; @param value New value
; @param mask Mask of the bits to affect by the new value
; @details
; xor new with original -> only bits that need to flip are 1
; and result with mask -> only selected bits that need to flip stay 1
; xor result with original -> flips selected bits
; xor #value with addr -> only bits that need to flip are 1
; and result with #mask -> only selected bits that need to flip stay 1
; xor result with addr -> flips selected bits
;********************************************************************************
.macro UT_update_with_mask original,new,mask
lda #new
eor original
.macro MaskedWrite addr,value,mask
lda #value
eor addr
and #mask
eor original
sta original
eor addr
sta addr
.endmacro
@ -27,7 +31,7 @@ INCLUDE_UTILITY = 1
;;********************************************************************************
;; @macro Generate a unique label
;;********************************************************************************
.macro genlabel
.macro GenLabel
.ident(.sprintf("generated_label%04X", _n_genlabel))
_n_genlabel .set _n_genlabel + 1
.endmacro