; -----------------------------------------------
; PShell - a runtime environment for    
; sharp pocket computers                 
; file     : keyboard.asm                   
; author   : puehringer edgar           
; date     : 14.06.2004                 
; version  : 1.0.0                      
; assembler: as61860                    
;                                       
; All keyboard related funtions for pshell
; -----------------------------------------------

.area pshell (REL)
        
.include "pshell.h"
.include "internal.h"


; -----------------------------------------------
; Checks if a key is pressed on the keyboard
; if Carry Flag = 0, no key was pressed
; if Carry Flag = 1, a key was pressed
; The key code stays in A
; Used Registers: Various because a ROM call
;   is used
; Return value: A, Carry
; label prefix 00
; -----------------------------------------------

ps_kbd_nowait2::
	TEST 8			; check for BREAK key
	JPNZ ps_break      

.if __PC_1350__

	LIA >(ps_keycode-1)
	LP  REG_YH	
	EXAM
	LIA  <(ps_keycode-1)
	LP  REG_YL	
	EXAM
	
	RA
	LIDP ps_keycode
	STD

        CAL  INT_ROM_KPRESS

	LIDP ps_keycode
	LDD
	CPIA 0
	JRNZP lb0001

	CAL INT_ROM_RAWKEY
	JRNCP lb0002
	;ORIA 0x80
	SC
	RTN

lb0001: SC
lb0002:	RTN

ps_keycode:
	.db 0x00

.else
.if __PC_1262__

	LIA >(ps_keycode-1)
	LP  REG_YH	
	EXAM
	LIA  <(ps_keycode-1)
	LP  REG_YL	
	EXAM
	
	RA
	LIDP ps_keycode
	STD

        CAL  INT_ROM_KPRESS

	LIDP ps_keycode
	LDD
	CPIA 0
	JRNZP lb0001

	RC
	RTN

lb0001: SC
lb0002:	RTN

ps_keycode:
	.db 0x00

.else
.if __PC_1403__

	RA			; 0->K (address)
	LP   REG_K
	EXAM
	LIB  7			; 7->B (increment)	
	LII  1			; 1->I (mask)

; ** Reading the keys from IA-port **
lb0001:	LP   REG_I
	LDM			; I->A (assert P == REG_I)
	LIP 92			; A->IA-Port
	EXAM
	OUTA
	INA			; IA-Port->A
	CPIA 0			; if != 0,
	JRNZP lb0002		; jump to keycode calculation
	LP   REG_B		; K = K - B
	LDM
	LP   REG_K
	ADM
	DECB			; B--
	LP   REG_I		; I = I >> 1
	LDM
	SL
	EXAM
	CPIA 32			; If I != 64 (i.e. old val. != 32),
	JRNZM lb0001		; do the loop

; ** Reseting the IA-Port **
	RA			; 0->IA-Port
	LIP 92 
	EXAM
	OUTA

; ** Reading the keys from K-port **
	LIA  28			; 28->K (address)
	LP   REG_K
	EXAM
	LII  1			; 1->I (mask)
lb0003:	LP   REG_I
	LDM			; I->A (assert P == REG_I)
	LIDP KEY_P		; Address of key port
	STD
	INA			; Read port A
	CPIA 0			; if != 0,
	JRNZP lb0002		; jump to keycode calculation
	LP   REG_K		; K = K - 8
	ADIM 8
	LP   REG_I		; I = I >> 1
	LDM
	SL
	EXAM
	CPIA 64			; If I != 128 (i.e. old val. != 64),
	JRNZM lb0003		; do the loop

	LP   REG_K		; 255->K
        ORIM 0xFF
	LIA  128		; 128->A

; ** Key code calculation **
lb0002: CPIA 128		; If A == 128, jump
	JRZP  lb0004		; to end (assert, A is never 0)
	RC
	SL			; A = A >> 1
	INCK			; K = K + 1			
	JRM   lb0002		; do the loop

; ** If we get here, no key is pressed, so reset the carry
        RC
        JRP  lb0005       

; ** Output and end **
lb0004:	LP   REG_K		; K->A
	LDM
        SC
	
lb0005: RA			; 0->key port
	LIDP MEM_KEYPORT
	STD
        RTN

.else

; other modells are not implemented yet
.error 1

.endif
.endif
.endif

; -----------------------------------------------
; Waits on a key to be pressed on the keyboard.
; If a key is pressed while entering the
; function, it waits until it is released
; The key code stays in A
; Used Registers: Various because a ROM call
;   is used
; Return value: A
; label prefix 02
; -----------------------------------------------

ps_kbd_raw::
lb0201:	CALL    ps_kbd_nowait
	JRCM   lb0201
lb0202:	CALL    ps_kbd_nowait
	JRNCM   lb0202
	RTN

; -----------------------------------------------
; Read a character from the keyboard (blocking)
; Used Registers: Various because a ROM call
;   is used
; Return value: A
; label prefix 04
; -----------------------------------------------
ps_getchar_kbd::
lb0402:	CALL    ps_kbd_nowait
	JRNCM   lb0402
	CAL INT_ROM_GETKEY	; FIXXXME PowerDown (A=10) should be respected
	TEST 8			; check for BREAK key
	JPNZ ps_break      
	RTN


	;; -----------------------------------------------
	;; ps_kbd_reset, ps_kbd_single:
	;; Read a single row from the keybord matrix (non
	;; blocking). The mask pattern is given in A.
	;; If carry is set, the extended matrix rows (not
	;; port A, port B or something on the gate array)
	;; are addresses. ps_kbd_reset sets the matrix
	;; back to zero
	;; Used registers: A,B
	;; Return value: A
	;; label prefix 06
	;; -----------------------------------------------

ps_kbd_reset:
	RA
	
ps_kbd_single:
	EXAB			; if C, B=A, A=0
	RA			;   else B=0
	JRCP lb0601
	EXAB
	
lb0601: LIP  PORT_A		; A ==> port A
	EXAM
	OUTA

	EXAB			; B ==> port B or K
.if __PC_KBD_GATE_ARRAY__
	LIDP MEM_KEYPORT
	STD
.else
	LIP  PORT_B
	EXAM
	OUTB
.endif	
	INA  

	RTN

	
	;; -----------------------------------------------
	;; Checks if a key is pressed on the keyboard
	;; if Carry Flag = 0, no key was pressed
	;; if Carry Flag = 1, a key was pressed
	;; The key code stays in A
	;; Used Registers: A,B
	;; Return value: A, Carry
	;; label prefix 08
	;; -----------------------------------------------

ps_kbd_nowait::
	TEST TEST_BRK		; check for BREAK key
	JPNZ ps_break      

	
	RA			; K=0 (address)
	LP   REG_K
	EXAM
	
	LIA  7			; L=7 (increment)
	LP   REG_L
	EXAM
		
	LII  1			; I=1 (mask)

lb0801:	LP   REG_I		; A=I
	LDM
	RC			; Reading the keys from port A
	CALL ps_kbd_single	
	CPIA 0			; if != 0
	JRNZP lb0802		;   jump to keycode calculation
	
	LP   REG_L		; K = K + L
	LDM
	LP   REG_K
	ADM
	
	DECL			; L--
	
	LP   REG_I		; I = I >> 1
	LDM
	SL
	EXAM
	
	CPIA 32			; if I != 64 (i.e. old val. != 32)
	JRNZM lb0801		;   do the loop

	
	LIA  KEYPORT_OFFS	; K=KEYPORT_OFFS (address)
	LP   REG_K
	EXAM
	
	LII  1			; I=1 (mask)

lb0803:	LP   REG_I		; A=I
	LDM	
	SC			; Reading the keys from port B or K
	CALL ps_kbd_single	
	CPIA 0			; if != 0,
	JRNZP lb0802		;   jump to keycode calculation
	
	LP   REG_K		; K = K + 8
	ADIM 8
	
	LP   REG_I		; I = I >> 1
	LDM
	SL
	EXAM
	
	CPIA 64			; if I != 128 (i.e. old val. != 64)
	JRNZM lb0803		;   do the loop


	CALL ps_kbd_reset	; If we get here, no key is pressed,
        RC			; so reset the carry and return
	RTN

	
	;; ================================
	;; Key code calculation
	;; Precondition: A != 0
	
lb0802: CPIA 128		; if A == 128
	JRZP  lb0804		;  jump to end
	RC
	SL			; A = A >> 1
	INCK			; K = K + 1			
	JRM   lb0802		; do the loop


lb0804:	CALL ps_kbd_reset
	LP   REG_K		; A=K
	LDM
        SC

	RTN
