📄 kb_mouse.asm
字号:
;========================================================================
; 010/15/98 bth
;
; Removed the stuff added 7/10/98. Instead, modified the operation of the
; state machine and the 1msec ISR so that mouse_machine automatically repairs
; itself when the mouse is plugged or unplugged mid-transfer. The basic
; changes are:
;
; Changed the ps2_active_flagC to ps2_tx_flagC, which is now only set/reset
; to indicate that a command was successfully transmitted. ps2_active_flagC
; and its associated functionality were removed. Changed subroutine mouse_status
; to return the state of mouse_machine, rather than the state of the mouse
; connect flag (this routine was not previously called by anyone and so changing
; its return variable had no effect on older code). Finally, changed the mouse 1msec code
; to increment the timeout counter iff the state of mouse_machine is not idle.
; therefore, the timeout counter will expire if mouse_machine is "stuck" in
; a state other than idle, indicating that it is hung. The expiration of the
; timeout counter will, in turn, force mouse_machine to return to idle with
; the mouse_connect flag deasserted, the next time it is invoked.
;
; Due to these functional changes, the added flags plugin and 256msec_counter
; could be removed. They were added to "unstick" mouse_machine, which it now
; does automatically.
;
; changed mouse_int and mouse_1ms_int to subroutines (used ret instead of reti)
; so that they could be called from ISR code in usbmain
;========================================================================
; 07/10/98 v7.0 jk
; Added support for plug and play PS/2 mouse. If the keyboard is powered
; up with no mouse attached, the main loop would ignore the mouse forever
; in Version 6. The "mouse_int" routine has been changed in 2 ways:
;
; (1) If we enter "mouse_int" (which means PS/2 activity has occured) and
; the "mouse_conx_flagc"=0 (which means that we think there is no mouse
; connected) then we set the "plugin" flag here to tell the main loop that
; the mouse is back. The main loop will take care of properly initializing
; the newly connected mouse.
;
; (2) The mouse state machine can get confused if the mouse is plugged
; or un-plugged in the middle of a transfer. This used to cause Version 6
; to hang. A 256ms timer has been implemented which is decremented in the
; 1ms iSR. Any time there is mouse activity, the counter is reset back to
; 256ms. This resetting is done in the "mouse_int" routine below. If the
; mouse state machine crashes for some reason, the 256ms timer will
; decrement to zero. At that point, the 1ms isr knows that the PS/2 bus has
; crashed and will recover. This allows random plug and un-plug to work
; successfully.
;========================================================================
; 01/14/98 v0.1 hth
;========================================================================
;##### START Module kb_mouse #####
;## Rev 0.10
XPAGEON
INCLUDE "kbm_defs.asm"
INCLUDE "kbm_cmd.asm"
INCLUDE "kbm_util.asm"
;**********
; ps2_xmit
;
; Transmit data byte to mouse
;
; Parameters: A = data byte
; Returns: C-bit set on failure
; Side Effects: None
;
; This routine initiates a new transmission to the mouse.
; ps2_xmit asserts the inhibit to the mouse, then executes a 100uS delay. Since this
; routine is not interrupt protected, the inhibit state could last much longer than
; 100uS. This is acceptable, as the mouse will not begin clocking data until the
; inhibit is released.
;
; Once the clock line is released, the remainder of the transmission is handled by the
; mouse_int state machine, which is invoked on every falling edge of the PS/2 clock.
;
;**********
ps2_xmit:
push a ;save a
mov [mouse_dataV],a ;copy transmit data byte to working storage
mov [mouse_resendV],a ;keep another copy in case we need to ReSend
CLRFLAG ps2_error_flagsC ;clear ps2 error flags
CLRFLAG mouse_rcv_flagC ;*** 1/13/97 blow off any pending received bytes
mov a,ps2_ST_T1C ;init state variable to xmit state T1
mov [ps2_stateV],a
mov a,ps2_timeoutC ;init timeout counter
mov [mouse_mScntV],a
mov a,ps2_StartC ;write inhibit/start (clk=0, data=0)
; iowr IO_mouse_port ;falling edge on clk may force int entry to state machine
PS2_WR_PORT3 ;macro that does port 3 writes
mov a,100 ;delay at least 100uS
call us_delay
mov a,ps2_Data0C ;release clock, drive start bit only
; iowr IO_mouse_port
PS2_WR_PORT3
CLRFLAG ps2_tx_flagC ;flag ps/2 active
inc [ps2_stateV] ;increment xmit state to T2
pop a ;restore a
ret ;return
;*****
; ps2_bus_idle
; Set ps/2 bus idle. Places ps/2 bus and state machine in idle state.
;*****
ps2_bus_idle:
push a
mov a,ps2_ST_IdleC
mov [ps2_stateV],a ;first set state machine to idle
CLRFLAG ps2_error_flagsC ;clear ps2 error flags
mov a,ps2_Data1C
; iowr IO_mouse_port ;now set ps/2 bus idle
PS2_WR_PORT3 ;macro that does port 3 writes
pop a
ret
;*****
; ps2_bus_inhibit
; Inhibit ps/2 bus.
;*****
ps2_bus_inhibit:
mov a,ps2_ST_R11C
mov [ps2_stateV],a ;set state machine to inhibit
mov a,ps2_InhibitC
; iowr IO_mouse_port ;inhibit bus
PS2_WR_PORT3 ;macro that does port 3 writes
ret
;**********
;********************
; This is kb_mouse's 1mS interrupt code
; If the ps/2 bus is active, the mouse 1mS timeout counter is decremented. If it reaches
; zero, a timeout is flagged, and the ps/2 active flag is cleared. The main mouse code
; is left to deal with cleaning up the bus.
mouse_1mS_int:
call mouse_status
cmp A,0
jz .end ; branch if not
dec [mouse_mScntV] ; decrement mouse timeout counter to force timeout
jnz .end ; branch to end if timer has not expired
SETFLAG ps2_timout_flagC ; flag the timeout
.end:
ret
;********************
;********************
;********************
; mouse_int
; PS/2 GPIO interrupt entry. This interrupt service is entered on each falling
; edge of the PS/2 clock, and drives the PS/2 state machine.
;
; NOTE: Latency between the falling edge of the ps/2 clock and entry to this code
; must be no more than 17uS in order to guarantee transmit data setup time at the mouse.
;
mouse_int:
push a ;save a
CHKFLAG mouse_suspend_flagC ;suspended?
jz mx0 ;branch if not
call ps2_bus_inhibit ;else, inhibit mouse
CLRFLAG mouse_suspend_flagC ;clear suspend flag
jmp ps2_end_state ;exit interrupt sevice to let app resume
mx0: mov a,[ps2_stateV] ;read state variable into a
index ps2_ST_tbl ;a <- table value = offset to state code
jacc ps2_ST_base ;jump to proper state code
;*****
; PS/2 State table. This jump table contains an entry point to the state processing
; code for each state. The absolute state # (offset within this table) is shown
; in parentheses for each state. The content of each table entry is an offset from
; "ps2_ST_base" to the state processing code for that state.
;*****
;*** State constant Definitions
ps2_ST_T1C: equ 1 ;Transmit state 1 (T1)
ps2_ST_rdC: equ 13 ;Receive state 1 (R1)
ps2_ST_IdleC: equ 0 ;ps/2 idle state
ps2_ST_R11C: equ 23 ;receive inhibit
ps2_ST_tbl:
db ps2_ST_Idle - ps2_ST_base ;(0) Idle
;* Transmit data states
db ps2_end_state - ps2_ST_base ;(1) T1 - Inhibit
db ps2_ST_T2 - ps2_ST_base ;(2) T2 - Start bit
db ps2_ST_tdata - ps2_ST_base ;(3) T3 - bit 0
db ps2_ST_tdata - ps2_ST_base ;(4) T4 - bit 1
db ps2_ST_tdata - ps2_ST_base ;(5) T5 - bit 2
db ps2_ST_tdata - ps2_ST_base ;(6) T6 - bit 3
db ps2_ST_tdata - ps2_ST_base ;(7) T7 - bit 4
db ps2_ST_tdata - ps2_ST_base ;(8) T8 - bit 5
db ps2_ST_tdata - ps2_ST_base ;(9) T9 - bit 6
db ps2_ST_T10 - ps2_ST_base ;(10) T10 - bit 7
db ps2_ST_T11 - ps2_ST_base ;(11) T11 - parity
db ps2_ST_T12 - ps2_ST_base ;(12) T12 - stop bit
;* Receive data states
db ps2_ST_rdata - ps2_ST_base ;(13) R1 - bit 0
db ps2_ST_rdata - ps2_ST_base ;(14) R2 - bit 1
db ps2_ST_rdata - ps2_ST_base ;(15) R3 - bit 2
db ps2_ST_rdata - ps2_ST_base ;(16) R4 - bit 3
db ps2_ST_rdata - ps2_ST_base ;(17) R5 - bit 4
db ps2_ST_rdata - ps2_ST_base ;(18) R6 - bit 5
db ps2_ST_rdata - ps2_ST_base ;(19) R7 - bit 6
db ps2_ST_rdata - ps2_ST_base ;(20) R8 - bit 7
db ps2_ST_R9 - ps2_ST_base ;(21) R9 - parity
db ps2_ST_R10 - ps2_ST_base ;(22) R10 - stop
db ps2_ST_R11 - ps2_ST_base ;(23) R11 - receive inhibit
ps2_ST_base: ;base of state processing routines
;*****
; Transmit - State 1 (T1) - Inhibit/Start
; The state machine is entered in T1 when a new transmission is initiated on an
; idle bus (typical).
; No action is performed in this state, other than resetting the timeout counter,
; so the jump table passes control directly to ps2_end_state.
; The ps2_xmit code itself causes the transition to T2.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -