From 5d923411895f43d802f4aaa1683287189fb01e2a Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Thu, 5 Dec 2024 20:41:03 +0800 Subject: [PATCH] PS2 Interrupt driven keyboard for Duo For keyboard interface on I/O Multi board. Default is disabled. Requires interrupt #2 jumper set on I/O Multiboard, which is pin 11-12 in P5. Has limitations around port settings. Do not have a video card on my Duo so have been forcing a video driver to load and testing with PIP CON:=UR2: . Let me know what you think. --- Source/HBIOS/cfg_MASTER.asm | 1 + Source/HBIOS/fv.asm | 6 +- Source/HBIOS/hbios.asm | 4 +- Source/HBIOS/hbios.inc | 2 +- Source/HBIOS/kbd.asm | 83 ++++++------ Source/HBIOS/ps2iface.inc | 246 ++++++++++++++++++++++++++++++++++++ Source/HBIOS/std.asm | 1 + Source/HBIOS/vrc.asm | 4 +- 8 files changed, 293 insertions(+), 54 deletions(-) create mode 100644 Source/HBIOS/ps2iface.inc diff --git a/Source/HBIOS/cfg_MASTER.asm b/Source/HBIOS/cfg_MASTER.asm index 61ac19ae..367a234d 100644 --- a/Source/HBIOS/cfg_MASTER.asm +++ b/Source/HBIOS/cfg_MASTER.asm @@ -64,6 +64,7 @@ CPUSPDCAP .EQU SPD_FIXED ; CPU SPEED CHANGE CAPABILITY SPD_FIXED|SPD_HILO CPUSPDDEF .EQU SPD_HIGH ; CPU SPEED DEFAULT SPD_UNSUP|SPD_HIGH|SPD_LOW CPUOSC .EQU 1000000 ; CPU OSC FREQ IN MHZ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) +INTPS2KBD .EQU FALSE ; USE INTERRUPTS FOR PS2 KEYBOARD DEFSERCFG .EQU SER_9600_8N1 ; DEFAULT SERIAL LINE CONFIG (SEE STD.ASM) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) diff --git a/Source/HBIOS/fv.asm b/Source/HBIOS/fv.asm index 57041386..97ff6a82 100644 --- a/Source/HBIOS/fv.asm +++ b/Source/HBIOS/fv.asm @@ -1,6 +1,6 @@ ;====================================================================== ; VIDEO DRIVER FOR FPGA VGA -; http://s100computers.com/My%20System%20Pages/FPGA%20Z80%20SBC/FPGA%20Z80%20SBC.htm +; http://s100computers.com/My%20System%20Pages/FPGA%20Z80%20SBC/FPGA%20Z80%20SBC.htm ; ; WRITTEN BY: WAYNE WARTHEN -- 9/2/2024 ;====================================================================== @@ -36,8 +36,8 @@ FV_CTL .EQU FV_BASE+2 ; VGA CONTROL PORT ; FV_BUFCTL .EQU $08 ; -FV_KBDDATA .EQU $03 -FV_KBDST .EQU $02 +FV_KBDDATA .EQU $03 ; KBD CTLR DATA PORT +FV_KBDST .EQU $02 ; KBD CTLR STATUS/CMD PORT ; FV_ROWS .EQU 40 FV_COLS .EQU 80 diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index d2f8c154..9bad42c7 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -1137,7 +1137,7 @@ HBX_INTSTK .EQU $ ; --- -------------- -------------- -------------- -------------- -------------- ; 0 CTC0A INT1 -+ -+ -+ HCCARCV -+ ; 1 CTC0B INT2 | | | HCCASND | -; 2 CTC0C TIM0 | | IM2 | IM2 NABUKB | IM2 +; 2 CTC0C TIM0 | | IM2 PS2KBD | IM2 NABUKB | IM2 ; 3 CTC0D TIM1 | | INT | INT VDP | INT ; 4 UART0 DMA0 | Z180 UART0 | VEC UART0 | VEC OPTCRD0 | VEC ; 5 UART1 DMA1 | CPU UART1 | GEN UART1 | GEN OPTCRD1 | GEN @@ -2361,7 +2361,7 @@ HB_CPU1: CALL SN76489_PREINIT #ENDIF #IF (DSRTCENABLE) - ; THE DSRTC NEEDS TO BE INITIALIZED IN ORDER TO PERFROM THE + ; THE DSRTC NEEDS TO BE INITIALIZED IN ORDER TO PERFORM THE ; CPU SPEED DETECTION BELOW. CALL DSRTC_PREINIT #ENDIF diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index bac1c903..d355a474 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -347,7 +347,7 @@ NVSW_AUTOBOOT .EQU 3 ; Auto Boot NVRAM Switch ; ; AUTO BOOT MASKS ABOOT_AUTO .EQU %00100000 ; AUTO=1/MANUAL=0 BOOT -ABOOT_TIMEOUT .EQU %00001111 ; MENU TIMEOUT IN SECONDS, 0=IMMEDIAGE +ABOOT_TIMEOUT .EQU %00001111 ; MENU TIMEOUT IN SECONDS, 0=IMMEDIATE ; DEFAULT BOOT MASKS DBOOT_ROM .EQU %10000000 ; ROM=1/DISK=0 FLAG DBOOT_UNIT .EQU %01111111 ; DISK UNIT diff --git a/Source/HBIOS/kbd.asm b/Source/HBIOS/kbd.asm index 75171cb0..0665f3e7 100644 --- a/Source/HBIOS/kbd.asm +++ b/Source/HBIOS/kbd.asm @@ -4,6 +4,13 @@ ; ; ORIGINAL CODE BY DR JAMES MOXHAM ; ROMWBW ADAPTATION BY WAYNE WARTHEN +; INTERUPT DRIVER ADDITION BY PHIL SUMMERS +; +; +; IN DEBUG MODE: +: >>nn SHOWS HEX COMMAND nn BEING WRITTEN TO THE COMMAND PORT +; >nn SHOWS HEX VALUE nn BEING WRITTEN TO THE DATA PORT +; = 2) PUSH AF CALL PC_SPACE @@ -300,7 +291,7 @@ KBD_RESET0: JR NZ,KBD_RESET1 ; GOT A BYTE? IF SO, GET OUT OF LOOP DJNZ KBD_RESET0 ; LOOP TILL COUNTER EXHAUSTED KBD_RESET1: - LD A,B +; LD A,B XOR A ; SIGNAL SUCCESS (RESPONSE IS IGNORED...) RET ; DONE ; @@ -312,7 +303,7 @@ KBD_SETLEDS: LD A,$ED ; SET/RESET LED'S COMMAND CALL KBD_PUTDATA ; SEND THE COMMAND CALL KBD_GETDATA ; READ THE RESPONSE - CP $FA ; MAKE SURE WE GET ACK + CP KBD_ACK ; MAKE SURE WE GET ACK RET NZ ; ABORT IF NO ACK LD A,(KBD_STATE) ; LOAD THE STATE BYTE RRCA ; ROTATE TOGGLE KEY BITS AS NEEDED @@ -333,7 +324,7 @@ KBD_SETRPT: LD A,$F3 ; COMMAND = SET TYPEMATIC RATE/DELAY CALL KBD_PUTDATA ; SEND IT CALL KBD_GETDATA ; GET THE ACK - CP $FA ; MAKE SURE WE GET ACK + CP KBD_ACK ; MAKE SURE WE GET ACK RET NZ ; ABORT IF NO ACK LD A,(KBD_REPEAT) ; LOAD THE CURRENT RATE/DELAY BYTE CALL KBD_PUTDATA ; SEND IT diff --git a/Source/HBIOS/ps2iface.inc b/Source/HBIOS/ps2iface.inc new file mode 100644 index 00000000..73a90916 --- /dev/null +++ b/Source/HBIOS/ps2iface.inc @@ -0,0 +1,246 @@ +;__________________________________________________________________________________________________ +; HARDWARE INTERFACE FOR POLLED AND INTERRUPT DRIVEN PS2 KEYBOARD. +; +; IN POLLED MODE THE KEYBOARD DEVICE IS IDENTIFIED BY THE TABLE POINTED TO BY IY +; IN INTERRUPT MODE THE KEYBOARD DEVICE IS UNKNOWN SO PREDEFINED PORT VALUES ARE USED. +; +; REQUIRES INTERRUPT JUMPER TO BE SET +;__________________________________________________________________________________________________ +; +#IF ((INTMODE == 2) & INTPS2KBD)) + +#IF (TMSENABLE) +KBDPORTD .DB TMS_KBDDATA ; KBD CTLR DATA PORT +KBDPORTS .DB TMS_KBDST ; KBD CTLR STATUS/CMD PORT +#ELSE + +#IF (GDCENABLE) +KBDPORTD .DB GDC_KBDDATA ; KBD CTLR DATA PORT +KBDPORTS .DB GDC_KBDST ; KBD CTLR STATUS/CMD PORT +#ELSE + +#IF (CVDUENABLE) +KBDPORTD .DB CVDU_KBDDATA ; KBD CTLR DATA PORT +KBDPORTS .DB CVDU_KBDST ; KBD CTLR STATUS/CMD PORT +#ELSE + +#IF (VRCENABLE) +KBDPORTD .DB VRC_KBDDATA ; KBD CTLR DATA PORT +KBDPORTS .DB VRC_KBDST ; KBD CTLR STATUS/CMD PORT +#ELSE + +#IF (VGAENABLE) +KBDPORTD .DB VGA_KBDDATA ; KBD CTLR DATA PORT +KBDPORTS .DB VGA_KBDST ; KBD CTLR STATUS/CMD PORT +#ENDIF + +#ENDIF +#ENDIF +#ENDIF +#ENDIF +; +;__________________________________________________________________________________________________ +; KEYBOARD QUEUE FOR INTERRUPTS +;__________________________________________________________________________________________________ +; +; +KBDQSIZ .EQU 16 ; MUST BE POWER OF TWO, <=128 +KBDQGETX .DB 0 ; QUEUE INDEX +KBDQPUTX .DB 0 ; QUEUE INDEX + .DB $55 ; GUARD BYTE FOR DEBUGGING +KBDQ .FILL KBDQSIZ,0 ; CIRCULAR KEYBOARD BUFFER + .DB $AA ; GUARD BYTE FOR DEBUGGING + +;__________________________________________________________________________________________________ +; RESET THE QUEUE TO EMPTY +;__________________________________________________________________________________________________ +; +KBDQINIT: + XOR A + LD (KBDQGETX),A + LD (KBDQPUTX),A + RET +; +;__________________________________________________________________________________________________ +; KEYBOARD INTERRUPT VECTOR +;__________________________________________________________________________________________________ +; +KBD_INT: +; CALL KBDQDBG + LD A,(KBDPORTS) ; READ CONTROLLER STATUS + LD C,A + IN A,(C) + AND 1 + RET Z + LD A,(KBDPORTD) ; GET THE RESPONSE + LD C,A + IN A,(C) +; CALL KBDQPUSH ; SAVE KEYBOARD SCAN CODE +; RET +; +;__________________________________________________________________________________________________ +; ADD A BYTE TO THE KEYBOARD QUEUE +;__________________________________________________________________________________________________ +; +KBDQPUSH: ; ADD A SCAN CODE TO THE QUEUE + PUSH AF + CALL KBDQFULL + JR Z,KBDQISF ; EXIT IF THE QUEUE IS FULL +; + LD HL,KBDQPUTX + LD A,(HL) ; CREATE QUEUE INDEX + AND KBDQSIZ-1 + INC (HL) ; UPDATE INDEX +; + LD HL,KBDQ ; INDEX INTO THE QUEUE + LD B,0 + LD C,A + ADD HL,BC + POP AF + LD (HL),A ; SAVE THE CHARACTER IN THE QUEUE +; CALL KBDQDBG +; + RET +; +KBDQISF:POP AF + RET + +KBDQFULL: ; RETURN Z IF QUEUE IS FULL + CALL KBDQLEN ; RETURN NZ IF STILL SPACE IN QUEUE + SUB KBDQSIZ + RET +#ENDIF +;__________________________________________________________________________________________________ +; KEYBOARD READ +;__________________________________________________________________________________________________ +; +#IF ((INTMODE == 2) & INTPS2KBD)) +; +; RETURN A BYTE TO FROM KEYBOARD QUEUE +; NOTE THE QUEUE INDEX'S NEVER DECREASE IN SIZE. +; +KBD_IN: +KBDQPOP: + CALL KBDQLEN + RET Z ; EXIT IF THE QUEUE IS EMPTY +; + LD HL,KBDQGETX + LD A,(HL) ; CREATE QUEUE INDEX + AND KBDQSIZ-1 + INC (HL) ; UPDATE INDEX +; + LD HL,KBDQ ; INDEX INTO THE QUEUE + LD B,0 + LD C,A + ADD HL,BC + LD A,(HL) ; GET THE CHARACTER FROM THE QUEUE +; LD (HL),B ; DEBUG - CLEAN QUEUE +; + RET +; +#ELSE +; +; RETURN A BYTE FROM THE KEYBOARD PORT +; +KBD_IN: + IN A,(C) ; GET THE DATA VALUE + LD C,(IY+KBD_DAT) ; DATA PORT + EZ80_IO + IN A,(C) ; GET THE DATA VALUE + RET +#ENDIF +; +;__________________________________________________________________________________________________ +; KEYBOARD INPUT STATUS +;__________________________________________________________________________________________________ +; +#IF ((INTMODE == 2) & INTPS2KBD)) +KBD_IST: +KBDQLEN: ; EXIT WITH NUMBER OF CHARACTERS IN QUEUE + LD A,(KBDQPUTX) ; Z STATUS AND ZERO IF NONE + LD HL,KBDQGETX + SUB (HL) + RET +#ELSE +KBD_IST: ; A=0, Z SET FOR NOTHING PENDING, OTHERWISE DATA PENDING + LD C,(IY+KBD_ST) ; STATUS PORT + EZ80_IO + IN A,(C) ; GET STATUS + AND $01 ; ISOLATE INPUT PENDING BIT + RET +#ENDIF +; +;__________________________________________________________________________________________________ +; OUTPUT TO KEYBOARD COMMAND PORT +;__________________________________________________________________________________________________ +; +KBD_CMDOUT: + LD C,(IY+KBD_CMD) ; COMMAND PORT + EZ80_IO + OUT (C),A + RET +;__________________________________________________________________________________________________ +; OUTPUT TO KEYBOARD COMMAND DATA +;__________________________________________________________________________________________________ +; +KBD_DTAOUT: + LD C,(IY+KBD_DAT) ; DATA PORT + EZ80_IO + OUT (C),A + RET +;__________________________________________________________________________________________________ +; KEYBOARD OUTPUT STATUS - A=0, Z SET FOR NOT READY, OTHERWISE READY TO WRITE +;__________________________________________________________________________________________________ +; +KBD_OST: + LD C,(IY+KBD_ST) ; STATUS PORT + EZ80_IO + IN A,(C) ; GET STATUS + AND $02 ; ISOLATE OUTPUT EMPTY BIT + XOR $02 ; FLIP IT FOR APPROPRIATE RETURN VALUES + RET +; +;__________________________________________________________________________________________________ +; DEBUG QUEUE +;__________________________________________________________________________________________________ +; +#IF ((INTMODE == 2) & INTPS2KBD & 0) +KBDQDBG: + PUSH HL + PUSH DE + PUSH BC + PUSH AF + + CALL NEWLINE ; PRINT QUEUE CONTENTS WITH PRE AND POST GUARD BYTES + LD B,KBDQSIZ+2 + LD HL,KBDQ-1 +KBDQPRT: + LD A,(HL) + CALL PRTHEXBYTE + INC HL + DJNZ KBDQPRT + + LD A,' ' ; PRINT QUEUE INDEX + CALL COUT + LD A,(KBDQGETX) + AND KBDQSIZ-1 + CALL PRTHEXBYTE + + LD A,' ' ; PRINT QUEUE INDEX + CALL COUT + LD A,(KBDQPUTX) + AND KBDQSIZ-1 + CALL PRTHEXBYTE + + LD A,' ' ; PRINT # SCAN CODES IN QUEUE + CALL COUT + CALL KBDQLEN + CALL PRTHEXBYTE + CALL NEWLINE + + POP AF + POP BC + POP DE + POP HL + RET +#ENDIF diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 0e5903c7..cea7dfaa 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -971,6 +971,7 @@ INT_CTC0D .EQU 15 ; ZILOG CTC 0, CHANNEL D ; ; DUO Z80 IM2 INTERRUPTS ; +INT_PS2KB .EQU 2 ; KEYBOARD RECEIVE INT_UART0 .EQU 4 ; UART 0 INT_UART1 .EQU 5 ; UART 1 INT_SIO0 .EQU 8 ; ZILOG SIO 0, CHANNEL A & B diff --git a/Source/HBIOS/vrc.asm b/Source/HBIOS/vrc.asm index 73b748ce..98b12a59 100644 --- a/Source/HBIOS/vrc.asm +++ b/Source/HBIOS/vrc.asm @@ -15,8 +15,8 @@ VRC_BASE .EQU $00 ; FIRST CHAR DATA PORT VRC_FONTBASE .EQU VRC_BASE + $0C ; FIRST FONT PORT VRC_SCROLLIO .EQU $F5 ; SCROLL REG PORT ; -VRC_KBDDATA .EQU $F4 -VRC_KBDST .EQU $F5 +VRC_KBDDATA .EQU $F4 ; KBD CTLR DATA PORT +VRC_KBDST .EQU $F5 ; KBD CTLR STATUS/CMD PORT ; VRC_ROWS .EQU 48 VRC_COLS .EQU 64