.include "system.h65" .include "string.h65" .include "lcd.h65" .include "math.h65" .include "keypad.h65" .include "keyboard.h65" .include "chars.h65" .import homeloop:absolute .import home:absolute .segment "SPI" .export CODE_START .import memcopy 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 ARG1 lda #<$3000 sta ARG2 lda #>$3000 sta ARG3 ldy #20 jsr memcopy 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 kb::init 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 cmp #'B' beq @lB cmp #'C' beq @lC 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 @lB: Strf fmt_str, out_str, kb::keycode Print out_str bra @loop @lC: jsr lcd::clear bra @loop ; .proc 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 ; .endproc ; ;; @details ; ;; IO::SR has to be read before the next bit is shifted in, which happens ~75us after the irq ; ;; at 1MHz, handlings this interrupt takes about 50us (without any additional debug code), so it should work ; .proc 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 ; .endproc .proc irq_timer_handler ; lda #'<' ; jsr lcd::print_char lda kb::KB_IO + IO::SR sta kb::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 ; reset SR stz kb::KB_IO + IO::SR ; lda #'|' ; rotate bit 2 (last bit of keycode) into the carry ror ror ror lda kb::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 kb::keycode Strf fmt_str2, out_str, kb::keycode, kb::key_read, kb::key_read+1 PrintNC out_str stz kb::key_read stz kb::key_read+1 rts .endproc ; key_read: .res 2 ; keycode: .res 1 kb_irq1: ; lda #'!' ; jsr lcd::print_char jsr kb::irq_shift_reg_handler ; lda #':' ; jsr lcd::print_char rts .byte '=' kb_irq2: ; lda #'?' ; jsr lcd::print_char ; jsr kb::on_timer_irq jsr irq_timer_handler ; lda #';' ; jsr lcd::print_char rts .byte '@' out_str: .res 40 fmt_str: .asciiz "kc%x;" fmt_str2: .asciiz "kc%x-%x-%x; "