Compare commits

..

No commits in common. "fcdedd02dc940e64d5ab38ca853cc67e7fafd77b" and "92f26b0cf294f25699772c06fedd76bed37405c4" have entirely different histories.

16 changed files with 465 additions and 503 deletions

View File

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

View File

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

View File

@ -1,25 +0,0 @@
.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,8 +1,9 @@
.include "system.h65" .ifndef INCLUDE_PRINT_SLOW
.include "sleep.h65" INCLUDE_PRINT_SLOW = 1
.include "lcd.h65"
.export print_slow .include "system.h65"
.include "sleep.s65"
.include "lcd.h65"
.code .code
;******************************************************************************** ;********************************************************************************
@ -24,3 +25,22 @@
@print_end: @print_end:
rts rts
.endproc .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

View File

@ -1,20 +0,0 @@
.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,8 +1,20 @@
.ifndef INCLUDE_SLEEP
INCLUDE_SLEEP = 1
.include "system.h65" .include "system.h65"
.export sleep
.code .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
;******************************************************************************** ;********************************************************************************
; @function sleep ; @function sleep
; @param x: Time to sleep in centiseconds (10^-2s = 10ms) ; @param x: Time to sleep in centiseconds (10^-2s = 10ms)
@ -29,3 +41,4 @@ _VAR_1 = ARG15
rts rts
; so T = N * 0,010244s - (1(last bne) + 4(jsr) + 6(rts)) * (1/1MHz) ; so T = N * 0,010244s - (1(last bne) + 4(jsr) + 6(rts)) * (1/1MHz)
.endproc .endproc
.endif ; guard

View File

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

View File

@ -1,154 +1,282 @@
.include "system.h65" .include "system.h65"
.include "string.h65"
.include "lcd.h65" .include "lcd.h65"
.include "math.h65" .include "math.h65"
.include "keypad.h65" .include "keypad.h65"
.include "chars.h65"
.import homeloop:absolute
.import home:absolute .import home:absolute
.segment "SPI" .segment "SPI"
.export CODE_START .export CODE_START
CODE_START: CODE_START:
.assert * = $5000, error, "SPI Code not at $5000" .assert * = $5000, error, "SPI Code not at $5000"
jsr lcd::clear lda '$'
lda #'>'
jsr lcd::print_char jsr lcd::print_char
jsr rb_test_init 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
stz kp::_DEBUG_VAL stz kp::_DEBUG_VAL
ldy #0
@loop: @loop:
lda kp::_DEBUG_VAL lda kp::_DEBUG_VAL
pha jeq home
stz kp::_DEBUG_VAL bra @loop
pla
beq @loop fmt_idx = $30
cmp #'*' out_idx = $31
jeq homeloop fmt_digit = $32
cmp #'#' .proc strf
beq @print stz out_idx
tya stz fmt_idx
pha 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 iny
jsr rb_test_write 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
@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:
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 pla
ora #$30 div A,16
jsr lcd::print_char and #%00001111
tay
bra @loop lda HEX_CHARS_UPPER,y
@print:
@printloop:
lda #'r'
jsr lcd::print_char
jsr @print_state
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
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 rts
.endproc .endproc
.proc rb_test_read ;********************************************************************************
ldx RB_READ ; @function Convert any int into hex
cpx RB_WRITE ; @param ARG2-3: Address of output string
beq @rb_read_rts ; if buffer empty ; @param Y: Offset onto output string
lda RB_START,x ; @param A: Number of digits to convert
inx ; increment RB_READ pointer, not using macro bec. of unknown Pz ; @param X: Offset onto ARG4 = start of int (big endian)
cpx #RB_LENGTH ; @returns Y: New offset onto output string
beq @read_wrap ; @returns A: 0
stx RB_READ ; @returns X: Offset onto ARG4 = past the end of number
@rb_read_rts: ; @modifies X,Y,A
rts ;********************************************************************************
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0 .proc int_to_hex_str
stz RB_READ bit
; make sure Pz is not set beq @rts ; check done
ldx #$01 @loop:
rts ; load next byte
.endproc pha
lda ARG4,x
.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 inx
cpx #RB_LENGTH phx
beq @read_wrap pha ; copy byte
stx RB_READ div A,16 ; get first 4 bits = first digit
rts and #%00001111
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0 phy
stz RB_READ 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 rts
.endproc .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"

View File

