?? mouse45.asm
字號:
dec A
jnz delay2
iowr Watchdog ; clear watchdog timer
mov A, FFh
dec [disch_counter]
jnz delay2
iord Port0_Data ; read port 0
cmp A, [port_temp] ; compare port 0 data to previosly stored data
jz No_change
iord USB_Status_Control ; check if there is no bus activity
and A, BusActivity
jnz Wakeup_end ; bus active
iord USB_Status_Control ; set J state
or A, 04h ;
iowr USB_Status_Control
and A, 0fBh ; clear J state
iowr USB_Status_Control
iord USB_Status_Control ; send wakeup to host
or A, ForceResume ; set Force Resume bit
iowr USB_Status_Control
mov A, 01h ; set wakeup flag
mov [wakeup_flag], A
mov A, 0h ; clear wakeup counter
mov [wakeup_counter], A
mov A, TIMER_ONLY ; enable one msec timer interrupts
iowr Global_Interrupt
Wakeup_wait:
mov A, [wakeup_counter] ; Wait for 10ms
cmp A, 0Ah
jc Wakeup_wait
mov A, 0h ; disable interrupts
iowr Global_Interrupt
iord USB_Status_Control ; Clear Force Resume bit
and A, ~ForceResume
iowr USB_Status_Control
mov A, 0h ; clear wakeup flag
mov [wakeup_flag], A
iord Port0_Data ; read port 0
mov [port_temp], A ; save value
No_change:
mov A, 0ffh ; turn off the LED on Port 1 bit[0]
iowr Port1_Data
mov A, 01h ; disable open drain O/P driver
iowr Cext ; start charging for the next one
Wakeup_end:
mov A, WAKEUP_MASK
ipret Global_Interrupt
;*******************************************************
; The 1 msec interrupt is only used to clear the watchdog
; timer. This interrupt service routine would be the
; place to enter suspend mode.
One_mSec_ISR:
push A
iowr Watchdog ; clear watchdog timer
dec [4ms_counter] ; count til 4 to increment
jnz button_debounce
mov A,[idle_period_counter]
cmp A, 0ffh ; if 0ffH is reach in the
jz 4ms_set ; idle_period_counter no more
inc [idle_period_counter] ; increment
4ms_set:
mov A,4
mov [4ms_counter],A
button_debounce:
mov A, [button1_deb]
cmp A, 0h
jz no_debounce
inc A
mov [button1_deb], A
cmp A, 30
jnz no_debounce
mov A, 0h
mov [button1_deb], A
no_debounce:
mov A, [wakeup_flag] ; check if we are in a remote wakeup process
cmp A, 01h
jnz notremote_wakeup
inc [wakeup_counter] ; increment wakeup counter
mov A, TIMER_ONLY ; enable One_msec_ISR
ipret Global_Interrupt
notremote_wakeup:
iord USB_Status_Control ; check if there is no bus activity
and A, BusActivity
jz Inc_counter ; no bus activity
iord USB_Status_Control ; clear the bus activity bit
and A, ~BusActivity
iowr USB_Status_Control
mov A, 3h ; clear the suspend counter
mov [suspend_counter], A
jmp One_mSec_end
Inc_counter:
dec [suspend_counter] ; check if 3msecs of bus inactivity passed
jnz One_mSec_end ; less than 3msecs
iord Port0_Data ; save current value
mov [port_temp], A
mov A, 3h ; clear the suspend counter
mov [suspend_counter], A
mov A, 0ffh ; turn off the LED on Port 1 bit[0]
iowr Port1_Data
iowr Port0_Data
mov A, [remote_wakeup_status] ; check if remote wakeup is enabled
cmp A, ENABLE_REMOTE_WAKEUP
jnz Suspend1 ; Not enabled
mov A, 0
iowr Cext
mov A, FFh
mov [disch_counter], A
delay:
dec A
jnz delay
iowr Watchdog ; clear watchdog timer
mov A, FFh
dec [disch_counter]
jnz delay
mov A, 01h
iowr Cext ; start charging external capacitor
mov A, WAKEUP_MASK ; wakeup is the ONLY interrupt enabled
iowr Global_Interrupt
Suspend1:
iord Status_Control ;set the suspend bit causing suspend
or A, SuspendBits
iowr Status_Control
nop
mov A, 0f0h ; turn on the phototransistors
iowr Port0_Data
mov A, 0feh ; turn on the LED on Port 1 bit[0]
iowr Port1_Data
One_mSec_end:
mov A, [interrupt_mask]
ipret Global_Interrupt
;*******************************************************
; Interrupt handler: endpoint_one
; Purpose: This interrupt routine handles the specially
; reserved data endpoint 1 (for a mouse). This
; interrupt happens every time a host sends an
; IN on endpoint 1. The data to send (NAK or 3
; byte packet) is already loaded, so this routine
; just prepares the dma buffers for the next packet
USB_EP1_ISR:
push A ; save accumulator on stack
iord USB_EP1_TX_Config ; return NAK when data is not
and A, 7Fh ; ready
xor A, DataToggle ; flip data 0/1 bit
iowr USB_EP1_TX_Config
mov A, 0h
mov [horiz_position], A
mov [vert_position], A
mov [button_position], A
mov A, [interrupt_mask] ; return from interrupt
ipret Global_Interrupt
;*******************************************************
; reset processing
; The idea is to put the microcontroller in a known state. As this
; is the entry point for the "reserved" interrupt vector, we may not
; assume the processor has actually been reset and must write to all
; of the I/O ports.
;
; Port 0 bits 3:0 are the phototransistors
; Write these pins "low" with midrange current to bias
; the phototransistors.
; Port 0 bits 7:4 are the mouse buttons
; Write these pins "high" with pullup resistors to
; support the mouse buttons.
; Port 1 bit 0 is the LED output
; Write this pin low with maximum current sink to turn
; on the LEDs.
Reset:
mov A, endpoint_0 ; move data stack pointer
swap A, dsp ; so it does not write over USB fifos
;
; initialize Port 0
;
mov A, Ptr_Current ; select midrange DAC setting
iowr Port0_Isink0 ; isink current Port 0 bit[0]
iowr Port0_Isink1 ; isink current Port 0 bit[1]
iowr Port0_Isink2 ; isink current Port 0 bit[2]
iowr Port0_Isink3 ; isink current Port 0 bit[3]
mov A, 0 ; select minimum DAC setting
iowr Port0_Isink4 ; isink current Port 0 bit[4]
iowr Port0_Isink5 ; isink current Port 0 bit[5]
iowr Port0_Isink6 ; isink current Port 0 bit[6]
iowr Port0_Isink7 ; isink current Port 0 bit[7]
mov A, 0fh ; disable Port 0 bit[3:0] pullups
iowr Port0_Pullup ; enable Port 0 bit[7:4] pullups
mov A, 0f0h ; initialize Port 0 data
iowr Port0_Data ; output zeros to Port 0 bit[3:0]
; output ones to Port 0 bit[7:4]
mov [port_temp], A
;
; initialize Port 1
;
mov A, LED_Current ; select maximum DAC setting
iowr Port1_Isink0 ; isink current Port 1 bit[0]
iowr Port1_Isink1 ; isink current Port 1 bit[1]
iowr Port1_Isink2 ; isink current Port 1 bit[2]
iowr Port1_Isink3 ; isink current Port 1 bit[3]
mov A, 0h ; enable Port 1 bit [7:0] pullups
iowr Port1_Pullup
mov A, 0feh ; turn on the LED on Port 1 bit[0]
iowr Port1_Data
mov A, 0
iowr Port0_Interrupt ; disable port 0 interrupts
iowr Port1_Interrupt ; disable port 1 interrupts
iowr Cext
;
; initialize variables
;
mov [buttons], A ; no buttons pushed
mov [horiz_state], A ; clear the horizontal state
mov [horizontal], A ; clear horizontal count
mov [vert_state], A ; clear the vertical state
mov [vertical], A ; clear vertical count
mov [endpoint_stall], A
mov [remote_wakeup_status], A
mov [configuration_status], A
mov [wakeup_counter], A
mov [wakeup_flag], A
mov [disch_counter], A
mov [horiz_position], A
mov [vert_position], A
mov [button_position], A
mov [button_flag], A
mov [button1_deb], A
mov [idle_period], A
mov [prev_idle_period], A
mov [new_idle_period], A
mov [new_idle_flag], A
mov [idle_period_counter], A
mov A,3 ; initialize suspend counter
mov [suspend_counter], A ; 3 msec idle, suspend
mov A,4 ; initialize 4ms_counter to 4
mov [4ms_counter], A ;
iowr Watchdog ; clear watchdog timer
; mov A, ENABLE_REMOTE_WAKEUP ; **** debug only ****
; mov [remote_wakeup_status], A
mov A, BOOT_PROTOCOL
mov [protocol_status], A
;
; test what kind of reset occurred
;
iord Status_Control
and A, USBReset ; test for USB Bus Reset
jnz BusReset
iord Status_Control
and A, WatchDogReset ; test for Watch Dog Reset
jz suspendReset
;
; Process a watchdog reset. Wait for a Bus Reset to bring the system
; alive again.
mov A, TIMER_ONLY ; enable one msec timer interrupt
mov [interrupt_mask],A
iowr Global_Interrupt
WatchdogHandler: ; wait for USB Bus Reset
jmp WatchdogHandler
suspendReset:
mov A, 09h
iowr Status_Control ; go back to suspend
nop
jmp suspendReset ; wait until real bus reset
;
; Either a bus reset or a normal reset has occurred
;
BusReset:
mov A, RunBit ; clear all reset bits
iowr Status_Control
; setup for enumeration
mov A, ENUMERATE_MASK
mov [interrupt_mask],A
iowr Global_Interrupt
wait: ; wait until configured
iord USB_EP1_TX_Config
cmp A, 0
jz wait
;*******************************************************
; main loop
; Purpose: This routine is the code for implementing
; a mouse function. It is divided into three
; parts; buttons, horizontal movement, and
; vertical movement. See the documentation
; for an explanation of the movement
; state machines.
;
;*******************************************************
main:
iord Port0_Data ; read and store port 0
mov [port_temp], A
call ReadButtons ; read the buttons
call CheckHorizontal ; check for horizontal movement
call CheckVertical ; check for vertical movement
mov A, [horizontal]
cmp A, 0h
jz NoChangeHorizontal
jmp send_packet
NoChangeHorizontal:
mov A, [vertical]
cmp A, 0h
jz NoChangeVertical
jmp send_packet
NoChangeVertical:
mov A, [button_flag]
cmp A, 0h
jz NoChangeButtons
jnz send_packet
NoChangeButtons:
mov A, [idle_period] ;if idle period is 0
cmp A, 0h ;report is sent only if changes
jz Nosend
dec A ; check if idle_period <= idle_period_counter
cmp A, [idle_period_counter]
jnc Nosend
send_packet:
iord USB_EP1_TX_Config
and A, 80h
cmp A, 80h
jz Nosend
mov A, [horizontal]
mov [horiz_position], A
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -