diff --git a/libsrc/osic1p/cgetc.s b/libsrc/osic1p/cgetc.s index d99f69a72..56209ff6b 100644 --- a/libsrc/osic1p/cgetc.s +++ b/libsrc/osic1p/cgetc.s @@ -2,236 +2,40 @@ ; char cgetc (void); ; - .constructor initcgetc .export _cgetc - .export inputc .import cursor + .import _kbhit .include "osic1p.inc" .include "extzp.inc" .include "zeropage.inc" -; Internal state that needs to be preserved across calls. -; These variables are named after the original memory locations used by the -; 65V PROM MONITOR, until the actual meaning is determined. -.segment "EXTZP" : zeropage - -KB0213: .res 1 -KB0214: .res 1 -KB0215: .res 1 -KB0216: .res 1 - -; Initialize one-character buffer that is filled by kbhit() - .segment "ONCE" -initcgetc: - lda #$00 - sta CHARBUF ; No character in buffer initially - - sta KB0213 ; Initialize keyboard state - sta KB0214 - sta KB0215 - sta KB0216 - - rts - -; Input routine from 65V PROM MONITOR, show cursor if enabled +; Input routine, show cursor if enabled .code _cgetc: - lda CHARBUF ; character in buffer available? - beq nobuffer - tax ; save character in X - lda #$00 - sta CHARBUF ; empty buffer - beq restorex ; restore X and return -nobuffer: + ldx CHARBUF ; character in buffer available? + bne done lda cursor ; show cursor? beq nocursor ldy CURS_X lda (SCREEN_PTR),y ; fetch current character sta tmp1 ; save it lda #$A1 ; full white square - sta (SCREEN_PTR),y ; store at cursor position + sta (SCREEN_PTR),y ; store at cursor position^ + nocursor: - jsr inputc ; get input character in A - ldx cursor + jsr _kbhit ; get input character in A + tax ; save A in X, set flags + beq nocursor ; until a key is actually pressed + lda cursor beq done ; was cursor on? - tax ; save A in X lda tmp1 ; fetch saved character ldy CURS_X sta (SCREEN_PTR),y ; store at cursor position -restorex: - txa ; restore saved character from X done: + lda #$00 + sta CHARBUF ; empty buffer + txa ; restore saved character from X ldx #$00 ; high byte of int return value rts - -; Routine to get character from keyboard and return it in A. -; Based on the OSI ROM routine at $FD00 but uses different -; storage locations to avoid corrupting CC65 run-time code. - -inputc: txa ; Save X on stack. - pha - tya ; Save Y on stack. - pha -LFD04: lda #$80 ; Bit mask for initial keyboard row -LFD06: jsr LFCBE ; Write keyboard row - jsr LFCC6 ; Read keyboard column - bne LFD13 ; Branch if a key in this column was pressed - lsr a ; Otherwise shift mask to next row - bne LFD06 ; If not done yet, check next row - beq LFD3A ; Branch if last row reached and no key pressed -LFD13: lsr a ; Have a key press. Shift LSB into carry - bcc LFD1F ; Branch if no key pressed in column 0 - txa ; Key pressed in row zero. Get the column data - and #$20 ; Mask only the bit for as it is the only key in row zero that returns key press - beq LFD3A ; Branch if was not the key - lda #$1B ; Set character to - bne LFD50 ; Do more processing -LFD1F: jsr LFE86 ; Shift to find bit that is set (in Y) - tya ; Get bit - sta KB0215 ; Save it - asl a ; Multiply by 7 by shifting left three times (X8)... - asl a - asl a - sec ; ...then subtracting one - sbc KB0215 - sta KB0215 ; Save value*7 for later lookup in table - txa ; Get the keyboard column - lsr a ; Shift out bit zero (only key there is ) - asl a ; And shift back - jsr LFE86 ; Shift to find bit that is set (in Y) - beq LFD47 ; Branch if no keys pressed - lda #$00 -LFD3A: sta KB0216 ; Save state of and shift keys -LFD3D: sta KB0213 - lda #$02 ; Count used for key debouncing - sta KB0214 - bne LFD04 ; Go back and scan keyboard again -LFD47: clc - tya ; Get bit number of pressed key - adc KB0215 ; Add previously calculated offset for keyboard row*7 - tay - lda LFF3B,y ; Read ASCII code for key from table -LFD50: cmp KB0213 ; Debounce - same as last key scan? - bne LFD3D ; If not, try again - dec KB0214 ; Decrement debounce counter - beq LFD5F ; Branch if done debouncing - jsr LFCDF ; Wait for short delay to debounce keyboard - beq LFD04 ; Go back and scan keyboard. -LFD5F: ldx #$64 ; Was key down? - cmp KB0216 - bne LFD68 ; Branch if not - ldx #$0F -LFD68: stx KB0214 - sta KB0216 - cmp #$21 - bmi LFDD0 ; Done, return key - cmp #$5F - beq LFDD0 ; Done, return key - lda #$01 - jsr LFCBE ; Write keyboard row - jsr LFCCF ; Read keyboard column - sta KB0215 - and #$01 - tax - lda KB0215 - and #$06 - bne LFDA2 - bit KB0213 - bvc LFDBB - txa - eor #$01 - and #$01 - beq LFDBB - lda #$20 - bit KB0215 - bvc LFDC3 - lda #$C0 - bne LFDC3 -LFDA2: bit KB0213 - bvc LFDAA - txa - beq LFDBB -LFDAA: ldy KB0213 - cpy #$31 - bcc LFDB9 - cpy #$3C - bcs LFDB9 - lda #$F0 - bne LFDBB -LFDB9: lda #$10 -LFDBB: bit KB0215 - bvc LFDC3 - clc - adc #$C0 -LFDC3: clc - adc KB0213 - and #$7F - bit KB0215 - bpl LFDD0 - ora #$80 -LFDD0: sta KB0215 ; Save pressed key - pla - tay ; Restore saved Y value - pla - tax ; Restore saved Y value - lda KB0215 ; Get pressed key and return in A - rts - -; Write keyboard row with value in A. -; Invert the bits before writing. -; Returns original value of A. - -LFCBE: eor #$FF - sta KBD - eor #$FF - rts - -; Read keyboard column and return in X. -; Sets Z flag if no keys were pressed. -; Saves current value of A. - -LFCC6: pha ; Save A - jsr LFCCF ; Read keyboard column - tax ; Save in X - pla ; Restore A - dex ; Decrement and then increment to - inx ; preserve value of X but set flags - rts - -; Read keyboard column. -; Invert the bits (pressed key(s) will show up as ones). - -LFCCF: lda KBD ; Read keyboard hardware - eor #$FF ; Invert the bits - rts - -; Short fixed delay routine. - -LFCDF: ldy #$10 -LFCE1: ldx #$40 -LFCE3: dex - bne LFCE3 - dey - bne LFCE1 - rts - -; Shift A left until we find a 1 in the most significant bit. -; Return the bit number in Y. - -LFE86: ldy #$08 -LFE88: dey - asl a - bcc LFE88 - rts - -; Lookup table of keyboard keys for each scan row. -LFF3B: .byte $BD - .byte 'P', ';', '/', ' ', 'Z', 'A', 'Q' - .byte ',', 'M', 'N', 'B', 'V', 'C', 'X' - .byte 'K', 'J', 'H', 'G', 'F', 'D', 'S' - .byte 'I', 'U', 'Y', 'T', 'R', 'E', 'W' - .byte $00, $00, $0D, $0A, 'O', 'L', '.' - .byte $00, '_', '-', ':', '0', '9', '8' - .byte '7', '6', '5', '4', '3', '2', '1' diff --git a/libsrc/osic1p/kbhit.s b/libsrc/osic1p/kbhit.s index 1ecfa1041..db28854f5 100644 --- a/libsrc/osic1p/kbhit.s +++ b/libsrc/osic1p/kbhit.s @@ -10,39 +10,197 @@ ; in tmp1 and that is set to zero after the first round. ; + .constructor initkbhit .export _kbhit - .import inputc .include "osic1p.inc" .include "extzp.inc" .include "zeropage.inc" -_kbhit: - lda #%11011111 ; Mask for only checking the column for the - sta tmp1 ; ESC key in the first keyboard row. +; Internal state that needs to be preserved across calls. +.segment "EXTZP" : zeropage + +LASTSCAN: .res 1 ; Result of previous keyboard scan +DBNCCNT: .res 1 ; Debounce counter +KBDTMP: .res 1 ; Temporary values +CTRLSHIFT: .res 1 ; State of CTRL and SHIFT keys + +; Initialize one-character buffer that is filled by kbhit() + .segment "ONCE" +initkbhit: + lda #$00 + sta CHARBUF ; No character in buffer initially + + sta LASTSCAN ; Initialize keyboard state + sta DBNCCNT + sta KBDTMP + sta CTRLSHIFT - lda #%11111110 ; Mask for first keyboard row -scan: - sta KBD ; Select keyboard row - tax ; Save A - lda KBD ; Read keyboard columns - ora tmp1 ; Mask out uninteresting keys (only relevant in - ; first row) - cmp #$FF ; No keys pressed? - bne keypressed - lda #$00 ; For remaining rows no keys masked - sta tmp1 - txa ; Restore A - sec ; Want to shift in ones - rol a ; Rotate row select to next bit position - cmp #$FF ; Done? - bne scan ; If not, continue - lda #$00 ; Return false - tax ; High byte of return is also zero - sta CHARBUF ; No character in buffer rts -keypressed: - jsr inputc ; Get input character in A - sta CHARBUF ; Save in buffer + +; Routine to get character from keyboard and return it in A. +; Based on the OSI ROM routine at $FD00 but uses different +; storage locations to avoid corrupting CC65 run-time code. + +_kbhit: lda CHARBUF ; Check for previously saved character + beq LFD05 ldx #$00 ; High byte of return is always zero - lda #$01 ; Return true + rts ; A contains non-zero character code meaning true +LFD05: lda #$80 ; Bit mask for initial keyboard row +LFD06: jsr LFCBE ; Write keyboard row + jsr LFCC6 ; Read keyboard column + bne LFD13 ; Branch if a key in this column was pressed + lsr a ; Otherwise shift mask to next row + bne LFD06 ; If not done yet, check next row + beq LFD3A ; Branch if last row reached and no key pressed +LFD13: lsr a ; Have a key press. Shift LSB into carry + bcc LFD1F ; Branch if no key pressed in column 0 + txa ; Key pressed in row zero. Get the column data + and #$20 ; Mask only the bit for as it is the only key in row zero that returns key press + beq LFD3A ; Branch if was not the key + lda #$1B ; Set character to + bne LFD50 ; Do more processing +LFD1F: jsr LFE86 ; Shift to find bit that is set (in Y) + tya ; Get bit + sta KBDTMP ; Save it + asl a ; Multiply by 7 by shifting left three times (X8)... + asl a + asl a + sec ; ...then subtracting one + sbc KBDTMP + sta KBDTMP ; Save value*7 for later lookup in table + txa ; Get the keyboard column + lsr a ; Shift out bit zero (only key there is ) + asl a ; And shift back + jsr LFE86 ; Shift to find bit that is set (in Y) + beq LFD47 ; Branch if no keys pressed STM: IS THIS CORRECT? + lda #$00 +LFD3A: sta CTRLSHIFT ; Save state of and shift keys +LFD3D: sta LASTSCAN + lda #$02 ; Count used for key debouncing + sta DBNCCNT + ldx #$00 ; High byte of return is always zero + lda #$00 ; Return false rts +LFD47: clc + tya ; Get bit number of pressed key + adc KBDTMP ; Add previously calculated offset for keyboard row*7 + tay + lda LFF3B,y ; Read ASCII code for key from table +LFD50: cmp LASTSCAN ; Debounce - same as last key scan? + bne LFD3D ; If not, try again + dec DBNCCNT ; Decrement debounce counter + beq LFD5F ; Branch if done debouncing + jsr LFCDF ; Wait for short delay to debounce keyboard + beq _kbhit ; Go back and scan keyboard. +LFD5F: ldx #$64 ; Was key down? + cmp CTRLSHIFT + bne LFD68 ; Branch if not + ldx #$0F +LFD68: stx DBNCCNT + sta CTRLSHIFT + cmp #$21 + bmi LFDD0 ; Done, return key + cmp #$5F + beq LFDD0 ; Done, return key + lda #$01 + jsr LFCBE ; Write keyboard row + jsr LFCCF ; Read keyboard column + sta KBDTMP + and #$01 + tax + lda KBDTMP + and #$06 + bne LFDA2 + bit LASTSCAN + bvc LFDBB + txa + eor #$01 + and #$01 + beq LFDBB + lda #$20 + bit KBDTMP + bvc LFDC3 + lda #$C0 + bne LFDC3 +LFDA2: bit LASTSCAN + bvc LFDAA + txa + beq LFDBB +LFDAA: ldy LASTSCAN + cpy #$31 + bcc LFDB9 + cpy #$3C + bcs LFDB9 + lda #$F0 + bne LFDBB +LFDB9: lda #$10 +LFDBB: bit KBDTMP + bvc LFDC3 + clc + adc #$C0 +LFDC3: clc + adc LASTSCAN + and #$7F + bit KBDTMP + bpl LFDD0 + ora #$80 +LFDD0: sta KBDTMP ; Save pressed key and return in A + sta CHARBUF + rts + +; Write keyboard row with value in A. +; Invert the bits before writing. +; Returns original value of A. + +LFCBE: eor #$FF + sta KBD + eor #$FF + rts + +; Read keyboard column and return in X. +; Sets Z flag if no keys were pressed. +; Saves current value of A. + +LFCC6: pha ; Save A + jsr LFCCF ; Read keyboard column + tax ; Save in X + pla ; Restore A + dex ; Decrement and then increment to + inx ; preserve value of X but set flags + rts + +; Read keyboard column. +; Invert the bits (pressed key(s) will show up as ones). + +LFCCF: lda KBD ; Read keyboard hardware + eor #$FF ; Invert the bits + rts + +; Short fixed delay routine. + +LFCDF: ldy #$10 +LFCE1: ldx #$40 +LFCE3: dex + bne LFCE3 + dey + bne LFCE1 + rts + +; Shift A left until we find a 1 in the most significant bit. +; Return the bit number in Y. + +LFE86: ldy #$08 +LFE88: dey + asl a + bcc LFE88 + rts + +; Lookup table of keyboard keys for each scan row. +LFF3B: .byte $BD + .byte 'P', ';', '/', ' ', 'Z', 'A', 'Q' + .byte ',', 'M', 'N', 'B', 'V', 'C', 'X' + .byte 'K', 'J', 'H', 'G', 'F', 'D', 'S' + .byte 'I', 'U', 'Y', 'T', 'R', 'E', 'W' + .byte $00, $00, $0D, $0A, 'O', 'L', '.' + .byte $00, '_', '-', ':', '0', '9', '8' + .byte '7', '6', '5', '4', '3', '2', '1'