;***************************************************************
;*							       *
;*	KEYBOARD DRIVER 				       *
;*							       *
;***************************************************************

;-16 keys buffered
;-fixed german character set
;-DOS compatible scan and key codes
;-F1..10 fixed
;-additional keys

;******* keybord DOS entry *************************************

;------- remove char from loval kbd buffer, wait ---------------

;ret.:  status word, transfer count and char

KeyIn:  jcxz    KbdEx

kbd$lp: push    bx ;!
        push    cx
        call    ChrIn
        pop     cx
        pop     bx
        stosb
        loop    kbd$lp
KbdEx:  jmp     exit

;------ input single char --------------------------------------

ChrIn:  xor     ax,ax
        xchg    al,altah
        or      al,al
        jnz     KeyRet

InAgn:  call    KbdIn                   ;BIOS read destr,wait

Alt10:  or      ax,ax                   ;scan & Ascii = 0?
        jz      inagn
        or      al,al
        jnz     keyret                  ;Ascii = 0? (AltKey)
        mov     altah,ah                ;AltAh <- scan code

KeyRet: ret

;------ 1 key look-ahead input, no wait --------------------------

;looks for next key if avail

;ret.:  busy bit & next char if avail
KeyNd:  mov     al,[altah]
        or      al,al
        jnz     RdEx

Rd1:    call    KbdSt                   ;BIOS read nondestr, imm.
        jz      Kbdbusy
        or      ax,ax
        jnz     KbdEx
        call    KbdIn
        jmp     KeyNd

RdEx:   lds     bx,[prtsav]
        mov     [bx].media,al           ;!
        jmp     exit
KbdBusy:jmp     BusExit                 ;!(un)buffered?

;------ kbd status ---------------------------------------------

;ret.:  status word & busy bit

KeySt:  call    KbdSt
        jz      KbdBusy
        jmp     exit

;------ kbd flush ----------------------------------------------

;physical flush of 8741 kbd buffer!

KeyFl:  in      al,byte ptr rskey       ;flush 8741:
        test    al,KbDat86
        jz      ExKeyFl                 ;z = done (no more avail.)

        in      al,byte ptr rdkey       ;poll 1 key from 8741
        jmp     KeyFl                   ;rpt until all removed

ExKeyFl:mov     [AltAh],0
        mov     byte ptr cs:[KeySts],not NewKey ;flush 1-key look ahead
        jmp     Exit

;****** keyboard BIOS entry ************************************

;All Kbd input is done by the transparent (i.e. not waiting)
;status routine. As the DM-V does not support any hardware
;interrupt at all, the standard 16 key look-ahead buffer is
;not implemented. Instead of Int9 a polling routine takes place,
;removing 1 key from the 8741 kbd buffer (destr I/O read) and
;storing it at the 1 key KeyBuf (emulate non destructive). 
;Thus, the local kbd buffer provides for 16 level look-ahead.
;To flush this non-interrupting kbd, its local buffer is read 
;until the status flag indicates nor more available.


int16:  mov     word ptr cs:[reg_ax],ax
        mov     word ptr cs:[reg_bx],bx
        mov     word ptr cs:[reg_cx],cx
        mov     word ptr cs:[reg_dx],dx ;further regs pushed loc.

        cmp     ah,0
        jz      I16_0                   ;kbd wait read?
        cmp     ah,1
        jz      I16_1
        cmp     ah,2
        jz      I16_2
        call    fail			;!
        xor     ax,ax
        mov     word ptr cs:[reg_ax],ax

;------ exit: return flags -------------------------------------

XInt16: pop     dx
        pop     bx
        pop     cx
	pushf         
	sub	sp,4	

XI16_1: mov     ax,word ptr cs:[reg_ax]
	mov     bx,word ptr cs:[reg_bx]
        mov     cx,word ptr cs:[reg_cx]
        mov     dx,word ptr cs:[reg_dx]
        sti                             ;???
        iret

;------ func 0: kbd input destr, wait --------------------------

;BIOS INT

I16_0:  call    KbdIn                   ;!not buffered
        jmp     XI16_1                  ;ret in ax,no flags

;DOS & BIOS CALL

KbdIn:  call    KbdSt                   ;read either buffer or I/O
        jz      KbdIn                   ;rpt until available
        mov     byte ptr cs:[KeySts],not NewKey;done (destr)
        ret                             ;no flags

;------ func 1: kbd status, not wait input ---------------------

;return:scan/ascii in ax, z = 0: char available

;BIOS INT:

I16_1:  call    KbdSt
        jmp     XInt16                  ;return zero flag

;BIOS & DOS CALL:

KbdSt:  test    byte ptr cs:[KeySts],NewKey ;1-KeyBuf empty?
        jz      InKSt
        mov     ax,word ptr cs:[KeyBuf] ;false: get undestr. 
        jmp     ExKbdSt                 ;from buf, return nz

InKSt:  in      al,byte ptr rskey       ;true: 8741 empty?
        test    al,Kbdat86
        jz      ExKbdSt                 ;true: return z

        pushf
        in      al,byte ptr rdkey       ;I/O read destr
        call    TxKbd                   ;ah = scan, al = Ascii
        mov     word ptr cs:[KeyBuf],ax ;move key -> buffer:
        mov     byte ptr cs:[KeySts],NewKey   ;non destr.
        popf                                  ;return nz

ExKbdSt:mov	word ptr cs:[reg_ax],ax       ;ret scan/ascii
	ret

;------ func 2: get shift status -------------------------------

;ret:  shift status in al
I16_2:  xor     al,al
        jmp     XI16_1                  ;no flags

;------ convert NCR-ascii -> IBM-ascii ger & scan code ---------

txkbd:  mov     dl,al
        xor     dh,dh

        mov     bx,offset CharTab
        add     bx,dx
        mov     al,byte ptr cs:bx       ;masm?
        mov     bx,offset ScanTab
        add     bx,dx
        mov     ah,byte ptr cs:bx       ;masm?
        mov     word ptr cs:[reg_ax],ax
        ret

CharTab:
;           ^a  ^b  ^c  ^d  ^e  ^f  ^g  ^h  ^i  ^j  ^k  ^l  ^m  ^n  ^o
DB      00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0ah,0bh,0ch,0dh,0eh,0fh
;       ^p  ^q  ^r  ^s  ^t  ^u  ^v  ^w  ^x  ^y  ^z
DB      10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1ah,1bh,1ch,1dh,1eh,1fh
DB      20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2ah,2bh,2ch,2dh,2eh,2fh
DB      30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3ah,3bh,3ch,3dh,3eh,3fh
DB      15h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4ah,4bh,4ch,4dh,4eh,4fh
;                                                   AE  OE  UE
DB      50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5ah,8eh,99h,9ah,5eh,5fh
DB      60h,61h,62h,63h,64h,65h,66h,67h,68h,69h,6ah,6bh,6ch,6dh,6eh,6fh
;                                                   ae  oe  ue  sz
DB      70h,71h,72h,73h,74h,75h,76h,77h,78h,79h,7ah,84h,94h,81h,0e1h,7fh

;80         ^c  lft dwn  up rgt ^g      cr          ^h
DB      00h,03h,00h,00h,00h,00h,07h,87h,0dh,89h,8ah,08h,8ch,8dh,8eh,8fh

;90..
db      10h dup (0)

;A0..:  ctl F1..10
db      10 dup (0)
db      1bh,1ch,1dh
db      20h-13 dup (0)

;C0..:  sft F1..F10
db      10 dup (0)
;       sft F11..F13
db      7bh,7ch,7dh
db      20h-13 dup (0)

;E0..:  F1..F10
db      10 dup (0)
;       F11..F17
db      5bh,5ch,5dh
db      20h-13 dup (0)

ScanTab:
;00..       ^a  ^b  ^c  ^d  ^e  ^f  ^g  ^h  ^i  ^j  ^k  ^l  ^m  ^n  ^o
db      00h,1eh,30h,2eh,20h,12h,21h,22h,23h,17h,24h,25h,26h,32h,31h,18h
;10..   ^p  ^q  ^r  ^s  ^t  ^u  ^v  ^w  ^x  ^y  ^z esc
db      19h,10h,13h,1fh,14h,16h,2fh,11h,2dh,2ch,15h,01h,00h,00h,00h,00h
;20..   sp  !   "      $   %   &   '   (   )   *   +   ,   -   .   /
db      39h,02h,03h,29h,05h,06h,07h,0dh,09h,0ah,1bh,1bh,33h,35h,34h,35h
;30..   0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
db      0bh,02h,03h,04h,05h,06h,07h,08h,09h,0ah,34h,33h,2bh,0bh,2bh,0ch
;40..      A..
db      00h,1eh,30h,2eh,20h,12h,21h,22h,23h,17h,24h,25h,26h,32h,31h,18h
;50..   P..                                     Z   Ž   ™   š   ^   _
db      19h,10h,13h,1fh,14h,16h,2fh,11h,2dh,2ch,15h,28h,27h,1ah,29h,35h
;60..   `   a..
db      0dh,1eh,30h,2eh,20h,12h,21h,22h,23h,17h,24h,25h,26h,32h,31h,18h
;70..   p..                                                     ~
db      19h,10h,13h,1fh,14h,16h,2fh,11h,2dh,2ch,15h,28h,27h,1ah,00h,00h

;80..:      hom lft dwn up  rgt clr     ret         bs
db      00h,47h,4bh,50h,48h,4dh,53h,00h,1ch,00h,00h,0eh,00h,00h,00h,00h
;90..
db      10h dup (0)

;a0..:  ctl F1..                          ..F10
db      5eh,5fh,60h,61h,62h,63h,64h,65h,66h,67h
;       [    \   ]  hom end Pgu Pdn
db      1ah,2bh,1bh,77h,75h,84h,76 
db      20h-17 dup (0)

;c0..:  sft F1..                           ..10
db      54h,55h,56h,57h,58h,59h,5ah,5bh,5ch,5dh
;       {   |   }  hom end Pgu Pdn
db     1ah,2bh,1bh,47h,4fh,49h,51h
db      20h-17 dup (0)

;e0..:  F1..                               ..10  
db      3bh,3ch,3dh,3eh,3fh,40h,41h,42h,43h,44h
;       [    \   ]  hom end Pgu Pdn
db     1ah,2bh,1bh,47h,4fh,49h,51h
db      20h-17 dup (0)


