Compare commits
2 Commits
92f26b0cf2
...
fcdedd02dc
Author | SHA1 | Date | |
---|---|---|---|
fcdedd02dc | |||
68df62164b |
@ -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`)
|
||||
|
12
main.s65
12
main.s65
@ -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
25
programs/print_slow.h65
Normal 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
|
||||
|
||||
|
@ -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
20
programs/sleep.h65
Normal 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
|
@ -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,010 244 s - (1(last bne) + 4(jsr) + 6(rts)) * (1/1MHz)
|
||||
.endproc
|
||||
.endif ; guard
|
||||
|
@ -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"
|
||||
|
372
spicode.s65
372
spicode.s65
@ -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
|
||||
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
|
||||
|
||||
@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
|
||||
stz kp::_DEBUG_VAL
|
||||
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
|
||||
beq @loop
|
||||
cmp #'*'
|
||||
jeq homeloop
|
||||
cmp #'#'
|
||||
beq @print
|
||||
tya
|
||||
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
|
||||
jsr rb_test_write
|
||||
pla
|
||||
dec
|
||||
bne @loop
|
||||
@rts:
|
||||
ora #$30
|
||||
jsr lcd::print_char
|
||||
|
||||
bra @loop
|
||||
|
||||
|
||||
@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
|
||||
.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
|
||||
.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
|
||||
@hex_char:
|
||||
; carry is not set
|
||||
adc #10
|
||||
@rts:
|
||||
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0
|
||||
stz RB_READ
|
||||
; make sure Pz is not set
|
||||
ldx #$01
|
||||
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
|
||||
.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
|
||||
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
|
||||
bra @check_buf_full
|
||||
@read_inc:
|
||||
ldx RB_READ
|
||||
inx
|
||||
pla
|
||||
dec
|
||||
bne @loop
|
||||
@invalid:
|
||||
@rts:
|
||||
cpx #RB_LENGTH
|
||||
beq @read_wrap
|
||||
stx RB_READ
|
||||
rts
|
||||
@read_wrap: ; ptr == RB_LENGTH -> ptr = 0
|
||||
stz RB_READ
|
||||
rts
|
||||
|
||||
.endproc
|
||||
|
||||
|
||||
|
||||
TEST_FMT: .asciiz "%x -> %x -> %x:)"
|
||||
TEST_OUT: .asciiz "TESTOUT"
|
||||
HEX_CHARS_UPPER: .byte "0123456789ABCDEF"
|
||||
HEX_CHARS_LOWER: .byte "0123456789abcdef"
|
||||
|
26
system/chars.h65
Normal file
26
system/chars.h65
Normal 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
34
system/chars.s65
Normal 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
|
@ -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
|
||||
|
328
system/lcd.s65
328
system/lcd.s65
@ -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
|
||||
|
||||
|
@ -32,6 +32,7 @@ ARG4 = $14
|
||||
ARG5 = $15
|
||||
ARG6 = $16
|
||||
ARG7 = $17
|
||||
ARG8 = $18
|
||||
ARG9 = $19
|
||||
ARG10 = $1a
|
||||
ARG11 = $1b
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
26
utility.h65
26
utility.h65
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user