📄 usbjoy32.asm
字号:
iowr Global_Interrupt
jmp TaskLoop
;========================================
; Task 14: Read Resistor Value for z_R2
;========================================
Task14:
mov a, 30h
iowr Global_Interrupt ;Enable only Capture interrupts
;**********************************************
;P0.0 = CMOS Hi-Z
;P0.1 = TTL Hi-Z
;P0.5 = High Sink
;P0.2/P0.3/P0.4/P0.6/P0.7 = CMOS Hi-Z
;Port0_Mode0 = 10000000
;Port0_Mode1 = 10000000
;Port0 = 00000010
;**********************************************
mov a, 80h ;Set port and port mode values to discharge capacitor
iowr Port0_Mode0 ;See table above
iowr Port0_Mode1
mov a, 02h
iowr Port0
mov a, 00h ;wait about 500usec (6000 cycles) for Capture_timer A & B ISRs, then recharge cap and do math below
mov [discharge_cnt], a
.discharge_loop:
inc [discharge_cnt]
mov a, CCh
cmp a, [discharge_cnt]
iowr Watchdog
jnz .discharge_loop
mov a, 00h
iowr Global_Interrupt ;Disable global interrupts
mov a, 00h
mov [rollover_bit], a ;rollover_bit set to 00h, but may need to change to 01h, if TTL value is < CMOS value
iord Capture_TimerA_Falling ;Read CaptureTimerA 8 bits, CMOS captured time value (always earlier and usually the smaller value)
mov [capture_a_temp], a
iord Capture_TimerB_Falling ;Read CaptureTimerB 8 bits, TTL captured time value (always earlier and usually the larger value)
mov [capture_b_temp], a
sub a, [capture_a_temp] ;Subtract CMOS time from TTL time to see if timer rolled over
jnc .no_timer_rollover ;If TTL value is > CMOS value, the timer did not roll over and we keep rollover_bit = 00h
mov a, 01h ;In the exception that TTL time value is < CMOS time value, we make rollover_bit = 01h
mov [rollover_bit], a
.no_timer_rollover:
mov a, FEh ;Recharges the capacitor, P0.0 is Hi-Z CMOS always, others set to Strong Drive CMOS
iowr Port0_Mode0
iowr Port0_Mode1
iowr Port0
SUB16x16 rollover_bit, capture_b_temp, 00h, capture_a_temp, always_zero, z_R2_diff2_new
; perform calculations to average the joystick readings (R_1st + R_2nd)/2
AVERAGE8x8 z_R1_diff1_new, z_R1_diff2_new, z_R1_diff1_old, z_R1_diff2_old, RunningCarry, RunningSum, z_R1_average
AVERAGE8x8 z_R2_diff1_new, z_R2_diff2_new, z_R2_diff1_old, z_R2_diff2_old, RunningCarry, RunningSum, z_R2_average
; perform calculations below to average and normalize the joystick position for more accuracy (R1*256)/(R1+R2)
ADD8x8wCarry z_R1_average, z_R2_average, divider_bottom_hi, divider_bottom_lo, z_R12_Sum_MSB, z_R12_Sum_LSB
mov a, [z_R1_average] ;Top of division equation gets R1, then it is "multiplied" by 256
mov [divider_top_hi], a
mov a, 00h
mov [divider_top_lo], a ;This is the LSByte of R1 in div equation, effectively "multiplies" it by 256
DIV16x16 divider_bottom_hi, divider_bottom_lo, divider_top_hi, divider_top_lo ; (R1*256)/(R1+R2)
mov a, [divider_top_lo] ; this is actually the joystick z position
mov [z_position], a
mov a, 05h ;Re-Enable 1ms,USBReset interrupts
iowr Global_Interrupt
jmp TaskLoop
;==========================================================
; Task 15:
;
; Fill endpoint buffer FIFO with Axis & button data
;==========================================================
Task15:
mov a, [00h] ; Fill endpoint buffer for sending to host
mov [ep1_dmabuff+0], a
mov a, [x_position]
mov [ep1_dmabuff+1], a
mov a, [00h]
mov [ep1_dmabuff+2], a
mov a, [y_position]
mov [ep1_dmabuff+3], a
mov a, [00h]
mov [ep1_dmabuff+4], a
mov a, [z_position]
mov [ep1_dmabuff+5], a
mov a, [hat_buttons]
mov [ep1_dmabuff+6], a
mov a, [fire_buttons]
mov [ep1_dmabuff+7], a
mov a, [x_R1_diff1_new] ;move new X resitor values to old X values for next calculations
mov [x_R1_diff1_old], a
mov a, [x_R2_diff1_new]
mov [x_R2_diff1_old], a
mov a, [x_R1_diff2_new]
mov [x_R1_diff2_old], a
mov a, [x_R2_diff2_new]
mov [x_R2_diff2_old], a
mov a, [y_R1_diff1_new] ;move new Y resitor values to old Y values for next calculations
mov [y_R1_diff1_old], a
mov a, [y_R2_diff1_new]
mov [y_R2_diff1_old], a
mov a, [y_R1_diff2_new]
mov [y_R1_diff2_old], a
mov a, [y_R2_diff2_new]
mov [y_R2_diff2_old], a
mov a, [z_R1_diff1_new] ;move new Z resitor values to old Z values for next calculations
mov [z_R1_diff1_old], a
mov a, [z_R2_diff1_new]
mov [z_R2_diff1_old], a
mov a, [z_R1_diff2_new]
mov [z_R1_diff2_old], a
mov a, [z_R2_diff2_new]
mov [z_R2_diff2_old], a
mov A, [ep1_data_toggle] ; preserve data toggle bit
or A, 08h ; send back 8 words to host
iowr Ep1_Count
mov a, ACK_IN ;Set to ack on endpoint 1
iowr Ep1_Mode ;USB mode is ACK in - Status Out, data is ready, send it to host
jmp TaskLoop
;*******************************************************
;
; Interrupt handler: BusResetISR
; Purpose: The program jumps to this routine when
; the microcontroller has a bus reset.
;
;*******************************************************
BusResetISR:
; At this point, endpoint 0 does not expect any packet except a SETUP.
; Set endpoint 0 mode to STALL INs&OUTs.
mov A, STALL_IN_OUT
iowr Ep0_Mode
; Enable USB address 0. If not enabled, the device's SIE does not respond
; to USB traffic sent to the device's address.
mov A, ADDRESS_ENABLE
iowr Usb_Address
; At this point, data endpoints (endpoint 1/or 2) does not respond to any
; USB traffic. A SetConfiguation at the end of the enumeration will enable the endpoint.
mov A, DISABLE
iowr Ep1_Mode
; Bus Reset is an interrupt. Upon entering the BusResetISR, the hardware
; automatically pushes the pc onto the psp. The "reti" or "ret" instruction at the end
; of the ISR will "pop" the pc back. In this case, the BusResetISR does not
; perform a "reti" but a "jmp" to the "Reset" vector. Therefore, firmware must reset
; program stack pointer to clear the 2 bytes pc that the hardware "pushes" on the psp.
mov A, 00h
mov psp,a
jmp Reset
;*******************************************************
;
; Interrupt handler: 1msTimerISR
; Purpose: Every 1ms this interrupt handler clears
; the Watchdog timer. If there's no bus
; activity for 3-4ms. This ISR puts the
; microcontroller into suspend mode.
;
;*******************************************************
1msTimerISR:
push A
; clear Watchdog timer
iowr Watchdog
; Clear [new_task] to zero to flag the main program loop (TaskLoop) that
; the 1ms time slice for the current task has been used up. Go execute
; the next task.
mov a, 00h
mov [new_task], a
; Each task is allocated 1ms. Every 1ms, the firmware increases [task_number] to
; tell the main loop what the next task is.
inc [task_number]
; check for no bus activity. Increase [suspend_count] if there's no bus activity since
; the last 1ms interrupt. The main loop will put the part into suspend if [suspend_count]==4.
1ms_suspend_timer:
iord Usb_Status_Control ; read bus activity bit
and A, BUS_ACTIVITY ; mask off activity bit
jnz bus_activity
inc [suspend_count] ; increment suspend counter
mov A, [suspend_count]
cmp A, 04h ; if no bus activity for 3-4ms,
jz usb_suspend ; then go into low power suspend
jmp ms_timer_done
usb_suspend:
; enable wakeup timer
mov A, (USB_RESET_INT)
iowr Global_Interrupt
iord Processor_Status_Control
or A, SUSPEND ; set suspend bit
ei
iowr Processor_Status_Control
nop
; look for bus activity, if none go back into suspend
iord Usb_Status_Control
and A, BUS_ACTIVITY
jz usb_suspend
; re-enable interrupts
mov A, (1MS_INT | USB_RESET_INT)
iowr Global_Interrupt
bus_activity:
mov A, 00h ; reset suspend counter
mov [suspend_count], A
iord Usb_Status_Control
and A, ~BUS_ACTIVITY ; clear bus activity bit
iowr Usb_Status_Control
ms_timer_done:
pop A
reti
;*******************************************************
;
; Interrupt: Endpoint0ISR
; Purpose: Usb control endpoint handler. This interrupt
; handler formulates responses to SETUP and
; CONTROL READ, and NO-DATA CONTROL transactions.
;
; Jump table entry formulation for bmRequestType and bRequest
;
; 1. Add high and low nibbles of bmRequestType.
; 2. Put result into high nibble of A.
; 3. Mask off bits [6:4].
; 4. Add bRequest to A.
; 5. Double value of A (jmp is two bytes).
;
;*******************************************************
Endpoint0ISR:
push X
push A
;Reading Ep0_Mode enables writing to the endpoint's buffer.
iord Ep0_Mode
;If EP0_ACK isn't set, the transaction didn't complete with an Ack,
;so exit the ISR.
and A, EP0_ACK
jz ep0_done
call EP0IntHandler
ep0_done: ;ParseSetup returns here. Exit ISR
pop A
pop X
reti
;*******************************************************
;
; Interrupt handler: endpoint1_ISR
; 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
;
;*******************************************************
Endpoint1ISR:
push A
iord Ep1_Mode ; if the interrupt was caused by a NAK, set the mode to NAK
and A, EP_ACK ; and exit the isr.
jz endpoint1_NAK
; change data toggle
mov A, 80h
xor [ep1_data_toggle], A
; set response
mov A, [ep1_stall] ; if endpoint is set to stall, then set
cmp A, FFh ; endpoint mode to stall
jnz endpoint1_NAK ; if not, set ep mode to NAK
mov A, STALL_IN_OUT
iowr Ep1_Mode
jmp endpoint1_done
endpoint1_NAK:
mov A, NAK_IN ; clear the ACK bits
iowr Ep1_Mode
endpoint1_done:
pop A
reti
;*******************************************************
;
; Interrupt handler: endpoint2_ISR
; Purpose: This interrupt is not implemented in the
; frameworks.
;*******************************************************
Endpoint2ISR:
reti
;*******************************************************
;
; Interrupt handler: 128us_ISR
; Purpose: This interrupt is not implemented in the
; frameworks.
;*******************************************************
128usTimerISR:
reti
;*******************************************************
;
; Interrupt handler: SPI_ISR
; Purpose: This interrupt is not implemented in the
; frameworks.
;*******************************************************
SpiISR:
reti
;*******************************************************
;
; Interrupt handler: CaptureTimerAISR
; Purpose: CMOS captured time related to cap discharge thru pot.
;*******************************************************
CaptureTimerAISR: ;This is the CMOS capture timer ISR
reti
;*******************************************************
;
; Interrupt handler: CaptureTimerBISR
; Purpose: TTL captured time related to cap discharge thru pot.
;*******************************************************
CaptureTimerBISR: ;This is the TTL capture timer ISR
mov a, 00h
iowr Global_Interrupt ;Disable global interrupts
reti
;*******************************************************
;
; Interrupt handler: GpioISR
; Purpose: This interrupt is not implemented in the
; frameworks.
;*******************************************************
GpioISR:
reti
;*******************************************************
;
; Interrupt handler: wake_up_ISR
; Purpose: This interrupt is not implemented in the
; frameworks.
;*******************************************************
WakeUpISR:
reti
INCLUDE "EP0IntHandler.asm"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -