📄 kbm_task.asm
字号:
;========================================================================
; MouseConnectTask
; This Task was invented to clean up and consolidate the code that deals
; with the plugging and unplugging of the mouse. To facilitate matters,
; no attempt is made to "catch" the mouse's initial power-on string when
; it is plugged in. Rather, the mouse is sent a reset command periodically
; and is determined to be connected if
; a valid power-up response is received. Once determined to be connected,
; the mouse state will
; move to "unconnected" if for some reason the mouse state machine loses
; contact with the mouse (as indicated by mouse_conx_flagC).
;
; note that the mouse's operation is driven by repeated calls to mouse_machine.
; In turn, mouse_machine depends upon the 1 msec ISR to detect if it is "stuck"
; due to a mouse being plugged/unplugged in the middle of a transaction.
; The 1 msec ISR will force mouse_machine back to the idle state if it detects
; no state transitions within the timeout period.
;
; To implement this idea, a state variable for the mouse connect state
; is maintained as follows
;
;
; MOUSE_UNCONNECTED: in this state, the keyboard is powered up and has been reset
; by the host. The mouse interface is now available because the GPIO and
; 1msec interrupts are enabled. In this state,
; ps2_init and mouse_reset are invoked to initiate a reset command to the mouse.
; The state is advanced to MOUSE_IN_RESET to indicate that a reset command has
; been sent to the mouse, and a response is being awaited.
;
; MOUSE_IN_RESET: in this state, the mouse has been issued a reset command.
; The mouse can take up to 1 second to respond to this command.
; The reset command can either result in a timeout, indicating that the
; reset response was not properly received, or the response to the reset
; command can be found in the mouse buffer. If the response is valid,
; the state is advanced to MOUSE_CONNECTED. If the response resulted in a
; timeout or was improper, the mouse is assumed to be disconnected and
; the state is returned to MOUSE_UNCONNECTED.
;
; MOUSE_CONNECTED: in this state, the mouse is connected. A call to
; mouse_machine is made to update the status of the connect flag.
;
;
; REVISION HISTORY: 3/26/99 Fixed to send a mouse packet only on change
; 02/9/99 Added 3D mouse support
; 02/2/99 Added boot/report protocol packet switching
; 11/9/98 Added report ID to endpoint 2 packet
;========================================================================
MOUSE_UNCONNECTED: equ 0h
MOUSE_IN_RESET: equ 1
MOUSE_CONNECTED: equ 2
MouseConnectTask:
push A
mov A,[mouse_connect_stateV]
cmp A,MOUSE_UNCONNECTED
jnz .in_reset
;if the state is unconnected, send a reset command
call ps2_init
call mouse_reset
mov A,MOUSE_IN_RESET
jmp .nextstate
.in_reset:
cmp A,MOUSE_IN_RESET ;if we've issued a reset to the mouse
jnz .connected
call mouse_machine ; call mouse_machine to process the reset com
jc .mend ;if the state machine returns idle,
CHKFLAG mouse_conx_flagC ;if not connected
jz .unconnect ; go to unconnect state
mov A,[mouse_packetV] ;if init string[0] <> aah
cmp A,0aah
jnz .unconnect ; go to unconnect state
mov A,[mouse_packetV+1] ;if init string[1] <> 00h
cmp A,00h
jnz .unconnect ; go to unconnect state
call mouse_init ;mouse must be there, so init it and
CHKFLAG mouse_conx_flagC ;if not connected
jz .unconnect ; go to unconnect state
mov A,MOUSE_CONNECTED ;go to connect state
jmp .nextstate
.connected:
call mouse_machine ;call mouse machine to verify connection
CHKFLAG mouse_conx_flagC ;if we lost the connection
jz .unconnect ; go to unconnect state
jmp .mend
.unconnect:
mov A,MOUSE_UNCONNECTED
.nextstate:
mov [mouse_connect_stateV],A
.mend:
pop A
ret
;========================================================================
; MOUSE POLLING TASK
;========================================================================
MouseTask:
push A
mov A,[mouse_connect_stateV]
cmp A,MOUSE_CONNECTED
jnz MouseTask_end
CHKFLAG mouse_conx_flagC ; check to see if the mouse is there
jz MouseTask_end ; because we may get here after a timeout
.idle1_period_check:
mov A, [mouse_idle_period_ctr] ; if idle_period is zero, then we only send
cmp A, 0 ; reports on change
jz .no_idle
dec A
mov [mouse_idle_period_ctr],A ; else decrement idle period
jnz .no_idle ; exit if idle period not expired
.xmit:
mov A,[mouse_idle_period] ; reset idle period
mov [mouse_idle_period_ctr],A
mov A,1
mov [mouse_send_flagV],A ; indicate that we need to send a report
.no_idle:
dec [mouse_poll_intervalV] ;gear down mouse polling to every 6*4 = 24 msec
jnc .skip_poll
.poll:
mov A,5
mov [mouse_poll_intervalV],A
call mouse_poll ; poll for data
.tw3:call mouse_machine ; wait for done
jc .tw3
CHKFLAG mouse_conx_flagC ; check to see if the mouse is there
jz MouseTask_end ; because we may get here after a timeout
.check_change:
mov A, [mouse_packetV] ; has 1st byte changed?
cmp A, [last_mouse_packetV]
jnz .change
mov A, [mouse_packetV+1] ; x , y, or z bytes non-zero?
or A, [mouse_packetV+2]
or A, [mouse_packetV+3] ; (if this is only an x-y mouse, z byte is always zero)
cmp A, 0
jz .no_change
.change:
mov A,1
mov [mouse_send_flagV],A ; flag we need to send a packet
mov A, [mouse_packetV] ; load first PS/2 data byte
mov [last_mouse_packetV], A ; save it for future comparison
.no_change:
.skip_poll: ;always check to see if we need to send
;data
call SendMouseData ; send mouse data to host
MouseTask_end:
pop A
ret
;========================================================================
; copy mouse data from buffer mouse_packetV to EP2 fifo and enable tx
;========================================================================
; The PS/2 mouse data packet consists of 3 bytes starting at mouse_packetV
; Byte 1: bit[0] = left button, bit[1] = right button
; Byte 2: X displacement
; Byte 3: Y displacement
; Note: positive Y values delivered by PS/2 mouse means moving toward to
; the bottom, so its sign need to be changed before sending to host
;
;***JK Check to see if the mouse is connected before we send anything
SendMouseData:
push A ; save A as CHKFLAG destroys it
mov A,[mouse_send_flagV] ; if we need to send mouse data
cmp A,00 ;
jz SMD_Done ;
iord EP_A2_Mode ; are we currently transmitting a report?
and A, USB_MODE_MASK
cmp A, ACKIN
jz SMD_Done ; yes, then exit (so we don't mess up current xact)
push X
mov A,endpoint_2 ;point X at endpoint 2's buffer
mov X,A
mov A,[protocol_status] ;if not boot protocol
cmp A,BOOT_PROTOCOL
jz .skipID
mov A,[mouse_idV] ;
mov [X+0],A ; load report ID first
inc X
.skipID:
mov A, [mouse_packetV] ; load first PS/2 data byte
and A, 07h ; mask out bit 3 to bit 7
mov [X+0], A ; load button data to fifo
mov A, [mouse_packetV+1] ; load x displacement to fifo
mov [X+1], A
mov A, [mouse_packetV+2] ; load y displacement to fifo
cpl A ; invert the sign in 2's complement
add A, 01h
mov [X+2], A
mov A,[mouse_packet_lenV] ; check to see if we are xmitting 3d packets
cmp A,MOUSE_3D_PACKET_LEN
mov A,0
jnz .skipz ; no, zero the wheel displacement, else
mov A, [mouse_packetV+3] ; load z displacement to fifo
cpl A
add A,1
.skipz:
mov [X+3], A
pop X
iord EP_A2_Counter
and A, DATATOGGLE ; keep data toggle setting
push A
mov A,[protocol_status] ;if not boot protocol
cmp A,BOOT_PROTOCOL
pop A
jz .report
or A, (MOUSE_REPORT_LEN) ; use report packet size
jmp .enable
.report:
or A, (MOUSE_REPORT_LEN-2) ; else use boot packet size
.enable:
iowr EP_A2_Counter
mov A, ACKIN ; enable packet transmission
iowr EP_A2_Mode
mov A,0
mov [mouse_send_flagV],A ;clear send flag
SMD_Done:
pop A
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -