;__TESTKB____________________________________________________________________________________________
	.Title "TestKB"
;
;  TESTKB  
;     Read PIO attached Matrix Keyboard, debounce and return scancode 
;____________________________________________________________________________________________________

; constants


PORTA	.EQU 	60H
PORTB	.EQU 	61H
PORTC	.EQU 	62H
PIOCONT .EQU 	63H

	.ORG	0100H

	LD	DE,MSG
	LD	C,09H			; CP/M write string to console call
	CALL	0005H

	CALL    mTerm_Init		; Init 8255 for mTerm
	LD	HL,CPUUP		; SET POINTER TO DATA BUFFER
	CALL	SEGDISPLAY		; DISPLAY 



Loop:
	CALL	KB_Get			; Get Key from KB
	CP	017H			; IS boot?
	JR	Z,Exit			; YES, EXIT
	LD	(DISPLAYBUF),A		; STORE A IN DISPLAY BUFFER
	LD	HL,DISPLAYBUF		; SET POINTER TO DATA BUFFER
	CALL	HEXDISPLAY		; DISPLAY DIGIT ON 7 SEG
	CALL    HEXSTR                  ; Change Number in 'A' to ASCII 
	LD	A,H
        LD 	(PRINT_BUFFER),A       	; store ASCII to Print
	LD	A,L
        LD 	(PRINT_BUFFER1),A       ; store ASCII to Print
	LD	DE,PRINT_BUFFER
	LD	C,09H			; CP/M write string to console call
	CALL	0005H
	JR	Loop
Exit:
	RET	




;__mTerm_Init________________________________________________________________________________________
;
;  Setup 8255, Mode 0, Port A=Out, Port B=In, Port C=Out/Out 
;     
;____________________________________________________________________________________________________
mTerm_Init:
	LD	A, 82H
	OUT (PIOCONT),A
	RET

;__KB_Get____________________________________________________________________________________________
;
;  Get a Single Key and Decode
;     
;____________________________________________________________________________________________________
KB_Get:

KB_Get_Loop:				; WAIT FOR KEY
	CALL	KB_Scan			;  Scan KB Once
	CP	00H			;  Null?
	JR	Z,KB_Get_Loop		;  Loop while not zero
	LD      D,A			;  Store A
	LD	A,4FH			;  Scan All Col Lines
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
KB_Clear_Loop:				; WAIT FOR KEY TO CLEAR
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Clear_Loop	;  Yes, Exit.
	LD	A,D			;  Restore A
	LD	D,00H			;
	LD	HL,KB_Decode		;  Point to beginning of Table	
KB_Get_LLoop:
	CP	(HL)			;  Match?	
	JR	Z,KB_Get_Done		;  Found, Done
	INC	HL
	INC	D			;  D + 1	
	JP	NZ,KB_Get_LLoop		;  Not Found, Loop until EOT			
KB_Get_Done:
	LD	A,D			;  Result Into A
	RET



;__KB_Scan____________________________________________________________________________________________
;
;  SCan Keyboard Matrix for an input
;     
;____________________________________________________________________________________________________
KB_Scan:

	LD      C,0000H
	LD	A,41H			;  Scan Col One
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,0040H
	LD	A,42H			;  Scan Col Two
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,0080H
	LD	A,44H			;  Scan Col Three
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD      C,00C0H			;
	LD	A,48H			;  Scan Col Four
	OUT 	(PORTC),A		;  Send to Column Lines
        CALL    KB_Scan_Delay		;  Delay to allow lines to stabilize
	IN	A,(PORTB)		;  Get Rows
	CP	00H 			;  Anything Pressed?
	JR	NZ,KB_Scan_Found	;  Yes, Exit.

	LD	A, 40H			;  Turn off All Columns
	OUT 	(PORTC),A		;  Send to Column Lines
	LD	A, 00H			;  RETURN NULL
	RET				;  Exit

KB_Scan_Found:
	AND	3FH			;  Clear Top two Bits
	OR	C			;  Add in Row Bits 
	LD	C,A			;  Store Value
	LD	A, 00H			;  Turn off All Columns
	OUT 	(PORTC),A		;  Send to Column Lines
	LD	A,C			;  Restore Value
	RET

PAUSE:
KB_Scan_Delay:
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	RET



;__HEXDISPLAY________________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in decoded Hex bits 0-3 are displayed dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
HEXDISPLAY:
	PUSH	AF			; STORE AF
	PUSH	BC			; STORE BC
	LD	BC,0007H	
	ADD	HL,BC
	LD	B,08H			; SET DIGIT COUNT
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
	CALL 	PAUSE			; wait
	LD	A,0F0H			; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal)
	OUT	(PORTA),A		; output to port
	LD	A,80H			; Strobe write pulse with Control=1
	OUT	(PORTC),A		; output to port
	CALL 	PAUSE			; wait
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
HEXDISPLAY_LP:		
	LD	A,(HL)			; GET DISPLAY DIGIT
	CALL	DECODEDISPLAY		; DECODE DISPLAY
	OUT	(PORTA),A		; OUT TO PORTA
	LD	A,00H			; SET WRITE STROBE
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; DELAY
	LD	A,40H			; SET CONTROL PORT OFF
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; WAIT
	DEC	HL			; INC POINTER
	DJNZ	HEXDISPLAY_LP		; LOOP FOR NEXT DIGIT
	POP	BC			; RESTORE BC
	POP	AF			; RESTORE AF
	RET

;__DECODEDISPLAY_____________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in decoded Hex bits 0-3 are displayed dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
DECODEDISPLAY:
	PUSH	BC			; STORE BC
	PUSH	HL			; STORE HL
	LD	HL,SEGDECODE		; POINT HL TO DECODE TABLE
	LD	B,00H			; RESET HIGH BYTE
	LD	C,A			; CHAR INTO LOW BYTE
	ADD	HL,BC			; SET TABLE POINTER
	LD	A,(HL)			; GET VALUE
	POP	HL			; RESTORE HL
	POP	BC			; RESTORE BC
	RET


;__SEGDISPLAY________________________________________________________________________________________
;
;  Display contents of DISPLAYBUF in RAW dig, bit 7 is DP
;     
;____________________________________________________________________________________________________
SEGDISPLAY:
	PUSH	AF			; STORE AF
	PUSH	BC			; STORE BC
	LD	BC,0007H	
	ADD	HL,BC
	LD	B,08H			; SET DIGIT COUNT
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
	CALL 	PAUSE			; wait
	LD	A,0F0H			; set control to 1111 (Data Coming, Hex Decode,NO Decode, Normal)
	OUT	(PORTA),A		; output to port
	LD	A,80H			; Strobe write pulse with Control=1
	OUT	(PORTC),A		; output to port
	CALL 	PAUSE			; wait
	LD	A,40H			; set Control port 7218 to off
	OUT	(PORTC),A		; output
SEGDISPLAY_LP:		
	LD	A,(HL)			; GET DISPLAY DIGIT
	OUT	(PORTA),A		; OUT TO PORTA
	LD	A,00H			; SET WRITE STROBE
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; DELAY
	LD	A,40H			; SET CONTROL PORT OFF
	OUT	(PORTC),A		; OUT TO PORTC
	CALL	PAUSE			; WAIT
	DEC	HL			; INC POINTER
	DJNZ	SEGDISPLAY_LP		; LOOP FOR NEXT DIGIT
	POP	BC			; RESTORE BC
	POP	AF			; RESTORE AF
	RET

; function HEXSTR
; input number in A
; output upper nibble of number in ASCII in H
; output lower nibble of number in ASCII in L
; uses BC
;
; based on following algorithm:
:
;  const
;    hextab : string = ('0','1','2','3','4','5','6','7','8',
;                       '9','A','B','C','D','E','F');
;
;  PROCEDURE hexstr(n: int): ^string;
;  BEGIN
;    n := n and 255;
;    tmpstr[1] := hextab[n / 16];
;    tmpstr[2] := hextab[n and 15];
;    tmpstr[0] := #2;
;    return @tmpstr;
;  END;


HEXSTR:
	PUSH	BC			;SAVE BC
	LD	B,A
	RLC	A			;DO HIGH NIBBLE FIRST  
	RLC	A
	RLC	A
	RLC	A
	AND	0FH			;ONLY THIS NOW
	ADD	A,30H			;TRY A NUMBER
	CP	3AH			;TEST IT
	JR	C,HEXSTR1		;IF CY SET SAVE 'NUMBER' in H
	ADD	A,07H			;MAKE IT AN ALPHA
HEXSTR1:
	LD	H,A			;SAVE 'ALPHA' in H
	LD	A,B			;NEXT NIBBLE
	AND	0FH			;JUST THIS
	ADD	A,30H			;TRY A NUMBER
	CP	3AH			;TEST IT
	JR	C,HEXSTR2		;IF CY SET SAVE 'NUMBER' in L
	ADD	A,07H			;MAKE IT ALPHA

HEXSTR2:
	LD	L,A			;SAVE 'ALPHA' in L
	POP	BC			;RESTORE BC
	RET



;_KB Decode Table__________________________________________________________________________________________________________
; 
;
KB_Decode:
;                0  1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
	.DB	41H,02H,42H,82H,04H,44H,84H,08H,48H,88H,10H,50H,90H,20H,60H,0A0H
;               FW  BK  CL  EN  DP  EX  GO  BO
	.DB	01H,81H,0c1H,0c2H,0c4H,0c8H,0D0H,0E0H
;
; F-Keys,
; FW = Forward
; BK = Backward
; CL = Clear
; EN = Enter
; DP = Deposit (into mem)
; EX = Examine (Mem)
; GO = GO
; BO = Boot
;_________________________________________________________________________________________________________________________

;_Text Strings____________________________________________________________________________________________________________
; 
MSG:
	.TEXT	"Begin Keyboard Test Program"
	.DB	0Ah, 0Dh		; line feed and carriage return
	.DB	"$"			; Line terminator

PRINT_BUFFER:
	.DB	00			; Buffer for output
PRINT_BUFFER1:
        .DB     00
        .TEXT   "<- Scan Code"
	.DB	0Ah, 0Dh		; line feed and carriage return
	.DB	"$"			; line terminator
DISPLAYBUF:
	.DB 	00,00,00,00,00,00,00,00
CPUUP:
	.DB 	084H,0EEH,0BBH,080H,0BBH,0EEH,0CBH,084H
SEGDECODE:
	.DB	0FBH,0B0H,0EDH,0F5H,0B6H,0D7H,0DFH,0F0H,0FFH,0F7H,0FEH,09FH,0CBH,0BDH,0CFH,0CEH,080H,084H
;_________________________________________________________________________________________________________________________


.end


