;---------------------------------------------------------------------------
;   W A T K I N    T E C H N O L O G Y    S o f t w a r e  D i v i s i o n
;---------------------------------------------------------------------------
; PROGRAM: Keyboard Test under FAMOS Flat Real mode
; VERSION: 1.0                            PLATFORM: IBM PC (8088 up)
; PROJECT:                                    FILE: KEYCODES.ASM
;  AUTHOR: Neville Watkin                     DATE: 24 Oct 2008
;   NOTES: 16-bit real-mode code only. Will run on PC/XT!
;---------------------------------------------------------------------------
                ORG     0100H
KC:
                CALL    INIT
GETKEY:
                CALL    WAITKEY
                PUSH    AX              ;save key codes
                MOV     DX,0D1AH
                MOV     BX,7
                CMP     AL,0DH
                JNZ     CHKBS
                JMP     BLANK
CHKBS:          CMP     AL,08
                JNZ     CHKBEL
                JMP     BLANK
CHKBEL:         CMP     AL,07
                JNZ     NOBLANK
BLANK:
                MOV     AL,20H
NOBLANK:
                CALL    DCHARP          ;display char
                POP     AX
                PUSH    AX
                XCHG    AH,AL           ;get scan code
                ADD     DL,9
                MOV     BX,7
                CALL    DISP2HEX        ;display scan code
                POP     AX              ;get ascii code
                PUSH    AX
                ADD     DL,9
                CALL    DISP2HEX        ;display ascii code
                POP     AX
                CMP     AL,1BH
                JZ      EXIT
                JMP     GETKEY
EXIT:
                INT     20H
;---------------------------------------------------------------------------
;  INITIALISE
;---------------------------------------------------------------------------
INIT:
                MOV     AX,3
                INT     10H

;                CALL    KBRESET         ;any differences with this?

                MOV     SI,TITLE
                MOV     BX,7
                MOV     DX,030DH
                CALL    DISPLAYB

                MOV     DX,0D2EH
                MOV     AH,2
                INT     10H

                RET
;---------------------------------------------------------------------------
;  DISPLAY ASCII NUL-TERMINATED STRING USING BIOS (data from code seg)
;---------------------------------------------------------------------------
;enter with reqd cursor row/col in DH/DL, page no./text colour in BH/BL
;null-terminated string at cs:si
DISPLAYB:
                MOV     AH,02
                INT     10H
DISPLYB1:
                MOV     AL,[CS:SI]
                CMP     AL,00
                JZ      DISPLYBD
                CALL    DCHAR
                INC     SI
                JMP     DISPLYB1
DISPLYBD:       RET
;---------------------------------------------------------------------------
;  DISPLAY SINGLE CHAR WITH POSITION OPTION
;---------------------------------------------------------------------------
;enter DCHARP with reqd position (row/col) in DH/DL
DCHARP:         MOV     AH,02
                PUSH    AX              ;save reqd char
                INT     10H             ;set (cursor) position (destroys AL)
                POP     AX              ;restore reqd char in al
;enter DCHAR with reqd page no./text colour in BH/BL, reqd char in AL
DCHAR:          MOV     AH,0EH          ;select teletype mode
                INT     10H             ;and go, then
                RET                     ;and return
;---------------------------------------------------------------------------
;               ORG     NEXT      DISPLAY 2 BCD DIGITS
;---------------------------------------------------------------------------
;enter with DX=row/col, AL=2 bcd digits to display as ascii, BX=page/colour
DISP2HEX:       CALL    BYTE2HEX        ;convert data to ascii-hex
                PUSH    AX              ;save data
                XCHG    AH,AL           ;get MSD in al
                CALL    DCHARP          ;and display it
                POP     AX              ;restore data (LSD in al)
                CALL    DCHAR           ;and display it
                RET
;---------------------------------------------------------------------------
;  WAIT FOR KEYPRESS (DEBOUNCED)
;---------------------------------------------------------------------------
WAITKEY:        MOV     AH,01
                INT     16H             ;get keyboard status
                MOV     AH,00           ;select Wait for Key service
                JZ      GOTKEY          ;when key gone, go get it
                INT     16H             ;else flush the buffer
                JMP     WAITKEY         ;and wait for it again
GOTKEY:         INT     16H             ;read key from keyboard buffer
                RET
;return with ascii key code in AL, scan code in AH
;---------------------------------------------------------------------------
;               ORG     NEXT    ;CONVERT BYTE TO 2 ASCII HEX DIGITS
;---------------------------------------------------------------------------
;enter with 8-bit binary data or 2 valid BCD digits in AL
BYTE2HEX:       PUSH    BX
                PUSH    AX              ;save binary data
                SHR     AL,4
                CALL    NYBL2HEX        ;and convert to ascii-hex
                MOV     BH,AL           ;save MSD in bh
                POP     AX              ;retrieve binary data
                AND     AL,0FH          ;get low nybble
                CALL    NYBL2HEX        ;and convert to ascii-hex
                MOV     AH,BH           ;restore MSD to ah
                POP     BX
                RET
;exit with ascii codes of 2 hex digits in AX
;---------------------------------------------------------------------------
;  CONVERT NYBLLE TO EQUIVALENT HEX DIGIT
;---------------------------------------------------------------------------
;enter with valid nybble in AL (bits 4-7 = 0)
NYBL2HEX:       ADD     AL,30H
                CMP     AL,3AH
                JB      NYBLDONE
                ADD     AL,07
NYBLDONE:       RET
;exit with ascii code of equivalent hex digit in AL
;---------------------------------------------------------------------------
;  KEYBOARD RESET
;---------------------------------------------------------------------------
KBRESET:        STI                     ;enable interrupts
                IN      AL,61H          ;read 8255 control port
                OR      AL,80H          ;set bit 7
                OUT     61H,AL          ;send leading edge of reset
                AND     AL,7FH          ;clear bit 7
                OUT     61H,AL          ;send falling edge of reset
                MOV     AL,20H          ;End of Interrupt command code
                OUT     20H,AL          ;send EOI to PIC
                RET
;---------------------------------------------------------------------------
;  FIXED DATA (accessed via CS: override)
;---------------------------------------------------------------------------
TITLE:
 DB "KeyCodes by Neville Watkin. All Rights Reserved",13,10
 DB "             ===============================================",13,10,10
 DB "                    Press any key ... (Esc will exit)",13,10,10,10
 DB "                        char      scan     ascii",13,10
 DB "                       screen     code     code",13,10
 DB "                      display      hex      hex",13,10
 DB "                      ~~~~~~~~~~~~~~~~~~~~~~~~~~",13,10,0