@ -1,26 +0,0 @@
.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

View File

@ -1,34 +0,0 @@
.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,6 +10,7 @@
; - IO.RA7 -> LCD.E enable ; - IO.RA7 -> LCD.E enable
; ;
; @requires IO: Base Address of IO Chip ; @requires IO: Base Address of IO Chip
; @optparam MEM: Memory address for a runtime variable. Default = $300
; @depends IO-W65C22N ; @depends IO-W65C22N
;******************************************************************************** ;********************************************************************************
.ifndef INCLUDE_LCD .ifndef INCLUDE_LCD
@ -19,28 +20,14 @@ INCLUDE_LCD = 1
.scope lcd .scope lcd
LCD_IO = IO1 LCD_IO = IO1
Import lcd,init,clear,print,print_char,set_position,set_custom_char Import lcd,init,clear,print,print_char,set_position
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 ; @macro Print a null-terminated string
; @param message: Address of the message ; @param message: Address of the message
;******************************************************************************** ;********************************************************************************
.macro PrintNC message .macro Print message
jsr lcd::clear
lda #<message lda #<message
sta ARG0 sta ARG0
lda #>message lda #>message
@ -53,18 +40,11 @@ E = %10000000
RW = %01000000 RW = %01000000
RS = %00100000 RS = %00100000
RA_MASK = %11100000
; LCD Instructions (see datasheet for more) ; LCD Instructions (see datasheet for more)
CMD_CLEAR = %00000001 ; clear display CMD_CLEAR = %00000001 ; clear display
CMD_ENTRY_MODE = %00000110 ; auto-shift cursor CMD_ENTRY_MODE = %00000110 ; auto-shift cursor
CMD_DISPLAY_ON = %00001111 ; everything on, with blinking 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_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 CMD_SET_ADDRESS = %10000000 ; or with the address
; LCD Constants ; LCD Constants
LINE1 = $00 LINE1 = $00
@ -72,5 +52,9 @@ LINE2 = $40
LINE3 = $10 LINE3 = $10
LINE4 = $50 LINE4 = $50
CLEAR = %00000000
.ifndef KEEPSCOPE
.endscope .endscope
.endif
.endif ; guard .endif ; guard

View File

@ -4,13 +4,12 @@
.fatal "lcd::LCD_IO is not defined: set it to the base address of the IO chip of the LCD" .fatal "lcd::LCD_IO is not defined: set it to the base address of the IO chip of the LCD"
.endif .endif
Export lcd,init,clear,print,print_char,set_position,set_custom_char Export lcd,init,clear,print,print_char,set_position
Export lcd,_cmd,_wait_nbusy,_write_ram,_read_ram
; RAM VARIABLES ; RAM VARIABLES
.bss .bss
charcount: .res 1 charcount: .res 1
; TODO when clockspeeds are more than 1MHz, _cmd, _write_ram and _read_ram might need to be adjusted
.code .code
;;******************************************************************************** ;;********************************************************************************
;; @function Initialize the lcd module ;; @function Initialize the lcd module
@ -22,9 +21,9 @@ charcount: .res 1
lda #$ff ; RB 0-7 output lda #$ff ; RB 0-7 output
sta lcd::LCD_IO+IO::DDRB sta lcd::LCD_IO+IO::DDRB
MaskedWrite lcd::LCD_IO+IO::DDRA, (lcd::RS | lcd::RW | lcd::E), lcd::RA_MASK ; 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 lda #(lcd::RS | lcd::RW | lcd::E) ; RA 5-7 output
; sta lcd::LCD_IO+IO::DDRA sta lcd::LCD_IO+IO::DDRA
; init lcd ; init lcd
lda #lcd::CMD_FUNCTION_SET lda #lcd::CMD_FUNCTION_SET
@ -41,11 +40,115 @@ charcount: .res 1
.endproc .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 ;; @function Set the cursor to a position
;; @param A: cursor position: `(lcd::LINEX + offset)`, where offset € [$0, $f] ;; @param A: cursor position: `(lcd::LINEX + offset)`, where offset € [$0, $f]
;; @details: ;; @details:
;; If the position is too large, it will be set to char 4 in line 2 ;; If the position is too large, it will be set to char 5 in line 2
;; @returns A: the cursor position ;; @returns A: the cursor position
;;******************************************************************************** ;;********************************************************************************
.proc set_position .proc set_position
@ -73,209 +176,16 @@ charcount: .res 1
@set: @set:
sta charcount sta charcount
pla pla
pha
ora #lcd::CMD_SET_ADDRESS ora #lcd::CMD_SET_ADDRESS
jsr _cmd jsr _cmd
; and #(<~lcd::CMD_SET_ADDRESS) ; return original argument and #(<~lcd::CMD_SET_ADDRESS) ; return original argument
pla
rts rts
@invalid: @invalid:
pla ; otherwise stack corruption lda $14
lda #$13
sta charcount sta charcount
lda #(lcd::CMD_SET_ADDRESS | (lcd::LINE2 + 3)) lda #(lcd::CMD_SET_ADDRESS | (lcd::LINE2 + 4))
jsr _cmd jsr _cmd
lda #(lcd::LINE2 + 3) lda #(lcd::LINE2 + 4)
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 rts
.endproc .endproc
@ -287,11 +197,11 @@ charcount: .res 1
; check if checks are necessary ; check if checks are necessary
lda charcount lda charcount
beq @line1 beq @line1
bit #%10001111 ; ($10 | $20 | $30 | $40) = %01110000 and #%10001111 ; ($10 | $20 | $30 | $40) = %01110000
beq @check bne @rts
rts
@check:
; checks necessary ; checks necessary
lda charcount
beq @line1
cmp #$10 cmp #$10
beq @line2 beq @line2
cmp #$20 cmp #$20
@ -300,6 +210,7 @@ charcount: .res 1
beq @line4 beq @line4
cmp #$40 ; set to line1 when full cmp #$40 ; set to line1 when full
bge @line1 bge @line1
@rts:
rts rts
@line1: @line1:
stz charcount stz charcount
@ -319,3 +230,4 @@ charcount: .res 1
jsr _cmd jsr _cmd
rts rts
.endproc .endproc

