📄 637mouse.asm
字号:
; Delay about 500 ms
;
mov X, 10
BATouterWait:
mov A, 00h ; reset 1 ms counter
mov [dualInterface1ms], A ;
and A, 50 ; set up for 50ms
BATinnerWait:
iowr WATCHDOG_REG ; clear watchdog reset
cmp A, [dualInterface1ms]
jnz BATinnerWait
dec X
jnz BATouterWait
mov A, 0AAh ; send AA to host
mov [ps2XmitBuffer0], A ;
mov A, 00h ; send 00h to host
mov [ps2XmitBuffer1], A ;
mov A, 02h ; buffer has 2 bytes
mov [ps2XmitBufferLen], A ;
mov [ps2XmitLen], A ; to send 2 bytes
ret
;========================================================================
; FUNCTION: ps2GetHostByte
;
; Gets a byte from host in (A), if any
; On exit:
; (cf) = 1 if receive error or host does not send data
; (cf) = 0 if receive data
;
;========================================================================
ps2GetHostByte:
call ps2HostRequestToSend
jc ghbExit ; go if host does not request to
; send data
call disable1msInterrupt ; to avoid clock jitter
; during ps2 clock-in
call ps2Receive ; get byte in (A)
; (cf) = 0 if ok
; (cf) = 1 if error in receiving data
push A ; save byte for later use
call enable1msInterrupt ;
pop A ; restore received byte
ghbExit:
ret
;========================================================================
; FUNCTION: ps2HostRequestToSend
; (cf) = 1 if host does not request to send data; Else (cf) = 0.
;
;========================================================================
ps2HostRequestToSend:
iord PORT2
and A, (SCLK + SDATA)
cmp A, SCLK
jz hrtsExit ; go if host requests to send data
; (clock high, data low)
SETC ; indicate no host RTS
ret
hrtsExit:
CLEARC
ret
;========================================================================
; FUNCTION: ps2HostInhibit
; (cf) = 1 if host inhibits, else (CF) = 0
;
;========================================================================
ps2HostInhibit:
iord PORT2
and A, (SCLK)
cmp A, 0h
jz hInhibit ; go if host inhibits data
; (clock low)
CLEARC ; indicate no host inhibit
ret
hInhibit:
SETC
ret
;========================================================================
; FUNCTION: disable1msInterrupt
;
;========================================================================
disable1msInterrupt:
iord GLOBAL_INTERRUPT_REG
and A, ~1MS_INT
iowr GLOBAL_INTERRUPT_REG
ret
;========================================================================
; FUNCTION: enable1msInterrupt
;
;========================================================================
enable1msInterrupt:
rlc ; save carry flag
push A ;
iord GLOBAL_INTERRUPT_REG
or A, 1MS_INT
iowr GLOBAL_INTERRUPT_REG
pop A ; restore (CF)
rrc ;
ret
;========================================================================
; FUNCTION: ps2SendNextByte
; Sends a byte from transmit buffer
;
;========================================================================
ps2SendNextByte:
call ps2HostRequestToSend
jnc snbExit ; go if host request to send
call ps2HostInhibit
jc snbExit ; go if host inhibits transmission
mov A, [ps2XmitBufferLen] ; compute offset into next byte
sub A, [ps2XmitLen] ; of xmit buffer
mov X, A ;
mov A, [X + ps2XmitBuffer] ; get byte to send
push A ; save it for later use
call disable1msInterrupt ; to prevent clock jitter
pop A ; get it back
call ps2Send ; send it to host
jc snbNext ; go if sending error
dec [ps2XmitLen] ; point to next byte in buffer
snbNext:
call enable1msInterrupt
snbExit:
ret
;========================================================================
; FUNCTION: ps2SendResponseByte
;
; Attempts to send a response byte (ACK, ERROR, RESEND) to the host.
;
; On entry: (A) = response byte to be sent
;
;========================================================================
ps2SendResponseByte:
push A ; save sending byte for later use
srbLoop:
call ps2HostRequestToSend
jnc srbExit ; quit if host requests to send data
call ps2HostInhibit
jc srbNext ; go if host inhibits
call disable1msInterrupt
pop A ; get back sending byte
call ps2Send ; and send it
call enable1msInterrupt
ret
srbNext:
iowr WATCHDOG_REG ; clear watchdog timer
jmp srbLoop ; continue
srbExit:
pop A
ret
;========================================================================
; FUNCTION: checkWheel
;
; Checks whether proper sequence of commands have been issued
; by host to enable the wheel of the mouse. The sequence is 3 consecutive
; setting rate commands of 200, 100 and 80 reports/sec.
;
; On Entry: (A) = rate (reports/sec)
; On Exit: [ps2Wheel] = 1 if z-wheel enabled, else [ps2Wheel] = 0
;
;========================================================================
XPAGEOFF
rateArray: db 200, 100, 80
RATE_ARRAY_SIZE: equ 03h
XPAGEON
checkWheel:
mov [temp], A ; save rate for later use
mov A, 00h ; get 1st element in array
index rateArray ;
cmp A, [temp]
jnz cw1 ; go if rates mismatch
mov A, 00h
mov [sequence], A ; start sequence from beginning
cw1:
mov A, [sequence] ; get element in rateArray
index rateArray ;
cmp A, [temp]
jnz cwExit ; go if rates do not match
inc [sequence] ; next element
mov A, [sequence]
cmp A, RATE_ARRAY_SIZE
jc cwExit2
mov A, 01h ; enable Z-WHEEL
mov [ps2Wheel], A ;
cwExit:
mov A, 00h
mov [sequence], A ; reset index
cwExit2:
ret
;********************************************************************
;
; PS2 I/O Routines
;
; Contains the code that sends/receives data via the
; D- and D+ output pins, in ps2 format
;
;********************************************************************
;
;
; Defines for the 4 combinations of clock and data
; (SCLK = D+, SDATA = D-)
CLKH_DATAH: equ 07h ; force D+ HiZ, D- HiZ
CLKL_DATAH: equ 06h ; force D+ Low, D- HiZ
CLKH_DATAL: equ 05h ; force D+ HiZ, D- Low
CLKL_DATAL: equ 04h ; force D+ Low, D- Low
;========================================================================
; FUNCTION: ps2Send
;
; Sends a byte in (A)
;
;
; Returns:
; C= 0 if transmission was successful
; C= 1 if not
;
;========================================================================
ps2Send:
push A ; save our data byte
push X ; save X register
mov X, A ; save data byte momentarily in X
DELAY 50 ; delay a bit time between bytes
.l1: ; some PC's.
call send_0 ; clock out start bit
jnc .sendStartBitSuccess
; if we are being inhibited and the host is not requesting to send,
; then continue to try to send the start bit
.sendInhibitWait:
iowr WATCHDOG_REG ; reset the watchdog
iord PORT2
and A, (SCLK + SDATA) ; if CLK=low (inhibit) and DATA=high
cmp A, SDATA ; then wait until host releases clock
jz .sendInhibitWait
cmp A, SCLK ; if host is requesting to send, then
jz .error ; quit with error
jmp .l1 ; else try to send start bit again
.sendStartBitSuccess:
mov A, 1
mov [ps2Temp0], 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 [ps2Temp0] ; 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, [ps2Temp0] ; now send parity too
jmp .l2
.error:
mov A, CLKH_DATAH ; make sure PS2 bus is left idle
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
SETC
jmp .exit2
.exit:
mov A, CLKH_DATAH ; make sure PS2 bus is left idle
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
.exit2:
pop X
pop A
ret
;========================================================================
; FUNCTION: send_0,send_1
;
; Sends bit out the ps2 port
;
;
; Returns:
; C= 0 if transmission was successful
; C= 1 if not
;
;========================================================================
;
; The following state table defines the next state for the clock-data pair
; to clock out a given bit.
;
XPAGEOFF
drive_table:
db 0, 0, 0, CLKH_DATAL, 0, CLKL_DATAL, CLKH_DATAH, CLKL_DATAH
XPAGEON
send_1:
push A
mov A, CLKH_DATAH ; start with clock high, data high
jmp clock
send_0:
push A
mov A,CLKH_DATAL ; start with clock high, data low
clock:
push A
iord PORT2 ; read clock
and A, SCLK
pop A
jnz .l2
SETC
pop A ; should be high
ret
.l2:
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG ; set up register
and A, 07h
DELAY 5
index drive_table ; wait 5 us
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG ; write it out
and A, 07h
DELAY 35 ; delay as per spec
index drive_table ; deassert clock
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -