⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2_io.asm

📁 用cy7c66113开发的HUB
💻 ASM
字号:
;-------------------------------------------------------------------------
; For CKHub, While these routine is executed, interrupt should be disabled.
;-------------------------------------------------------------------------

;========================================================================
;   FILE: ps2_io.asm
;
;8/25/98 Added a 50 usec delay prior to sending commands. 
;Some PC's did not like it without this delay.
;
;
;========================================================================

;========================================================================
; FUNCTION: ps2_send
;
; Sends a byte 
;
;
; Returns: 
;   C= 0 if transmission was successful
;   C= 1 if not
;
;========================================================================
ps2_send:
	push	A					                ; save our data byte                    
	push	X					                ; save X register

	MOV     X, A					            ; save data byte momentarily in X               
	iord    PS2_PORT					        ; get clock/data pair
	and     A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; mask off other bits in port
	cmp     A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; if both are not high,
	jz      .l1            
	SETC
	JMP     .error      				        ; exit this routine with carry set

.l1:
	DELAY   50					                ; allow some spacing between bytes for
							                    ; some PC's.

	call    send_0					    ; clock out start bit
	jc      .error      				; if a problem, quit now
	MOV     A, 1
	MOV     [ps2_temp0], A				; keep track of parity
	MOV     A, X					    ; get back our data byte
	MOV     X, 8					    ; count 8 bits
.l2:
	asr	A					            ; shift bit to send into carry
	jc      .one					    ; if carry is zero
	call    send_0					    ; send a zero
	jc      .error      				; problem, quit now
	JMP     .next					    ;
.one:							        ; else
	call    send_1					    ; send a 1
	jc      .error      				; problem, quit now
	inc     [ps2_temp0]				    ; keep track of parity
.next:							        ;
	dec     X					        ; decrement counter
	jz      .parity					    ; if at zero do parity
	jnc     .l2					        ; if -1, exit

 .stopbit:
	call    send_1					    ; clock out stop bit  
	CLEARC
	JMP     .exit

.parity:
	MOV     A, [ps2_temp0]				; now send parity too
	JMP     .l2

.exit:
	MOV     A, [p3_shadow]
	OR      A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; make sure PS2 bus is left idle
	MOV     [p3_shadow], A
	iowr    PS2_PORT
	JMP     .return

.error:
	MOV     A, [p3_shadow]
	OR      A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; make sure PS2 bus is left idle
	MOV     [p3_shadow], A
	iowr    PS2_PORT
	SETC

.return:
	POP     X
	POP     A
	ret						;return


;========================================================================
; FUNCTION: send_0,send_1
;
; Sends bit out the ps2 port
;
;
; Returns: 
;   C= 0 if transmission was successful
;   C= 1 if not
;
;========================================================================
send_1:
	PUSH    A
	MOV     A, [p3_shadow]
	OR      A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)
	JMP     clock
send_0:
	PUSH    A
	MOV     A, [p3_shadow]
	OR      A, (PS2_CLOCK_BIT)
	and     A, ~(PS2_DATA_BIT)

clock:
	PUSH    A					; prior to sending a bit
	iord    PS2_PORT
	and     A, PS2_CLOCK_BIT	; check for clock inhibit
	POP     A					;
	jnz     .l1					; if there is an inhibit
	SETC						; quit right now
	POP     A
	ret
.l1:
	iowr    PS2_PORT				; set up register
	DELAY	5 
	AND     A, ~(PS2_CLOCK_BIT)
	iowr    PS2_PORT				; write it out
	DELAY   35					; delay as per spec
	OR      A,(PS2_CLOCK_BIT)
	iowr    PS2_PORT
	DELAY   30					; wait as per spec
	CLEARC
	POP     A
	ret

;========================================================================
; FUNCTION: getbit
;
; Receives  a bit
;
;
; Returns: 
;   C = state of bit clocked in
;
;========================================================================
getbit:
	PUSH    A					; PUSH    A
	iord    PS2_PORT		    ; host inhibit, skip this nonsense
	and     A, PS2_CLOCK_BIT
	jz      .error
	MOV     A, [p3_shadow]
	OR      A, (PS2_DATA_BIT)
	AND     A, ~(PS2_CLOCK_BIT)	; start with clock low, data high
	iowr    PS2_PORT          
	DELAY   35					; wait 35 usec
	OR      A, (PS2_CLOCK_BIT)
	iowr    PS2_PORT		    ;

IFDEF   CombiKB
	DELAY	12					; JUK
	iord    PS2_PORT			; 
	DELAY	14					; 
ELSE
	DELAY	5					; wait 5 usec 
	iord    PS2_PORT			; read the data line
	DELAY	21					; wait 25 usec
ENDIF	
								; (total time clock high should be
								; around 40 us per logitech.
								; actual clock high can be affected
								; by 1ms interrupt plus jitter
								; in this code and in  ps2_receive.
								; empirical calculation gives the minimum
								; delay time here as 25 us, which
								; still satisfies the minimum allowed
								; clock high time of 30 us. while
								; giving us an average time of around
								; 37-38 us.
	AND     A, PS2_DATA_BIT	    ; mask off all but data bit
	JZ      .low				; if data bit high,
	SETC						; set the carry
.low:                   	
	POP     A					; POP acc and rotate carry into msb
	rrc     A           	
	CLEARC						; clear carry indicating success
	ret							; return
.error:                 	
	POP     A           	
	SETC                	
	ret                 	
                        	

;========================================================================
; FUNCTION: ps2_receive
;
; Receives a byte 
;
;
; Returns: 
;   C= 0 if reception was successful
;   C= 1 if not
;
;========================================================================

ps2_receive:
	PUSH    X					; save X, we'll wipe it out

	MOV     X, 18				; do the following 18 times:
.wait:							;
	DELAY   7					; kill time for 7 us
	iord    PS2_PORT			; get port 3 data
	and     A, PS2_DATA_BIT		; make sure data bit low
	jnz     .exitearly			; out now if not
	dec     X					; wait again
	jnz     .wait				;
							    ; above loop consumes approx 180 us.

.start:
    

;	DELAY   5					; wait prior to anything
	MOV     X, 8				; count 9  bits (8 data, 1 parity)
	MOV     A, 0				; clear parity count
	MOV     [ps2_temp0], A

.l1:
	call    getbit
	jc      .inhibit				; if not inhibiting
	cmp     A, 80h					; see if msbit = 1
	jc      .next					; yup,
	inc     [ps2_temp0]				; increment parity count
.next:
	dec     X					    ; decrement counter
	jc      .done					; if at -1, done    
	jnz     .l1    
	PUSH    A					    ; else save partial result
	JMP     .l1

.inhibit:						    ; we were inhibited in
	dec     X					    ; the middle of getting stuff,
	jc      .done					; adjust stack appropriately
	PUSH    A
.done:
    
    ;arrive here with data byte on the stack and the received parity bit in the msb
    ;of the accumulator. the calculated parity bit is in the lsb of ps2_temp0.
    ;if we arrived here due to host inhibit, both parity and data byte are
    ;garbage but that's ok -- we'll abort out of this routine anyway.
	MOV     A, [ps2_temp0]			
	and     A, 1
	MOV     X, A
							        ; X should be 1 if ok

	call    getbit					; get stop bit
	jc     .error      				; if no problem getting it
	rlc     a                           
	jc     .ack					    ; if it's not a 1
	MOV     X, 0					; X= 0 indicates an error

.badstop:						    ;
	call    getbit					; keep looking for it
	jc      .error
	rlc     a
	jnc    .badstop

.ack:
							        ; arrive here with x = 0 if no errors
	call    send_0					; send a 0 to ack the transaction
	MOV     A, X
	cmp     A, 0
	jz     .error

.exit:
	MOV     A, [p3_shadow]
	OR      A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; make sure PS2 bus is left idle
	MOV     [p3_shadow], A
	iowr    PS2_PORT
	JMP     .return

.error:
	MOV     A, [p3_shadow]
	OR      A, (PS2_CONNECT+PS2_CLOCK_BIT+PS2_DATA_BIT)	; make sure PS2 bus is left idle
	MOV     [p3_shadow], A
	iowr    PS2_PORT
	SETC						; set carry indicating a problem
.return:
	POP     A					; POP     result into ACC  
	POP     X					; restore X
    ret

.exitearly:
	SETC
	POP     X
	ret




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -