📄 usb232.asm
字号:
include "63000.inc"
;Received data:
Data_Byte0: equ 38h
;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
data_send: equ 28h ; start of data to be sent
hi_data_count: equ 60h ; high byte of data count
low_data_count: equ 61h ; low byte of data count
loop_num: equ 62h ; loop number (USB sending)
temp2: equ 63h ; temporary variable
send_ptr: equ 7Dh ; Send buffer ptr
;======================================================================
;interrupt vectors
;======================================================================
org 00h ; Reset vector; begin here after a reset.
jmp Reset
org 02h ; 128-microsecond interrupt
jmp Serial_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
include "rs232.asm"
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!
;************************************************************************
; This is the main loop that is entered after reset processing
;************************************************************************
;main:
call SerialInitialize
iowr Watchdog ; clear watchdog timer
call put_String
call putCommand
call delay1
; call getSerial
; iowr Watchdog
nochange:
jmp main
put_String:
push A ; Save the accumulator.
push X ; Save the index register.
call initialize_req
mov A,[Data_Byte0] ; Load ASCII 'I' into accumulator
mov [X + txBuf], A ; Write into the buffer.
pop X ; Restore the index.
pop A ; Restore the accumulator.
ret ; Return to caller.
;*******************************************************************
; This routine initializes the sending of requests to the UPS
;*******************************************************************
initialize_req:
call delay
call Clear_rxBuf
mov A, 00h ;
mov [rxBufPtr], A ; Reset the receive buffer pointer.
mov [txBufPtr], A ;
mov X, [txBufPtr] ;
ret
;************************************************************************
; This routine ends the transmission loading part, transmits the commands
; and receives the result from the UPS
;************************************************************************
end_req:
mov [X + txBuf], A
inc [txBufPtr] ; Increment tx buffer pointer
mov X, [txBufPtr]
mov A, Car_Ret ; Load carriage return into accumulator
mov [X + txBuf], A
inc [txBufPtr] ; Increment tx buffer pointer
mov X, [txBufPtr]
mov A, Ln_Fd ; Load line feed into accumulator
mov [X + txBuf], A
call putCommand ; Send command to UPS
call getSerial ; Receive result from UPS
ret
;**********************************************************************
; This is the routine that is entered when a data item from the UPS is
; requested and returns with the string resident in the receive buffer.
;**********************************************************************
putCommand:
mov A, 00h ; Clear the accumulator.
mov [txBufPtr], A ; Reset tx buffer pointer.
iowr Watchdog ; Clear watchdog timer.
mov X, [txBufPtr] ; Set the index.
mov A,[X + txBuf] ; Load Command Byte Zero.
mov [txData], A ; Put it in the transmit register.
call txRoutine ; Go transmit the byte.
iowr Watchdog ; Ping the watch dog timer.
call delay1 ; Give the serial device some time.
iowr Watchdog ; clear watchdog timer
ret ; Return to sender.
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.
;----------------------------------------------------------------------
;----------------------------------------------------------------------
;The endpoint 0 ISR supports the control endpoint.
;This code enumerates and configures the hardware.
;It also responds to Set Report requests that receive data from the host.
;----------------------------------------------------------------------
USB_EP0_ISR:
push A
iord USB_EP0_RX_Status
;Has a Setup packet been received?
and A, 01h
;If no, ignore.
jz check_for_out_packet
;If yes, handle it.
;Disable endpoint 0 interrupts.
mov A,[interrupt_mask]
and A, 0F7h
mov [interrupt_mask], A
iowr Global_Interrupt
;Find out what the setup packet contains and handle the request.
call StageOne
;Re-enable Endpoint 0 interrupts.
mov A, [interrupt_mask]
or A, 08h
mov [interrupt_mask], A
jmp done_with_packet
check_for_out_packet:
iord USB_EP0_RX_Status
;Is it an OUT packet?
and A, 02h
;If no, ignore it.
jz done_with_packet
;If yes, process the received data.
;Disable Endpoint 0 interrupts.
mov A,[interrupt_mask]
and A, 0F7h
mov [interrupt_mask], A
iowr Global_Interrupt
push X
;data_count holds the number of bytes left to read.
;X holds the index of the address to read
;and the index of the address to store the received data.
;Initialize the X register.
mov X, 0
Get_Received_Data:
;Find out if there are any bytes to read.
mov A, 0
cmp A, [data_count]
;Jump if nothing to read.
jz DoneWithReceivedData
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Get a byte.
mov A, [X + Endpoint_0]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov [X + Data_Byte0], A
; cpl a
; iowr Port0_Data
;Decrement the number of bytes to read.
dec [data_count]
;Increment the address to read.
inc X
;Do another
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -