From 78a765147ed6f1577b795690274a180f17a1f771 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sat, 25 May 2024 16:16:14 -0700 Subject: [PATCH] NABU Keyboard Typeahead - Implemented a 16 character typeahead buffer for interrupt-enabled builds of NABU. --- Source/HBIOS/nabukb.asm | 203 ++++++++++++++++++++++++++++++---------- Source/HBIOS/util.asm | 2 +- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 4 files changed, 159 insertions(+), 50 deletions(-) diff --git a/Source/HBIOS/nabukb.asm b/Source/HBIOS/nabukb.asm index 0f5e2205..2a5d79a9 100644 --- a/Source/HBIOS/nabukb.asm +++ b/Source/HBIOS/nabukb.asm @@ -21,9 +21,11 @@ ; WILL TRANSLATE SPECIAL KEYS ($E0-$FF) TO ROMWBW EQUIVALENTS. ALL ; OTHER KEYS WILL BE PASSED THROUGH AS IS. ; -; NABUKB_IODAT .EQU $90 ; KEYBOARD DATA (READ) NABUKB_IOSTAT .EQU $91 ; STATUS (READ), CMD (WRITE) +; +; +NABUKB_BUFSZ .EQU 16 ; RECEIVE RING BUFFER SIZE ; DEVECHO "NABUKB: IO=" DEVECHO NABUKB_IODAT @@ -62,6 +64,7 @@ NABUKB_INIT: LD (IVT(INT_NABUKB)),HL ; IVT INDEX #ENDIF ; +#IF (INTMODE > 0) ; ENABLE KEYBOARD INTERRUPTS ON NABU INTERRUPT CONTROLLER LD A,14 ; PSG R14 (PORT A DATA) OUT (NABU_RSEL),A ; SELECT IT @@ -69,6 +72,7 @@ NABUKB_INIT: SET 5,A ; ENABLE VDP INTERRUPTS LD (NABU_CTLVAL),A ; UPDATE SHADOW REG OUT (NABU_RDAT),A ; WRITE TO HARDWARE +#ENDIF ; XOR A RET @@ -87,96 +91,149 @@ NABUKB_INT: ; ;CALL PC_LT ; *DEBUG* IN A,(NABUKB_IODAT) ; GET THE KEY - LD E,A ; STASH IN REG E + ;CALL PRTHEXBYTE ; *DEBUG* + ;CALL PC_COMMA ; *DEBUG* + CALL NABUKB_XB ; TRANSLATE THE KEY ;CALL PRTHEXBYTE ; *DEBUG* ;CALL PC_GT ; *DEBUG* -; - LD A,(NABUKB_KSTAT) ; GET KEY BUFFER STAT - OR A ; SET FLAGS - RET NZ ; BUFFER FULL, BAIL OUT W/ NZ (INT HANDLED), KEY DISCARDED -; - LD A,E ; RECOVER THE KEY CODE - CALL NABUKB_XB ; TRANSLATE AND BUFFER KEY - OR $FF ; SIGNAL INT HANDLED - RET ; DONE + JR C,NABUKB_INTRCV4 ; ABORT IF UNUSABLE KEY + LD B,A ; SAVE BYTE READ + LD HL,NABUKB_RCVBUF ; SET HL TO START OF BUF STRUCT + LD A,(HL) ; GET COUNT + CP NABUKB_BUFSZ ; COMPARE TO BUFFER SIZE + JR Z,NABUKB_INTRCV4 ; BAIL OUT IF BUFFER FULL, RCV BYTE DISCARDED + INC A ; INCREMENT THE COUNT + LD (HL),A ; AND SAVE IT + INC HL ; HL NOW HAS ADR OF HEAD PTR + PUSH HL ; SAVE ADR OF HEAD PTR + LD A,(HL) ; DEREFERENCE HL + INC HL + LD H,(HL) + LD L,A ; HL IS NOW ACTUAL HEAD PTR + LD (HL),B ; SAVE CHARACTER RECEIVED IN BUFFER AT HEAD + INC HL ; BUMP HEAD POINTER + POP DE ; RECOVER ADR OF HEAD PTR + LD A,L ; GET LOW BYTE OF HEAD PTR + SUB NABUKB_BUFSZ+4 ; SUBTRACT SIZE OF BUFFER AND POINTER + CP E ; IF EQUAL TO START, HEAD PTR IS PAST BUF END + JR NZ,NABUKB_INTRCV3 ; IF NOT, BYPASS + LD H,D ; SET HL TO + LD L,E ; ... HEAD PTR ADR + INC HL ; BUMP PAST HEAD PTR + INC HL + INC HL + INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START +NABUKB_INTRCV3: + EX DE,HL ; DE := HEAD PTR VAL, HL := ADR OF HEAD PTR + LD (HL),E ; SAVE UPDATED HEAD PTR + INC HL + LD (HL),D +NABUKB_INTRCV4: + OR $FF ; NZ SET TO INDICATE INT HANDLED + RET ; AND RETURN ; #ENDIF ; ; NORMAL HBIOS CHAR INPUT STATUS. IF INTERRUPTS ARE NOT ACTIVE, THEN ; KEYBOARD POLLING IS IMPLEMENTED HERE. ; +#IF (INTMODE == 0) NABUKB_STAT: LD A,(NABUKB_KSTAT) ; GET KEY WAITING STATUS OR A ; SET FLAGS -#IF (INTMODE > 0) - JR Z,NABUKB_STATX ; BAIL OUT W/ Z (NO KEY) - RET ; KEY WAITING, ALL SET -#ELSE RET NZ ; KEY WAITING, ALL SET IN A,(NABUKB_IOSTAT) ; GET KBD STATUS AND $02 ; CHECK DATA RDY BIT JR Z,NABUKB_STATX ; BAIL OUT W/ Z (NO KEY) IN A,(NABUKB_IODAT) ; GET THE KEY - CALL NABUKB_XB ; TRANSLATE AND BUFFER KEY - LD A,(NABUKB_KSTAT) ; GET NEW KEY WAITING STATUS + CALL NABUKB_XB ; TRANSLATE/FILTER + JR C,NABUKB_STATX ; IF CF SET, IGNORE + LD (NABUKB_KEY),A ; BUFFER IT + LD A,1 ; SIGNAL KEY WAITING + LD (NABUKB_KSTAT),A ; SAVE IT OR A ; SET FLAGS RET ; DONE -#ENDIF ; NABUKB_STATX: XOR A ; SIGNAL NO CHAR READY JP CIO_IDLE ; RETURN VIA IDLE PROCESSOR ; -; ROUTINE TO TRANSLATE AND BUFFER INCOMING NABU KEYBOARD KEYCODES +#ELSE +NABUKB_STAT: + LD A,(NABUKB_BUFCNT) ; GET BUFFER UTILIZATION COUNT + OR A ; SET FLAGS + JP Z,CIO_IDLE ; NOT READY, RETURN VIA IDLE PROCESSING + RET ; DONE +#ENDIF +; +; ROUTINE TO FILTER AND TRANSLATE INCOMING NABU KEYBOARD KEYCODES +; ENTER WITH RAW KEY CODE IN A +; RESULT IN A, CF SET IF THE KEY SHOULD BE DISCARDED ; NABUKB_XB: + ; $00 - $7F ARE NORMAL ASCII CHARS (PASS THROUGH) BIT 7,A ; HIGH BIT IS SPECIAL CHAR - JR Z,NABUKB_XB2 ; IF NORMAL CHAR, BUFFER IT - CP $90 ; START OF ERR CODES - JR C,NABUKB_XB1 ; NOT ERR CODE, CONTINUE + JR Z,NABUKB_XB2 ; IF NORMAL CHAR, RETURN W/ CF CLEAR + ; $80-$8F ARE JOSYSTICK PREFIXES (PASS THESE THROUGH) + CP $90 ; END OF JOYSTICK PREFIXES + JR C,NABUKB_XB2 ; IF JOY PRE, RETURN W/ CF CLEAR + ; $90-$9F ARE KEYBOARD ERROR CODES (IGNORE THESE) CP $A0 ; END OF ERR CODES - JR NC,NABUKB_XB1 ; NOT ERR CODE, CONTINUE - RET ; DISCARD ERR CODE AND RETURN -NABUKB_XB1: - CP $E0 ; SPECIAL CHARACTER? - JR C,NABUKB_XB2 ; IF NOT, SKIP XLAT, BUFFER KEY - CALL NABUKB_XLAT ; IF SO, TRANSLATE IT - RET C ; CF INDICATES INVALID, DISCARD AND RETURN -NABUKB_XB2: - LD (NABUKB_KEY),A ; BUFFER IT - LD A,1 ; SIGNAL KEY WAITING - LD (NABUKB_KSTAT),A ; SAVE IT - RET ; DONE -; -; ROUTINE TO TRANSLATE SPECIAL NABU KEYBOARD KEY CODES -; -NABUKB_XLAT: + JR C,NABUKB_XB1 ; IF ERR CODE, RETURN W/ CF SET + ; $A0-$BF ARE JOYSTICK DATA (PASS THESE THROUGH) + CP $C0 ; END OF JOYSTICK DATA + JR C,NABUKB_XB2 ; IF JOY DATA, RETURN W/ CF CLEAR + ; $C0-$DF ARE UNUSED CODES (IGNORE THESE) + CP $E0 ; END OF UNUSED CODES + JR C,NABUKB_XB1 ; IF UNUSED CODE, RETURN W/ CF SET ; NABU KEYBOARD USES $E0-$FF FOR SPECIAL KEYS ; HERE WE TRANSLATE TO ROMWBW SPECIAL KEYS AS BEST WE CAN - ; CF IS SET ON RETURN IF KEY IS INVALID (NO TRANSLATION) SUB $E0 ; ZERO OFFSET - RET C ; ABORT IF < $E0, CF SET! LD HL,NABUKB_XTBL ; POINT TO XLAT TABLE CALL ADDHLA ; OFFSET BY SPECIAL KEY VAL LD A,(HL) ; GET TRANSLATED VALUE OR A ; CHECK FOR N/A (0) RET NZ ; XLAT OK, RET W/ CF CLEAR - SCF ; SIGNAL INVALID +NABUKB_XB1: + ; RETURN W/ CF SET (DISCARD RESULT) + SCF ; ELSE SIGNAL INVALID RET ; DONE -; -NABUKB_XLAT1: - SCF ; SIGNAL INVALID - RET ; AND DONE +NABUKB_XB2: + ; RETURN W/ CF CLEAR (KEEP RESULT) + OR A ; CLEAR CF + RET ; RETURN, CF CLEAR ; ; FLUSH KEYBOARD BUFFER ; NABUKB_FLUSH: +#IF (INTMODE == 0) XOR A LD (NABUKB_KSTAT),A +#ELSE + ; RESET THE RECEIVE BUFFER + LD DE,NABUKB_RCVBUF ; DE := CNT + XOR A ; A := 0 + LD (DE),A ; _CNT = 0 + INC DE ; DE := ADR OF _HD + PUSH DE ; SAVE IT + INC DE + INC DE + INC DE + INC DE ; DE := ADR OF _BUF + POP HL ; HL := ADR OF _HD + LD (HL),E + INC HL + LD (HL),D ; _HD := _BUF + INC HL + LD (HL),E + INC HL + LD (HL),D ; _TL := _BUF +#ENDIF RET ; ; WAIT FOR A KEY TO BE READY AND RETURN IT. ; +#IF (INTMODE == 0) NABUKB_READ: CALL NABUKB_STAT ; CHECK FOR KEY READY JR Z,NABUKB_READ ; LOOP TIL ONE IS READY @@ -187,6 +244,46 @@ NABUKB_READ: LD D,A ; NO KEYSTATE LD (NABUKB_KSTAT),A ; CLEAR KEY WAITING STATUS RET ; AND RETURN +#ELSE +; +NABUKB_READ: + CALL NABUKB_STAT ; SEE IF CHAR AVAILABLE + JR Z,NABUKB_READ ; LOOP UNTIL SO + HB_DI ; AVOID COLLISION WITH INT HANDLER + LD HL,NABUKB_RCVBUF ; SET HL TO START OF BUF STRUCT + LD A,(HL) ; GET COUNT + DEC A ; DECREMENT COUNT + LD (HL),A ; SAVE UPDATED COUNT + INC HL ; HL := ADR OF TAIL PTR + INC HL ; " + INC HL ; " + PUSH HL ; SAVE ADR OF TAIL PTR + LD A,(HL) ; DEREFERENCE HL + INC HL + LD H,(HL) + LD L,A ; HL IS NOW ACTUAL TAIL PTR + LD C,(HL) ; C := CHAR TO BE RETURNED + INC HL ; BUMP TAIL PTR + POP DE ; RECOVER ADR OF TAIL PTR + LD A,L ; GET LOW BYTE OF TAIL PTR + SUB NABUKB_BUFSZ+2 ; SUBTRACT SIZE OF BUFFER AND POINTER + CP E ; IF EQUAL TO START, TAIL PTR IS PAST BUF END + JR NZ,NABUKB_READ2 ; IF NOT, BYPASS + LD H,D ; SET HL TO + LD L,E ; ... TAIL PTR ADR + INC HL ; BUMP PAST TAIL PTR + INC HL ; ... SO HL NOW HAS ADR OF ACTUAL BUFFER START +NABUKB_READ2: + EX DE,HL ; DE := TAIL PTR VAL, HL := ADR OF TAIL PTR + LD (HL),E ; SAVE UPDATED TAIL PTR + INC HL ; " + LD (HL),D ; " + LD E,C ; MOVE CHAR TO RETURN TO E + HB_EI ; INTERRUPTS OK AGAIN + XOR A ; SIGNAL SUCCESS + RET ; AND DONE +; +#ENDIF ; ; HELPER ROUTINE TO WRITE ; @@ -201,8 +298,20 @@ NABUKB_PUT: ; ; ; -NABUKB_KSTAT .DB 0 ; KEY STATUS -NABUKB_KEY .DB 0 ; KEY BUFFER +#IF (INTMODE == 0) +NABUKB_KSTAT .DB 0 ; KEY STATUS +NABUKB_KEY .DB 0 ; KEY BUFFER +#ELSE +; +; RECEIVE BUFFER +; +NABUKB_RCVBUF: +NABUKB_BUFCNT .DB 0 ; CHARACTERS IN RING BUFFER +NABUKB_HD .DW NABUKB_BUF ; BUFFER HEAD POINTER +NABUKB_TL .DW NABUKB_BUF ; BUFFER TAIL POINTER +NABUKB_BUF .FILL NABUKB_BUFSZ,0 ; RECEIVE RING BUFFER +NABUKB_BUFEND .EQU $ ; END OF BUFFER +#ENDIF ; ; THIS TABLE TRANSLATES THE NABU KEYBOARD SPECIAL CHARS INTO ; ANALOGOUS ROMWBW STANDARD SPECIAL CHARACTERS. THE TABLE STARTS WITH diff --git a/Source/HBIOS/util.asm b/Source/HBIOS/util.asm index 2496dd52..1cf2fbd3 100644 --- a/Source/HBIOS/util.asm +++ b/Source/HBIOS/util.asm @@ -101,8 +101,8 @@ PRTCH: PUSH AF LD A,(HL) CALL COUT - POP AF INC HL + POP AF EX (SP),HL RET ; diff --git a/Source/ver.inc b/Source/ver.inc index ce07b958..4db182b9 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,7 +2,7 @@ #DEFINE RMN 5 #DEFINE RUP 0 #DEFINE RTP 0 -#DEFINE BIOSVER "3.5.0-dev.42" +#DEFINE BIOSVER "3.5.0-dev.43" #define rmj RMJ #define rmn RMN #define rup RUP diff --git a/Source/ver.lib b/Source/ver.lib index ed3a01a1..fbd7857d 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 5 rup equ 0 rtp equ 0 biosver macro - db "3.5.0-dev.42" + db "3.5.0-dev.43" endm