Improved C64 Keyboard Reader

JMP $FCE2
MarcWalters
Member
Member
Posts: 55
Joined: Wed Jun 11, 2014 2:33 pm
Location: Lake Macquarie, NSW, Australia
Contact:

Improved C64 Keyboard Reader

Post by MarcWalters »

This is an improved keyboard reader.
It's main features are:
- slightly shorter
- about 20% faster
- not dependent on interrupts or vectors
- can be used with the Kernal ROM switched out
- Uses a keyboard buffer
- retains all the "features" of the original Kernal ROM routine

It's in C64 Prg Studio format.

To use:
1) Initialise with Keyb_Init at Application Start
Then, in a loop:
2) Call ReadKeyb to capture keypresses
3) Call GetKey to load the accumulator with a key from the keyboard buffer. On exit, Carry is set if the buffer was empty.

For example:

Code: Select all

TestKeyboard
         jsr Keyb_Init

@Loop    lda #$FF
@Raster  cmp $D012
	 bne @Raster

         jsr ReadKeyb
         jsr GetKey
         bcs @Skip
	
	 sta $0400
@Skip    jmp @Loop
Keyboard routines:

Code: Select all

KeyMapVec  word KeyMap1, KeyMap2, KeyMap3, KeyMap4

; Unshifted       
KeyMap1  byte $14, $0D, $1D, $88, $85, $86, $87, $11
         byte $33, $57, $41, $34, $5A, $53, $45, $01
         byte $35, $52, $44, $36, $43, $46, $54, $58
         byte $37, $59, $47, $38, $42, $48, $55, $56
         byte $39, $49, $4A, $30, $4D, $4B, $4F, $4E
         byte $2B, $50, $4C, $2D, $2E, $3A, $40, $2C
         byte $5C, $2A, $3B, $13, $01, $3D, $5E, $2F
         byte $31, $5F, $04, $32, $20, $02, $51, $03
         byte $FF

; Shifted
KeyMap2  byte $94, $8D, $9D, $8C, $89, $8A, $8B, $91
         byte $23, $D7, $C1, $24, $DA, $D3, $C5, $01
         byte $25, $D2, $C4, $26, $C3, $C6, $D4, $D8
         byte $27, $D9, $C7, $28, $C2, $C8, $D5, $D6
         byte $29, $C9, $CA, $30, $CD, $CB, $CF, $CE
         byte $DB, $D0, $CC, $DD, $3E, $5B, $BA, $3C
         byte $A9, $C0, $5D, $9e, $01, $3D, $DE, $3F
         byte $21, $5F, $04, $22, $A0, $02, $D1, $83
         byte $FF

; Commodore
KeyMap3
         byte $94, $8D, $9D, $8C, $89, $8A, $8B, $91
         byte $96, $B3, $B0, $97, $AD, $AE, $B1, $01
         byte $98, $B2, $AC, $99, $BC, $BB, $A3, $BD
         byte $9A, $B7, $A5, $9B, $BF, $B4, $B8, $BE
         byte $29, $A2, $B5, $30, $A7, $A1, $B9, $AA
         byte $A6, $AF, $B6, $DC, $3E, $5B, $A4, $3C
         byte $A8, $DF, $5D, $93, $01, $3D, $DE, $3F
         byte $81, $5F, $04, $95, $A0, $02, $AB, $83
         byte $FF

; Control
KeyMap4
         byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
         byte $1C, $17, $01, $9F, $1A, $13, $05, $FF
         byte $9C, $12, $04, $1E, $03, $06, $14, $18
         byte $1F, $19, $07, $9E, $02, $08, $15, $16
         byte $12, $09, $0A, $92, $0D, $0B, $0F, $0E
         byte $FF, $10, $0C, $FF, $FF, $1B, $00, $FF
         byte $1C, $FF, $1D, $FF, $FF, $1F, $1E, $FF
         byte $90, $06, $FF, $05, $FF, $FF, $11, $FF
         byte $FF

CIA1_KeybWrite    = $DC00
CIA1_KeybRead     = $DC01

cSYS_DelayValue   = 32
cKeybW_Row1       = $FE

KeyR              byte 0

SYS_Keyd          bytes 0 * 10 ; keyboard buffer
SYS_Ndx           byte 0   ; Count of chars in keyboard buffer
SYS_Xmax          byte 10  ; Maximum number of chars in the keyboard buffer

SYS_Shflag        byte 0   ; Shift collection (Shift=1, Commodore = 2, Control = 4)
SYS_Sfdx          byte 0   ; Previous key pressed. Keyboard Matrix Coordinate. Same value as SYS_Lstx.
SYS_Lstx          byte 0   ; Newest key Pressed (not shifts). $40 = no key.
SYS_Delay         byte 0   ; Repeat countdown. 16 to 0, so 0.25 second.
SYS_Kount         byte 0
SYS_Lstshf        byte 0

Keyb_Init
         lda #64
         sta SYS_Lstx
         sta SYS_Sfdx

         lda #cSYS_DelayValue
         sta SYS_Delay

         lda #6
         sta SYS_Kount

         lda #0
         sta SYS_Shflag
         sta SYS_Lstshf

         sta SYS_Ndx
         rts

ReadKeyb
         lda #<KeyMap1
         sta @SMC_Vec + 1
         lda #>KeyMap1
         sta @SMC_Vec + 2
         
         ; Clear Shift Flag
         lda #$40
         sta SYS_Sfdx

         lda #0
         sta SYS_Shflag

         sta CIA1_KeybWrite
         ldx CIA1_KeybRead
         cpx #$FF
         beq @Cleanup

         ldy #$00

         lda #7
         sta KeyR

         lda #cKeybW_Row1
         sta @SMC_Row + 1
@SMC_Row lda #0

         sta CIA1_KeybWrite

@Loop_Debounce
         lda CIA1_KeybRead
         cmp CIA1_KeybRead
         bne @Loop_Debounce

         ldx #7
@Loop_Col lsr
         bcs  @NextKey
         sta @SMC_A + 1

@SMC_Vec lda $FFFF,Y

         ; If <4 then is Stop or a Shift Key
         cmp #$05 
         bcs @NotShift ; Not Shift

         cmp #$03 
         beq @NotShift ; Stop Key
         
         ; Accumulate shift key types (SHIFT=1, COMM=2, CTRL=4)
         ora SYS_Shflag
         sta SYS_Shflag
         bpl @SMC_A

@NotShift sty SYS_Sfdx

@SMC_A   lda #0

@NextKey iny
         dex
         bpl @Loop_Col

         sec
         rol @SMC_Row + 1
         dec KeyR
         bpl @SMC_Row

         jmp @ProcKeyImg

; Handles the key repeat
@Process ldy SYS_Sfdx
@SMC_Key lda $FFFF,Y
         tax
         cpy SYS_Lstx
         beq @SameKey

         ldy #cSYS_DelayValue
         sty SYS_Delay     ; Repeat delay counter
         bne @Cleanup
         
@SameKey and #$7F
         ldy SYS_Delay
         beq @EndDelay
         dec SYS_Delay
         bne @Exit

@EndDelay dec SYS_Kount
         bne @Exit

         ldy #$04
         sty SYS_Kount
         ldy SYS_Ndx
         dey
         bpl @Exit

; Updates the previous key and shift storage
@Cleanup ldy SYS_Sfdx
         sty SYS_Lstx
         ldy SYS_Shflag
         sty SYS_Lstshf

         cpx #$FF
         beq @Exit
         txa
         ldx SYS_Ndx
         cpx SYS_Xmax
         bcs @Exit

         sta SYS_Keyd,X
         inx
         stx SYS_Ndx

@Exit    lda #$7F
         sta CIA1_KeybWrite
         rts

@ProcKeyImg 
         lda SYS_Shflag
         cmp #$03 ; C= + SHIFT
         bne @SetDecodeTable
         cmp SYS_Lstshf
         beq @Exit

@SetDecodeTable
         asl
         cmp #8   ; CONTROL
         bcc @Cont
         lda #$06
@Cont    tax
         lda KeyMapVec,X
         sta @SMC_Key + 1
         lda KeyMapVec + 1,X
         sta @SMC_Key + 2
         jmp @Process

; --------------------------
GetKey   lda SYS_Ndx
         bne @IsKey

@NoKey   lda #255 ; Null
         sec
         rts

@IsKey   ldy SYS_Keyd
         ldx #0
@Loop    lda SYS_Keyd + 1,X
         sta SYS_Keyd,X
         inx
         cpx SYS_Ndx
         bne @Loop 
         dec SYS_Ndx
         tya
         clc
         rts


xlar54
Member
Member
Posts: 1
Joined: Thu Dec 20, 2018 4:38 pm
Contact:

Re: Improved C64 Keyboard Reader

Post by xlar54 »

nice!
reeca
Member
Member
Posts: 1
Joined: Tue Apr 16, 2019 8:17 am
Contact:

Re: Improved C64 Keyboard Reader

Post by reeca »

Hi,

Has anyone else actually tried this? I'm getting strange characters appear : Number keys work fine but all others give various non alpha screen characters.

Regards
Reeca
MarcWalters
Member
Member
Posts: 55
Joined: Wed Jun 11, 2014 2:33 pm
Location: Lake Macquarie, NSW, Australia
Contact:

Re: Improved C64 Keyboard Reader

Post by MarcWalters »

It works correctly.

The test routine provided outputs the PETSCII character straight to the top left corner of the text screen without conversion to the equivalent screen code. The screencode for a PETSCII unshifted "A" is the spade symbol, so if you run it and press "A" then that's what appears.
Post Reply Previous topicNext topic

Who is online

Users browsing this forum: No registered users and 7 guests