View File

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

View File

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

View File

@ -1,5 +1,6 @@
.include "string.h65" .include "string.h65"
Export str, strf .include "math.h65"
Export str, strf, int8_to_hex_str
.code .code
;******************************************************************************** ;********************************************************************************
@ -49,7 +50,7 @@ fmt_idx := str::fmt_idx
@format_hex1: ; 1 byte hex -> 2 chars @format_hex1: ; 1 byte hex -> 2 chars
lda ARG4,x lda ARG4,x
phx phx
jsr str::uint8_to_hex_str jsr int8_to_hex_str
ldy out_idx ldy out_idx
sta (ARG2),y ; most sig digit sta (ARG2),y ; most sig digit
iny iny
@ -78,3 +79,27 @@ fmt_idx := str::fmt_idx
.endproc .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,26 +4,22 @@ INCLUDE_UTILITY = 1
.macpack longbranch ; jeq, jge... .macpack longbranch ; jeq, jge...
.macpack generic ; bge, add, sub .macpack generic ; bge, add, sub
.feature string_escapes
.feature underline_in_numbers
;******************************************************************************** ;********************************************************************************
; @macro Update a byte in memory using a mask ; @macro Update a byte in memory using a mask
; @param addr Address of the byte to update ; @param orignal Address of the byte to update
; @param value New value ; @param new New value
; @param mask Mask of the bits to affect by the new value ; @param mask Mask of the bits to affect by the new value
; @details ; @details
; xor #value with addr -> only bits that need to flip are 1 ; 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 ; and result with mask -> only selected bits that need to flip stay 1
; xor result with addr -> flips selected bits ; xor result with original -> flips selected bits
;******************************************************************************** ;********************************************************************************
.macro MaskedWrite addr,value,mask .macro UT_update_with_mask original,new,mask
lda #value lda #new
eor addr eor original
and #mask and #mask
eor addr eor original
sta addr sta original
.endmacro .endmacro
@ -31,7 +27,7 @@ INCLUDE_UTILITY = 1
;;******************************************************************************** ;;********************************************************************************
;; @macro Generate a unique label ;; @macro Generate a unique label
;;******************************************************************************** ;;********************************************************************************
.macro GenLabel .macro genlabel
.ident(.sprintf("generated_label%04X", _n_genlabel)) .ident(.sprintf("generated_label%04X", _n_genlabel))
_n_genlabel .set _n_genlabel + 1 _n_genlabel .set _n_genlabel + 1
.endmacro .endmacro