📄 usbled.asm
字号:
;====================================================================
; USB I/O controll card : 输出-> LED
;====================================================================
include "63000.inc"
;Received data:
Data_Byte0: equ 38h
;Data_Byte1: equ 39h
;Data_Byte2: equ 3Ah
;Data_Byte3: equ 3Bh
;Data_Byte4: equ 3Ch
;Data_Byte5: equ 3Dh
;Data_Byte6: equ 3Eh
;Data_Byte7: equ 3Fh
;Other variables:
suspend_counter: equ 35h ;number of idle bus milliseconds
loop_temp: equ 37h ;temporary loop variable
start_send: equ 32h ;0=false, 1=true
interrupt_mask: equ 20h
endp0_data_toggle: equ 24h
loop_counter: equ 25h
data_start: equ 26h
data_count: equ 27h
endpoint_stall: equ 28h
;======================================================================
;interrupt vectors
;======================================================================
org 00h ; Reset vector; begin here after a reset.
jmp Reset
org 02h ; 128-microsecond interrupt
jmp DoNothing_ISR
org 04h ; 1024-millisecond interrupt
jmp One_mSec_ISR
org 06h ; endpoint 0 interrupt
jmp USB_EP0_ISR
org 08h ; endpoint 1 interrupt
jmp USB_EP1_ISR
org 0Ah ; reserved interrupt
jmp Reset
org 0Ch ; general purpose I/O interrupt
jmp GPIO_ISR ; not used
org 0Eh ; Wakeup_ISR or resume interrupt
jmp DoNothing_ISR ; not used
ORG 10h
;======================================================================
;Interrupt routines
;======================================================================
;----------------------------------------------------------------------
; 128-microsecond interrupt, Cext
; Unused. If this interrupt occurs, just re-enable the interrupts.
;----------------------------------------------------------------------
DoNothing_ISR:
push A
;Enable interrupts and return
mov A,[interrupt_mask]
ipret Global_Interrupt
;----------------------------------------------------------------------
; 1-millisecond interrupt
; Check to see if the chip is in suspend mode.
; Copy values to Endpoint 1's buffer for sending.
;----------------------------------------------------------------------
One_mSec_ISR:
push A
;This watchdog reset is here until I figure out
;where else in the code the watchdog is timing out!
iowr Watchdog
;Find out if enumeration is complete.
;If enumerating is in progress, loop_temp = 0.
mov A, [loop_temp]
cmp A, 0h
;If enumeration is still in progress, jump.
jz not_main
;Enumeration has ended, so decrement the loop counter
;(so it no longer = 0).
dec [loop_temp]
not_main:
;Check for bus activity.
iord USB_Status_Control
and A, 01h
cmp A,0h
;If no bus activity, increment the suspend counter.
jz Inc_counter
;If bus activity detected, clear the bus-activity bit,
iord USB_Status_Control
and A, 0FEh
iowr USB_Status_Control
;and clear the suspend counter.
mov A, 0h
mov [suspend_counter], A
jmp Suspend_end
Inc_counter:
;Keep track of the amount of time with no bus activity.
inc [suspend_counter]
;Get the number of milliseconds the bus has been idle.
mov A, [suspend_counter]
;Has it been 3 milliseconds?
cmp A, 03h
;If no, there's nothing else to do.
jnz Suspend_end
;If yes, put the chip in Suspend mode.
;Clear the Suspend counter.
mov A, 0h
mov [suspend_counter], A
;Set the Suspend bit. The chip is now in Suspend mode.
iord Status_Control
or A, 08h
iowr Status_Control
nop
Suspend_end:
;Is endpoint 1 enabled?
iord USB_EP1_TX_Config
cmp A,0
;If no, do nothing.
jz Select
;If yes, is start_send = 1?
;(Start_send adds a short delay after enumeration.)
mov A, [start_send]
cmp A, 01h
;If no, do nothing
jnz Select
;If yes, send data:
jmp send_value
send_value:
;Copies values from RAM into Endpoint 1's buffer
;and enables sending the bytes on the next poll.
;disable Endpoint 1 interrupts
mov A,[interrupt_mask]
and A, EFh
mov [interrupt_mask],A
iowr Global_Interrupt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Copy values from RAM to Endpoint 1's FIFO for transmitting to the host.
;One byte:
mov A, [Data_Byte0]
mov [Endpoint1_Byte0], A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Configure Endpoint 1's transmit register
;so that the bytes will transmit on the next poll.
iord USB_EP1_TX_Config
;Don't change the Data 0/1 bit.
and A,40h
;Bits 4 and 7 enable transmitting.
;The low nibble is the number of data bytes (2).
or A,91h
iowr USB_EP1_TX_Config
Select:
;Enable Endpoint 1 interrupts.
mov A,[interrupt_mask]
or A, 10h
mov [interrupt_mask],A
ipret Global_Interrupt
;----------------------------------------------------------------------
;GPIO interrupt
;Can be configured to trigger when a port bit toggles.
;Unused here.
;----------------------------------------------------------------------
GPIO_ISR:
push A
push X
pop X
mov [interrupt_mask],A
ipret Global_Interrupt
;----------------------------------------------------------------------
;Endpoint 1 ISR
;Endpoint 1 can do IN (device to host) transfers only.
;This interrupt triggers when the host acknowledges
;receiving data from endpoint 1.
;The ISR just toggles the data 0/1 bit for the next transaction and
;returns.
;----------------------------------------------------------------------
USB_EP1_ISR:
push A
;Toggle the data 0/1 bit so it's correct for the next transaction.
iord USB_EP1_TX_Config
xor A,40h
;The interrupt clears the EnableRespondToIN bit (bit 7) in the TX Config.
;Set this bit to 1 so data will go out on the next interrupt.
or A, 91h
iowr USB_EP1_TX_Config
;Enable interrupts and return.
mov A, [interrupt_mask]
ipret Global_Interrupt
;----------------------------------------------------------------------
; Reset processing
; Triggers on Reset or "reserved" interrupt.
;To be safe, initialize everything.
;----------------------------------------------------------------------
Reset:
;Place the data stack pointer at the lowest address of Endpoint 0's FIFO.
;This keeps the stack from writing over the USB FIFOs.
;The USB FIFOs are in high RAM;
;the data stack pointer pre-decrements on a Push instruction.
mov A, Endpoint_0
swap A, dsp
;Initialize variables to FFh
mov a,00h
iowr Port0_Data ; output ones to port 0
mov A, ffh
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
iowr Port0_Isink0 ; maximum sink current Port0 bit 0
iowr Port0_Isink1 ; maximum sink current Port0 bit 1
iowr Port0_Isink2 ; maximum sink current Port0 bit 2
iowr Port0_Isink3 ; maximum sink current Port0 bit 3
iowr Port0_Isink4 ; maximum sink current Port0 bit 4
iowr Port0_Isink5 ; maximum sink current Port0 bit 5
iowr Port0_Isink6 ; maximum sink current Port0 bit 6
iowr Port0_Isink7 ; maximum sink current Port0 bit 7
;Initialize variables to 00h
mov A, 0h
iowr Port1_Data ; output zeros to port 1
iowr Port0_Interrupt ; disable port 0 interrupts
iowr Port0_Pullup ; enable port 0 pullups
mov [Endpoint1_Byte0],A
mov [Endpoint1_Byte1],A
mov [Endpoint1_Byte2],A
mov [endpoint_stall], A
mov [remote_wakeup_status], A
mov [configuration_status], A
mov [loop_temp], A
mov [start_send], A
iowr Watchdog ; clear watchdog timer
;Test what kind of reset occurred: bus or watchdog
iord Status_Control
;Was it a bus reset?
and A, USBReset
;If yes, jump to handle it.
jnz BusReset
iord Status_Control
;Was it a watchdog reset?
and A, WatchDogReset
;If no, continue to wait for a bus reset
jz suspendReset
mov A, TIMER_ONLY
mov [interrupt_mask],A
iowr Global_Interrupt
;Wait for a bus reset.
WatchdogHandler:
jmp WatchdogHandler
suspendReset:
;Return to suspend mode to wait for a USB bus reset.
mov A, 09h
iowr Status_Control
nop
jmp suspendReset
BusReset:
;Clear all reset bits.
;Set bit 0 (the run bit).
mov A, RunBit
iowr Status_Control
;Set up for enumeration (Endpoint 0 and 1-millisecond interrupts enabled)
mov A, ENUMERATE_MASK
mov [interrupt_mask],A
iowr Global_Interrupt
wait:
;Wait until configured.
iord USB_EP1_TX_Config
cmp A, 0
;Clear the watchdog timer
iowr Watchdog
;If not configured, continue to wait.
jz wait
mov A, 0ffh
mov [loop_temp], A
;Enable endpoint 1
iord USB_EP1_TX_Config
or A, 91h
iowr USB_EP1_TX_Config
;======================================================================
; The main program loop.
;======================================================================
main:
;Find out if the loop_temp delay has timed out.
;Loop_temp =0 if not timed out, FFh if timed out.
mov A, [loop_temp]
cmp A, 0Ah
;If no, don't enable transmitting.
jnc no_set
;If yes, enable transmitting.
mov A, 01h
mov [start_send],A
no_set:
;Clear the watchdog timer (accumulator=0)
;This has to be done at least once every 3 milliseconds!
; mov A,00h
; iowr Port0_Data ; output ones to port 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -