Jump to content
  • 0

Keyboard scan ...



Hello everyone,


I am in search for an easy method in assembly language to scan if a key is pressed on the X16 keyboard. I've been peering into the emulator source code and also I've been looking into the C64 best practices.

I have found out that it's not so easy to get this method answered through self research and discovery/dedection. So, I've decided to ask here the forum ...

Let's start with my main question!

What is the main chip that is connected to the keyboard and detects the keyboard presses? I see in the ROM two methods implemented!

The old C64 method and a new PS/2 keyboard method!


Method 1: Is it the old C64 type of keyboard driver using the CIA chipset on ports $dc00

or ...

Method 2: Is it through the new PS/2 keyboard through VIA chipset on the X16 using the via # 2 on ports $9f70, $9f71, $9f72 ...

I've tried both methods, and non of them seem to work ...

Let me explain each method that I tried to apply ... Note that the code is not optimal, it's trial and error code trying to figure our things ...


Method 1 explanation:

// Return true if there's a key waiting, return false if not
unsigned char kbhit(void) {
    // CIA#1 Port A: keyboard matrix columns and joystick #2
    char* const CIA1_PORT_A = 0xdc00;
    // CIA#1 Port B: keyboard matrix rows and joystick #1.
    char* const CIA1_PORT_B = 0xdc01;
    *CIA1_PORT_A = 0;
    return ~*CIA1_PORT_B;



Method 2 explanation:

This code I've taken from the X16 emulator ROM kernal code, and I've reworked it to a kickc / kickasm source code.

 This code uses the VIA#2 chip of the X16 as documented, at the addresses, and this logic should fill ps2byte with the scan...

Unfortunately, this does not seem to work and I really don't understand why not...


char ps2byte = 0;

while(!ps2byte) {
    kickasm(uses ps2byte) {{

     jsr ps2_init
     jmp continue1
     .var via2 =$9f70                  //VIA 6522 #2
     .var d2prb    =via2+0
     .var d2pra    =via2+1
     .var d2ddrb   =via2+2
     .var d2ddra   =via2+3

     .var port_ddr  =d2ddrb
     .var port_data =d2prb
     .var bit_data=1              // 6522 IO port data bit mask  (PA0/PB0)
     .var bit_clk =2              // 6522 IO port clock bit mask (PA1/PB1)

     // inhibit PS/2 communication on both ports
         ldx #1 // PA: keyboard
         jsr ps2dis
         dex    // PB: mouse
     ps2dis:   lda port_ddr,x
         ora #bit_clk+bit_data
         sta port_ddr,x // set CLK and DATA as output
         lda port_data,x
         and #$ff - bit_clk // CLK=0
         ora #bit_data // DATA=1
         sta port_data,x
     continue1: nop
   kickasm(uses ps2byte) {{
        jsr ps2_receive_byte
        jmp continue2
        // RECEIVE BYTE
        // out: A: byte (0 = none)
        //      Z: byte available
        //           0: yes
        //           1: no
        //      C:   0: parity OK
        //           1: parity error
     // set input, bus idle
        lda port_ddr,x // set CLK and DATA as input
        and #$ff-bit_clk-bit_data
        sta port_ddr,x // -> bus is idle, keyboard can start sending

        lda #bit_clk+bit_data
        //ldy #10 * mhz
        ldy #10 * 8
    // :   dey
     loop: dey
        beq lc08c
        bit port_data,x
    //     bne :- // wait for CLK=0 and DATA=0 (start bit)
        bne loop // wait for CLK=0 and DATA=0 (start bit)

        lda #bit_clk
     lc044:    bit port_data,x // wait for CLK=1 (not ready)
        beq lc044
        ldy #9 // 9 bits including parity
     lc04a:    bit port_data,x
        bne lc04a // wait for CLK=0 (ready)
        lda port_data,x
        and #bit_data
        cmp #bit_data
        ror ps2byte // save bit
        lda #bit_clk
     lc058:    bit port_data,x
        beq lc058 // wait for CLK=1 (not ready)
        bne lc04a
        rol ps2byte // get parity bit into C
     lc061:    bit port_data,x
        bne lc061 // wait for CLK=0 (ready)
     lc065:    bit port_data,x
        beq lc065 // wait for CLK=1 (not ready)
     lc069:    jsr ps2dis
        lda ps2byte
        php // save parity
     //lc07c:  lsr a // calculate parity
     lc07c:    lsr // calculate parity
        bcc lc080
     lc080:    cmp #0
        bne lc07c
        plp // transmitted parity
        adc #1
    //     lsr a // C=0: parity OK
        lsr // C=0: parity OK
        lda ps2byte
        ldy #1 // Z=0

     lc08c:    jsr ps2dis
        lda #0 // Z=1
        continue2: nop
    printf( "ps2byte = %x\n", ps2byte );


Who can help here?



Link to comment
Share on other sites

1 answer to this question

Recommended Posts

  • 0

I found out by looking into the cc65 assembly code of the cx16 section, that RAM bank 0 has a vector that contains the count of key presses waiting, which is stored in address $a00a.

So, the following code works:

// Return true if there's a key waiting, return false if not
unsigned char kbhit(void) {

    char keys = 0;
    char* keysptr = &keys;

    kickasm(uses keysptr) {{

        jsr _kbhit
        jmp continue1
        .var via1 = $9f60                  //VIA#1
        .var d1pra = via1+1

        ldy     d1pra       // The count of keys pressed is stored in RAM bank 0.
        stz     d1pra       // Set d1pra to zero to access RAM bank 0.
        lda     $A00A       // Get number of characters from this address in the ROM of the CX16 (ROM 38).
        sta     keys
        sty     d1pra       // Set d1pra to previous value.
        rts                     // ... state matters)
    continue1: nop

    return keys;

Thanks to Greg King for his contribution! cc65/kbhit.s at master · cc65/cc65 (github.com)


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Create New...

Important Information

Please review our Terms of Use