📄 js50.asm
字号:
ipret Global_Interrupt ; enable interrupts and return
;************************************************************************
; The 1 msec interrupt is used to check for suspend and start an
; analog measurement.
One_mSec_ISR:
push A ; save accumulator on stack
mov A, [loop_temp] ; Before enumeration end value is zero
cmp A, 0h
jz not_main ; Enumeration has not ended
dec [loop_temp] ; Enumeration ended decrement counter
not_main:
; suspend checking
iord USB_Status_Control ; check if there is no bus activity
and A, 01h
cmp A,0h
jz Inc_counter ; no bus activity
iord USB_Status_Control ; clear the bus activity bit
and A, 0FEh
iowr USB_Status_Control
mov A, 0h ; clear the suspend counter
mov [suspend_counter], A
jmp Suspend_end
Inc_counter:
inc [suspend_counter]
mov A, [suspend_counter] ; get idle msec counts
cmp A, 03h ; check if 3msecs of bus inactivity passed
jnz Suspend_end ; less than 3msecs
mov A, 0h ; clear the suspend counter
mov [suspend_counter], A
mov A, 0h ; Enable Pullup on port1 lines
iowr Port1_Pullup
mov A, 0ffh
iowr Port1_Data
iord Status_Control ;set the suspend bit causing suspend
or A, 08h
iowr Status_Control
nop
mov A, 0ffh ; Disable Pullup on port1 lines
iowr Port1_Pullup
mov A, 0h
iowr Port1_Data
Suspend_end:
; Starting an analog measurement requires three steps:
; 1. discharge the timing capacitor
; 2. start charging the timing capacitor
; 3. read and save the start time.
and A, 0h ; clear carry flag
mov A, [testbit] ; select analog channel for measurement
rrc A
jnz storeBit
iord USB_EP1_TX_Config
cmp A,0 ; test whether endpoint enabled
jz Select
mov A, [start_send]
cmp A, 01h
jnz Select
; Check if values have changed
mov A, [X_Value_old]
cmp A, [X_Value]
jnz send_value
mov A, [Y_Value_old]
cmp A, [Y_Value]
jnz send_value
mov A, [Z_Value_old]
cmp A, [Z_Value]
jnz send_value
mov A, [hat_bits_old]
cmp A, [hat_bits]
jnz send_value
mov A, [button_bits_old]
cmp A, [button_bits]
jnz send_value
mov A, [Throttle_old]
cmp A, [Throttle]
jnz send_value
jmp Select
send_value:
iord USB_EP1_TX_Config
and A,40h ; keep the Data 0/1 bit
or A,96h ; enable transmit 6 bytes
iowr USB_EP1_TX_Config
; Save transmitted values as old values
mov A, [X_Value]
mov [X_Value_old], A
mov A, [Y_Value]
mov [Y_Value_old], A
mov A, [Z_Value]
mov [Z_Value_old], A
mov A, [hat_bits]
mov [hat_bits_old], A
mov A, [button_bits]
mov [button_bits_old], A
mov A, [Throttle]
mov [Throttle_old], A
Select:
mov A,8 ; select fourth channel
storeBit:
mov [testbit],A ; start charge cycle
iowr Port1_Data
; The initial assumption is the start time will always be zero, since
; the measurement is synced with the one millisecond interrupt. The
; problem with that assumption is there could be a delay due to a USB
; ISR before this interrupt is recognized.
iord Timer ; read free-running timer
mov [start_time],A ; save start value
mov A,[interrupt_mask] ; prevent endpoint_1 interrupts
and A, EFh ; preventing jitter
mov [interrupt_mask],A
ipret Global_Interrupt ; enable interrupts and return
;************************************************************************
; The GPIO interrupt will be the end of an analog measurement on one
; of the four analog input channels in Port 1. Complete the measurement
; as a time critical problem, then setup for the next measurement.
GPIO_ISR:
push A ; save the accumulator to stack
push X ; save X on stack
iord Timer ; read timer
push A ; save stop time value
mov A,0 ; discharge timing capacitor
iowr Port1_Data
; We need to convert from a bit map to an index that allows us to store
; the result:
; 0001 => 000 X
; 0010 => 001 Y
; 0100 => 101 Throttle
; 1000 => 010 Z
mov X,0 ; clear counter
mov A,[testbit] ; load bit under test
rrc A ; test X value
jc done ; index=0 for X value
inc X
rrc A ; test Y value
jc done ; index=1 for Y value
mov X,5
rrc A ; test Throttle
jc done ; index=5 for Throttle
mov X,2 ; index=2 for Z value
;****************************************************************
; Jitter minimization subroutine
; In this subroutine the value of the joystick movement is being
; calculated and the jitter is being minimized by reducing the
; precision by 2 bits.
done:
pop A ; restore stop time value
sub A,[start_time] ; calculate the difference
mov [jitter_temp],A
mov A, [X+endpoint_1] ; get previous value
cmp A, [jitter_temp] ; compare previous to current value
jc next_minus_prev
sub A, [jitter_temp] ; previous > current
jmp check_diff
next_minus_prev:
mov A, [jitter_temp] ; current > previous
sub A, [X+endpoint_1]
check_diff:
cmp A, 4h ; check difference
jnc nojitter
mov A, [X+endpoint_1] ; send previous value
mov [jitter_temp],A
nojitter:
mov A, [jitter_temp] ; send current value
mov [X+endpoint_1],A ; store the measurement
pop X ; restore X from stack
mov A, [interrupt_mask] ; enable enpoint_1 interrupts
or A, 10h
mov [interrupt_mask],A
ipret Global_Interrupt ; enable interrupts and return
;********************** Endpoint_1_ISR **************************
USB_EP1_ISR:
push A ; save accumulator on stack
iord USB_EP1_TX_Config
xor A,40h ; flip data 0/1 bit
iowr USB_EP1_TX_Config
mov A, [interrupt_mask]
ipret Global_Interrupt ; enable interrupts and return
;************************************************************************
; 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.
Reset:
mov A, endpoint_0 ; move data stack pointer
swap A, dsp ; so it does not write over USB FIFOs
mov A, 0ffh ; load accumulator with ones
iowr Port0_Data ; output ones to port 0
iowr Port1_Pullup ; disable port 1 pullups
; select rising edge interrupts
iowr Port1_Isink0 ; maximum isink current Port1 bit 0
iowr Port1_Isink1 ; maximum isink current Port1 bit 1
iowr Port1_Isink2 ; maximum isink current Port1 bit 2
iowr Port1_Isink3 ; maximum isink current Port1 bit 3
mov A, 0h ; load accumulator with zeros
iowr Port1_Data ; output zeros to port 1
iowr Port0_Interrupt ; disable port 0 interrupts
iowr Port0_Pullup ; enable port 0 pullups
iowr Port0_Isink0 ; minimum sink current Port0 bit 0
iowr Port0_Isink1 ; minimum sink current Port0 bit 1
iowr Port0_Isink2 ; minimum sink current Port0 bit 2
iowr Port0_Isink3 ; minimum sink current Port0 bit 3
iowr Port0_Isink4 ; minimum sink current Port0 bit 4
iowr Port0_Isink5 ; minimum sink current Port0 bit 5
iowr Port0_Isink6 ; minimum sink current Port0 bit 6
iowr Port0_Isink7 ; minimum sink current Port0 bit 7
mov [hat_bits],A ; clear remembered hat bits
mov A, 80h ; default the analog channels
mov [X_Value],A ; X axis
mov [Y_Value],A ; Y axis
mov [Z_Value],A ; Z axis (rotation)
mov [Throttle],A ; throttle
mov A,8 ; initialize analog channel
mov [testbit],A ; select channel four
mov A, 0h
mov [endpoint_stall], A
mov [remote_wakeup_status], A
mov [configuration_status], A
mov [loop_temp], A
mov [start_send], A
mov [X_Value_old], A
mov [Y_Value_old], A
mov [Z_Value_old], A
mov [hat_bits_old], A
mov [button_bits_old], A
mov [Throttle_old], A
iowr Watchdog ; clear watchdog timer
mov A, 0fh
iowr Port1_Interrupt ; enable port 1 interrupts
;
; 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
;
; A bus 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
iowr Watchdog ; clear watchdog timer
jz wait
mov A, 0ffh ; initializes loop temp
mov [loop_temp], A
; loop_temp is used to add a delay in the start of transmission of data
; The delay will start after reaching this point. This means that the
; transmission of data from endpoint 1 will not start right after enumeration
; is complete but is going to be delayed. Until the transmission begins
; the controller will Nak any IN packets to endpoint 1. If data exists
; the first IN packet to enpoint 1 that will be responded to with data
; from the controller is after 230msec from enumeration end.
; This was done to solve driver problems when the joystick was plugged in and
; then the power was recycled or when the joystick was plugged in before the host
; was turned on. The joystick driver could not handle the data right after
; enumeration.
;************************************************************************
; This is the main loop that endlessly repeats the same sequence over
; and over.
main:
mov A, [loop_temp]
cmp A, 0Ah
jnc no_set ; do not enable TX yet
mov A, 01h ; enable transmission
mov [start_send], A ; after this loop_temp value doesn't matter
no_set:
iowr Watchdog ; clear watchdog timer
iord Port0_Data ; read Port 0
cpl A ; invert the buttons
push A ; save A on stack
and A,BUTTON_MASK ; mask button bits
mov [button_bits], A ; save the button status
pop A ; restore A from stack
and A,HAT_MASK
jz storeHat ; no hat button pressed
mov [temp],A
Test1st:
and A,10h ; test first button
jz Test2nd
mov A,[temp]
and A,0E0h ; test for multiple buttons
jnz nochange ; hold current state
mov A,FORWARD ; "forward" button is pressed
jmp storeHat
Test2nd:
mov A,[temp]
and A,20h ; test second button
jz Test3rd
mov A,[temp]
and A,0D0h ; test for multiple buttons
jnz nochange ; hold current state
mov A,RIGHT ; "right" button is pressed
jmp storeHat
Test3rd:
mov A,[temp]
and A,40h ; test third button
jz Test4th
mov A,[temp]
and A,0B0h ; test for multiple buttons
jnz nochange ; hold current state
mov A,BACK ; "back" button is pressed
jmp storeHat
Test4th:
mov A,[temp]
and A,80h ; test fourth button
jz storeHat ; should never happen
mov A,[temp]
and A,070h ; test for multiple buttons
jnz nochange ; hold current state
mov A,LEFT ; "left" button is pressed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -