📄 637mouse.asm
字号:
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
and A, 07h
;=====================================================================
; Substitute macro DELAY with a readProcessOptics procedure that
; consumes about the same amount of time. The reason is that we do not
; want to miss any optics count (To send or recive a bit in PS2 takes
; about 1 ms)
;======================================================================
call readProcessOptics
; DELAY 30 ; wait as per spec
CLEARC
pop A
ret
;========================================================================
; FUNCTION: getBit
;
; Receives a bit
;
;
; Returns:
; MSB of (A) = state of bit clocked in
; CF = 1 if error; CF = 0 if OK
;
;========================================================================
getBit:
push A
iord PORT2 ; IF INHIBIT, get out now
and A,SCLK
jz .error
mov A, CLKL_DATAH ; start with clock low, data high
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
and A, 07h
DELAY 35 ; wait 35 usec
mov A,CLKH_DATAH ; raise clock line
or A, (PS2_PULLUP | USB_PS2_MODE);
iowr USB_STATUS_CONTROL_REG ;
and A, 07h
DELAY 5 ; wait 5 usec
iord PORT2 ; read the data line
;=====================================================================
; Substitute macro DELAY with a readProcessOptics procedure that
; consumes about the same amount of time. The reason is that we do not
; want to miss any optics count (To send or recive a bit in PS2 takes
; about 1 ms)
;======================================================================
push A
call readProcessOptics
pop A
; DELAY 30 ; wait 30 usec
and A, SDATA ; mask off all but data bit
; (and instruction clears CF)
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: ps2Receive
;
; Receives a byte
;
;
; Returns:
; C= 0 if reception was successful
; C= 1 if not
;
;========================================================================
ps2Receive:
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 PORT2
and A, SDATA ; 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
mov X, 8 ; count 9 bits (8 data, 1 parity)
mov A, 0 ; clear parity count
mov [ps2Temp0], A
.l1:
call getBit
jc .inhibit ; if not inhibiting
cmp A, 80h ; see if msbit = 1
jc .next ; yup,
inc [ps2Temp0] ; increment parity count
.next:
dec X ; decrement counter
jc .done ; if at -1, done
jnz .l1
push A ; else save partial result
; (save all 8 bits)
jmp .l1 ; go and get parity bit
.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 ps2Temp0.
; 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, [ps2Temp0] ; get computed parity
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 = 1 if no errors
call send_0 ; send a 0 to ack the transaction
mov A, X
cmp A, 0
jz .error
.exit:
mov A, CLKH_DATAH ; make sure PS2 bus is left idle
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
and A, 07h
jmp .return
.error:
mov A,CLKH_DATAH ; make sure PS2 bus is left idle
or A, (PS2_PULLUP | USB_PS2_MODE)
iowr USB_STATUS_CONTROL_REG
and A, 07h
SETC ;set carry indicating a problem
.return:
pop A ; pop result into ACC
pop X ; restore X
ret
.exitearly:
SETC
pop X
ret
;********************************************************************
;
; Main Entry for USB Interface
;
;********************************************************************
usbMain:
;
; set wakeup timer interval and disable XTALOUT
;
mov A, WAKEUP_ADJUST2 | WAKEUP_ADJUST0 | INTERNAL_CLK | PRECISION_USB_CLOCKING
iowr CLOCK_CONFIG
;
; initialize USB variables
;
mov A, 00h
mov [ep0InMachine], A
mov [configuration], A
mov [ep1Stall], A
mov [idle], A
mov [suspendCount], A
mov [intTemp], A
mov [idleTimer], A
mov [idlePrescaler], A
mov [ep0Transtype], A
mov [ep1DmaBuff0], A
mov [ep1DmaBuff1], A
mov [ep1DmaBuff2], A
mov [ep1DmaBuff3], A
mov A, HID_REPORT
mov [protocol], A
mov A, SET
mov [remoteWakeup], A
;
; enable USB address for endpoint 0
;
mov A, ADDRESS_ENABLE
iowr USB_ADDRESS
;
; enable global and EP0 interrupts
;
mov A, (1MS_INT | USB_RESET_INT)
iowr GLOBAL_INTERRUPT_REG
mov A, EP0_INT
iowr ENDPOINT_INT
ei
;
; enable USB pullup resistor
;
mov A, VREG_ENABLE
iowr USB_STATUS_CONTROL_REG
;********************************************************************
;
; Main Task Loop for USB Interface
;
;********************************************************************
usbTaskLoop:
;
; usb main loop - watchdog clear
;
iowr WATCHDOG_REG ; clear watchdog
call processButtons
mov A, [eventMachine]
cmp A, EVENT_PENDING ; need to send data back to host?
jnz usbOptic ; no - go do optics
mov A, [buttonValue] ; assign button value to EP1
mov [ep1DmaBuff0], A ;
usbOptic:
call readProcessOptics
mov A, [eventMachine]
cmp A, EVENT_PENDING ; need to send data back to host?
jnz usbOptic2 ; no - continue
mov A, [xCount] ; yes, save data to EP1 FIFO
mov [ep1DmaBuff1], A ;
mov A, [yCount] ; need to invert y-coordinate for
cpl A ; proper direction
inc A ;
mov [ep1DmaBuff2], A ;
mov A, [protocol]
cmp A, 01h ; is it 4-byte packet?
jnz usbOptic2 ; go if 3-byte packet
mov A, [zCount] ;
mov [ep1DmaBuff3], A ;
; this task sends data out from endpoint 1 if the endpoint is configured
; and not set to stall
usbOptic2:
mov A, [eventMachine]
jacc eventMachineJumptable
eventPending:
;
; if not configured then skip data transfer
;
mov A, [configuration]
cmp A, 01h
jnz eventTaskDone ; go if not configured
;
; if stalled then skip data transfer
;
mov A, [ep1Stall]
cmp A, FFh
jz eventTaskDone ; go if EP1 stalled
mov A, [protocol]
cmp A, 01h ; is z-wheel enabled in either USB
; (REPORT_PROTOCOL mode) or PS2 mode?
mov A, MOUSE_PACKET_4 ; set up endpoint 1 to send 4 bytes
jz formPacket ; go if wheel button supported
dec A ; set up endpoint 1 to send 3 bytes
formPacket:
or A, [ep1DataToggle] ;
iowr EP1_COUNT ;
mov A, ACK_IN ; set to ack on endpoint 1
iowr EP1_MODE ;
eventTaskDone:
mov A, NO_EVENT_PENDING ; clear pending events
mov [eventMachine], A
noEventTask:
jmp usbTaskLoop
;========================================================================
; FUNCTION: Interrupt handler: dualUsbBusReset_ps2Error
; Purpose:
; If USB
; process USB reset
; Else
; goes to error handler
;
;========================================================================
dualUsbBusReset_ps2Error:
mov A, [dualInterfaceMouse] ; get interface type in (A)
cmp A, USB_MOUSE
jz usbBusReset ; go if USB
jmp ps2Error ; should not get here if PS2
usbBusReset:
mov A, STALL_IN_OUT ; set to STALL INs&OUTs
iowr EP0_MODE ;
mov A, ADDRESS_ENABLE ; enable USB address 0
iowr USB_ADDRESS ;
mov A, DISABLE ; disable endpoint1
iowr EP1_MODE ;
mov A, 00h ; reset program stack pointer
mov psp,a ;
jmp usbMain
;========================================================================
; FUNCTION: dual1msTimer
; Purpose:
; Poll the buttons every ms;
; If USB
; watches for USB suspend and handles the HID idle timer
;
;========================================================================
dual1msTimer:
push A
inc [dualInterface1ms] ; otherwise, increment 1ms counter
;
; poll buttons for button on/off state
;
; Notes:
; Any time we read a button port we will set
; buttonMachine = BUTTON_DATA_PENDING
;
mov A, [buttonMachine]
cmp A, BUTTON_DATA_PENDING ; has button port been read?
jz 1msSuspendTimer ; go if yes
call getButtons ; get but
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -