diff --git a/system/buffer.s65 b/system/buffer.s65 new file mode 100644 index 0000000..208cc53 --- /dev/null +++ b/system/buffer.s65 @@ -0,0 +1,97 @@ +;******************************************************************************** +; @module ringbuffer +; @type utility +; @details +; Size of the ringbuffer is RBUF_MEM_END - RBUF_MEM_START - 2, since two bytes +; are used by the read and write pointer +; The RBUF_NAME variable must be defined, the functions will then be exported +; as rb__ where = init, read or write +; @requires +; RBUF_MEM_START: Start address of ringbuffer memory space +; RBUF_MEM_END: End address of ringbuffer memory space +; RBUF_NAME: Name of the ringbuffer +;******************************************************************************** + +.ifndef RBUF_MEM_START + .fatal "RBUF_MEM_START not defined" +.endif +.ifndef RBUF_MEM_END + .fatal "RBUF_MEM_END not defined" +.endif + +; can not detect if RBUF_NAME is defined, if it is not you will get +; "String constant expected" Error on the line below +.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 + + +;******************************************************************************** +; @function Initialize the buffer +;******************************************************************************** +.ident(.concat(_RBUF_NAME, "_init")): +.scope + stz RB_WRITE + stz RB_READ + rts +.endscope + +;******************************************************************************** +; @function Read a value from the buffer +; @details +; If there is no value to be read, the Pz will be set +; @returns A: value +; @modifies: A, X +;******************************************************************************** +.ident(.concat(_RBUF_NAME, "_read")): +.scope + ldx RB_READ + cpx RB_WRITE + beq @rb_read_rts ; if buffer empty + lda RB_START,x + inx ; increment RB_READ pointer + cpx #RB_LENGTH + beq @rb_read_jump + stx RB_READ +@rb_read_rts: + rts +@rb_read_jump: + stz RB_READ + ; make sure Pz is not set + ldx #$01 + rts +.endscope + +;******************************************************************************** +; @function Write a value to the buffer +; @param A: value to store +; @modifies: X +;******************************************************************************** +.ident(.concat(_RBUF_NAME, "_write")): +.scope + ; lda kp_VALUES, x ; load the char in a + ldx RB_WRITE + sta RB_START,x + inx ; increment write pointer + cpx #RB_LENGTH + beq @rb_jump_write + stx RB_WRITE + rts +@rb_jump_write: ; when the end of the buffer is reached, the next keys go to the start again + stz RB_WRITE + rts +.endscope + +.undefine _RBUF_NAME +.undefine RBUF_NAME + + diff --git a/system/keypad.s65 b/system/keypad.s65 index 240e0b8..d6400d0 100644 --- a/system/keypad.s65 +++ b/system/keypad.s65 @@ -6,112 +6,95 @@ ; The LCD must be connected to a W65C22N Interface Chip: ; - IO.RB0-7 -> ; @requires KP_IO: Base Address of IO Chip -; @depends IO-W65C22N +; @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 -;******************************************************************************** -; Keypad Buffer from $202 to $2ff -;******************************************************************************** -KB_VAR = $00 -KB_WRITE = $200 ; write pointer, relative to KB_WRITE -KB_READ = $201 ; read ponter, relative to KB_START -KB_START = $202 -KB_LENGTH = $fd -kb_init: - stz KB_WRITE - stz KB_READ - ; write null to entire buffer - ldx #$00 -@kb_init_loop: - stz KB_START,x - inx - cpx #KB_LENGTH - bne @kb_init_loop - rts +RBUF_MEM_START = $200 +RBUF_MEM_END = $2ff +.define RBUF_NAME "keypad" +.include "buffer.s65" -; read from keybuffer, if empty null will be read -kb_read: - ldx KB_READ - lda KB_START,x - beq @kb_read_rts ; if a buffer is null, dont increment KB_READ - stz KB_START,x ; set buffer location to null - inx ; increment KB_READ pointer - cpx #KB_LENGTH - beq @kb_read_jump - stx KB_READ -@kb_read_rts: - rts -@kb_read_jump: - stz KB_READ - rts +KB_VAR = $05 +KB_LAST = $06 -; write to keybuffer -_kb_write: - lda kp_VALUES, x ; load the char in a - ldx KB_WRITE - sta KB_START,x - inx ; increment KB_WRITE pointer - cpx #KB_LENGTH - beq @kb_jump_write - stx KB_WRITE - rts -@kb_jump_write: ; when the end of the buffer is reached, the next keys go to the start again - stz KB_WRITE - rts +.proc kp_init + ; todo remove + stz KB_LAST + ; todo remove later + lda #$ff + sta KP_IO+IO_DDRB + stz KP_IO+IO_RB -kp_init: ; INIT KEYPAD lda #%00001111; KP_IO+IO_RB 0-3 output sta KP_IO+IO_DDRB stz KP_IO+IO_RB ; KP_IO+IO_RB 4-7 1 so keypad press can be detected stz KP_IO+IO_ACR - lda #%10010000 ; enable interrupt for CB1 on KP_IO+IO_IO - sta KP_IO+IO_IER - lda #%00010000 ; set CB1 to interrupt on pos. edge + ; lda #%00010000 ; set CB1 to interrupt on pos. edge + lda #IO_PCR_CB1_IP_AE sta KP_IO+IO_PCR - jsr kb_init ; init keybuffer + jsr rb_keypad_init ; init keybuffer + lda #%10010000 ; enable interrupt for CB1 on KP_IO + sta KP_IO+IO_IER rts +.endproc ;******************************************************************************** -; Reading the Keypad +; @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 ;******************************************************************************** -kp_read: ; test each "row" and check which column is 1 +.proc kp_read_on_irq + ; test each "row" and check which column is 1 lda #%00001110 ldx #$00 - jsr @kp_read_branch + jsr @kp_read_column lda #%00001101 ldx #$04 - jsr @kp_read_branch + jsr @kp_read_column lda #%00001011 ldx #$08 - jsr @kp_read_branch + jsr @kp_read_column lda #%00000111 ldx #$0c - jsr @kp_read_branch -@kp_read_rts: - stz KP_IO+IO_RB - lda KP_IO+IO_RB ; read to definetly clear the interrupt flag - rts -@kp_read_branch: + jsr @kp_read_column + bra @kp_read_rts +@kp_read_column: sta KP_IO+IO_RB lda KP_IO+IO_RB sta KB_VAR ; store result in zeropage so that bbr can be used - bbr4 KB_VAR,_kb_write + bbr4 KB_VAR,@kp_write inx - bbr5 KB_VAR,_kb_write + bbr5 KB_VAR,@kp_write inx - bbr6 KB_VAR,_kb_write + bbr6 KB_VAR,@kp_write inx - bbr7 KB_VAR,_kb_write + bbr7 KB_VAR,@kp_write rts +@kp_write: + ; temporary: store last keypress in KB_LAST, TODO: remove + lda kp_VALUES,x + sta KB_LAST + txa + jsr rb_keypad_write +@kp_read_rts: + stz KP_IO+IO_RB + ; lda KP_IO+IO_RB ; read to definetly clear the interrupt flag + rts +.endproc + +.segment "RODATA" kp_VALUES: ; TODO change to literal .byte "123A", "456B", "789C", "*0#D"