6502-OS/spicode.s65
2023-12-22 02:17:58 +01:00

214 lines
3.8 KiB
Plaintext

.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
.import memcopy
.scope kb
KB_IO = IO1
.endscope
CODE_START:
.assert * = $5000, error, "SPI Code not at $5000"
jsr lcd::clear
lda #'$'
jsr lcd::print_char
; stz kp::_DEBUG_VAL
; @loop:
; lda kp::_DEBUG_VAL
; beq @loop
; stz kp::_DEBUG_VAL
; cmp #'*'
; jeq homeloop
; jsr lcd::print_char
; bra @loop
lda #<kb_irq1
sta ARG0
lda #>kb_irq1
sta ARG1
lda #<$3000
sta ARG2
lda #>$3000
sta ARG3
ldy #20
jsr memcopy
lda #<kb_irq2
sta ARG0
lda #>kb_irq2
sta ARG1
lda #<$3100
sta ARG2
lda #>$3100
sta ARG3
ldy #20
jsr memcopy
lda #'?'
jsr lcd::print_char
; PrintNC $3000
jsr kbinit
lda #'%'
jsr lcd::print_char
stz kp::_DEBUG_VAL
ldy #0
@loop:
lda kp::_DEBUG_VAL
beq @loop
stz kp::_DEBUG_VAL
cmp #'*'
jeq homeloop
cmp #'1'
beq @l1
cmp #'2'
beq @l2
cmp #'3'
beq @l3
cmp #'A'
beq @lA
jsr lcd::print_char
bra @loop
@l1:
; jsr irq_on_shift_reg
jsr $3000
lda #'*'
jsr lcd::print_char
bra @loop
@l2:
; jsr irq_on_timer
jsr $3100
lda #'#'
jsr lcd::print_char
bra @loop
@l3:
lda $3000,y
jsr lcd::print_char
iny
bra @loop
@lA:
lda kb::KB_IO + IO::SR
jsr lcd::print_char
bra @loop
kbinit:
lda #'['
jsr lcd::print_char
; - use the shift register interrupts to read the first 8 bits
; set shift register to shift in under external clock on CB1
; - configure timer for timing the read of the last 3 bits
; timer 2 one shot mode is sufficient, leaves T1 available
lda #(IO::ACR::SR_SIN_PHIE | IO::ACR::T2_IRQ_LOAD)
tsb kb::KB_IO + IO::ACR
; the 3 last bits take about 230us, at @1MHz => wait 230 cycles and then the shift register
lda #230
sta kb::KB_IO + IO::T2CL
stz key_read
stz key_read+1
; enable SR interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
sta kb::KB_IO + IO::IER
; load SR to reset
lda kb::KB_IO + IO::SR
lda #']'
jsr lcd::print_char
rts
irq_on_shift_reg:
; lda #'{'
; jsr lcd::print_char
lda kb::KB_IO + IO::SR
sta key_read
stz kb::KB_IO + IO::SR
; disable SR interrupts
lda #IO::IRQ::SR
sta kb::KB_IO + IO::IER
; enable timer interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::T2)
sta kb::KB_IO + IO::IER
; start timer
lda #1
sta kb::KB_IO + IO::T2CH
; lda #'}'
; jsr lcd::print_char
rts
irq_on_timer:
lda #'<'
jsr lcd::print_char
lda kb::KB_IO + IO::SR
sta key_read + 1
lda kb::KB_IO + IO::T2CL ; clear interrupt flag
; disable timer interrupts
lda #(IO::IRQ::T2)
sta kb::KB_IO + IO::IER
; enable shift register interrupts
lda #(IO::IRQ::IRQ | IO::IRQ::SR)
sta kb::KB_IO + IO::IER
; load SR to reset
stz kb::KB_IO + IO::SR
; lda #'|'
lda key_read
jsr lcd::print_char
lda key_read + 1
jsr lcd::print_char
; rotate bit 2 (last bit of keycode) into the carry
ror
ror
ror
lda key_read ; not affecting carry
rol ; rotate carry into byte, rotate startbit into carry
; TODO byte is inverted, maybe consider wasting 256 bytes for a bit reverse lookup table?
sta keycode
stz key_read
stz key_read+1
Strf "kc:%x", out_str, keycode
PrintNC out_str
rts
key_read: .res 2
keycode: .res 1
kb_irq1:
; lda #'!'
; jsr lcd::print_char
jsr irq_on_shift_reg
; lda #':'
; jsr lcd::print_char
rts
.byte '='
kb_irq2:
; lda #'?'
; jsr lcd::print_char
jsr irq_on_timer
lda #';'
jsr lcd::print_char
rts
.byte '@'
out_str: .res 40