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
ps2_init:
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
rts
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
//****************************************
ps2_receive_byte:
// 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)
dey
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
iny
lc080: cmp #0
bne lc07c
tya
plp // transmitted parity
adc #1
// lsr a // C=0: parity OK
lsr // C=0: parity OK
lda ps2byte
ldy #1 // Z=0
rts
lc08c: jsr ps2dis
clc
lda #0 // Z=1
rts
continue2: nop
}}
printf( "ps2byte = %x\n", ps2byte );
}
Who can help here?
Sven