;******************************************************************************** ; @module keypad4x4 ; @type driver ; @device 4x4 Matrix Keypad ; @details ; The LCD must be connected to a W65C22N Interface Chip: ; - IO.RA0-7 -> ; @requires KP_IO: Base Address of IO Chip ; @depends IO-W65C22N ;******************************************************************************** .ifndef INCLUDE_KEYPAD INCLUDE_KEYPAD = 1 .ifndef KP_IO .fatal "KP_IO is not defined: set it to the base address of the IO chip of the Keypad" .endif .zeropage _KP_COLUMN: .res 1 ; for storing stuff _KP_DEBUG_VAL: .res 1 ; for storing the last char DEBUG .bss ; reserve space or ringbuffer KP_BUF_SIZE = 10 RBUF_MEM_START: .res KP_BUF_SIZE RBUF_MEM_END = RBUF_MEM_START + KP_BUF_SIZE - 1 .define RBUF_NAME "keypad" .include "buffer.s65" .code .proc kp_init ; todo remove later and test lda #$ff sta KP_IO+IO::DDRA stz KP_IO+IO::RA ; INIT KEYPAD ; todo: use masks lda #%11110000; KP_IO+IO::RA 0-3 output sta KP_IO+IO::DDRA ; output 0, key press will pull input pin low stz KP_IO+IO::RA stz KP_IO+IO::ACR ; lda #%00010000 ; set CA1 to interrupt on pos. edge ; todo: use masks lda #IO::PCR::CA1_IP_AE sta KP_IO+IO::PCR jsr rb_keypad_init ; init keybuffer lda #(IO::IRQ::IRQ | IO::IRQ::CA1) ; enable interrupt for CA1 on KP_IO sta KP_IO+IO::IER rts .endproc ;******************************************************************************** ; @function Read which key is pressed on the keypad ; @details ; Checks which key is pressed and stores it in the keybuffer ; The value stored in the keybuffer is the offset which must be added to ; kp_VALUES to retrieve the key that was pressed ;******************************************************************************** .proc kp_read_on_irq ; test each "row" and check which column is 1 ; TODO dont check every column if the value has been found lda #%11100000 ldx #$00 jsr @kp_read_column lda #%11010000 ldx #$04 jsr @kp_read_column lda #%10110000 ldx #$08 jsr @kp_read_column lda #%01110000 ldx #$0c jsr @kp_read_column stz KP_IO+IO::RA lda KP_IO+IO::RA ; clear interrupt flag again beceause it might be set again through the above tests rts @kp_read_column: sta KP_IO+IO::RA lda KP_IO+IO::RA sta _KP_COLUMN ; store result in zeropage so that bbr can be used bbr0 _KP_COLUMN,@kp_write ; row 1 inx bbr1 _KP_COLUMN,@kp_write ; row 3 inx bbr2 _KP_COLUMN,@kp_write ; row 2 inx bbr3 _KP_COLUMN,@kp_write ; row 4 rts @kp_write: lda _KP_VALUES,x ; TODO use ringbuffer sta _KP_DEBUG_VAL jsr rb_keypad_write rts .endproc .rodata _KP_VALUES: .byte "174*" .byte "2850" .byte "396#" .byte "ACBD" ; keypad conencted so that ; row 1 = PA0 ; row 2 = PA2 ; row 3 = PA1 ; row 4 = PA3 .endif