.include "keyboard.h65" .include "string.h65" .include "lcd.h65" Export kb,init,irq_shift_reg_handler,irq_timer_handler,scancode,key_read Export kb, CHARS_NOMOD, CHARS_MODSHIFT ExportZp kb,status .zeropage status: .bss key_read: .res 2 scancode: .res 1 .code ;;******************************************************************************** ;; @function Initialize the PS2 keyboard ;; @modifies: A ;;******************************************************************************** .proc init ; - 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 ; (this could be shorter since the it takes a few cycles after the interrupt) lda #230 sta kb::KB_IO + IO::T2CL stz key_read stz key_read+1 stz scancode stz status ; 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 rts .endproc ;;******************************************************************************** ;; @function Read the first 8 bits an ;; @modifies: A ;; @details ;; - read shift register ;; - disable shift register interrupts ;; - reset shift register ;; - enable timer 2 interrupts ;; - start timer 2 ;; IO::SR has to be read before the next bit is shifted in, which happens ~75us after the irq ;; at 1MHz, handling this interrupt takes about 50us (without any additional debug code), ;; so it should work ;;******************************************************************************** .proc irq_shift_reg_handler 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, low order count already in latch after init lda #0 sta kb::KB_IO + IO::T2CH rts .endproc ;;******************************************************************************** ;; @function Read the last 3 bits after after timer 2 is up ;; @modifies: A ;; @details ;; - read shift register ;; - disable timer 2 interrupts ;; - enable shift register interrupts ;; - reset shift register ;;******************************************************************************** .proc irq_timer_handler 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 ; reset SR ; disabling shifting in acr seems necessary to reset - otherwise ; it continues counting and interrupts after the first 5 bits of the next keypress lda #(IO::ACR::SR_SIN_PHIE | IO::ACR::T2_IRQ_LOAD) trb kb::KB_IO + IO::ACR tsb kb::KB_IO + IO::ACR stz kb::KB_IO + IO::SR ; enable shift register interrupts lda #(IO::IRQ::IRQ | IO::IRQ::SR) sta kb::KB_IO + IO::IER lda key_read+1 ror ror ror lda key_read ; not affecting carry rol ; rotate carry into byte, rotate startbit into carry Reverse A sta scancode rts .endproc .rodata .align 256 CHARS_NOMOD: .byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00^\x00" .byte "\x00\x00\x00\x00\x00q1\x00\x00\x00ysaw2\x00" .byte "\x00cxde43\x00\x00 vftr5\x00" .byte "\x00nbhgz6\x00\x00\x00mju78\x00" .byte "\x00,kio09\x00\x00.-l\xEFp\xE2\x00" .byte "\x00\x00\xE1\x00\xF5`\x00\x00\x00\x00\x00\x00\x00#\x00\x00" .byte "\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" .byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" .align 256 CHARS_MODSHIFT: .byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xDF\x00" .byte "\x00\x00\x00\x00\x00Q!\x00\x00\x00YSAW\"\x00" .byte "\x00CXDE$\xED\x00\x00 VFTR%\x00" .byte "\x00NBHGZ&\x00\x00\x00MJU/(\x00" .byte "\x00;KIO=)\x00\x00:_L\xEFP\xE2\x00" .byte "\x00\x00\xE1\x00\xF5`\x00\x00\x00\x00\x00\x00\x00'\x00\x00" .byte "\x00>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" .byte "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"