📄 usbhidio.asm
字号:
;Filename: usbhidio.asm
;Version: 1.3
;Date: 11/5/99
;Copyright 1999 by Jan Axelson (jan@lvr.com)
;
;Chip: Cypress Semiconductor CY7C63001 USB Microcontroller
;Assembler: cyasm.exe
;Purpose: demonstrates USB communications with an HID-class device
;Description:
;Handles all required standard USB and HID-class requests.
;Receives data from the host in output reports
;using interrupt transfers on Endpoint 1.
;Sends data to the host in input reports
;using control transfers on Endpoint 0.
;(The chip doesn't support OUT transfers on Endpoint 1.)
;I used Cypress Semiconductor's js50.asm joystick example code as a base
;in creating this program.
;The companion host software is the Visual-Basic project usbhidio.vbp.
;For more information, visit Lakeview Research at http://www.lvr.com .
;Send comments, bug reports, etc. to jan@lvr.com .
;Changes:
;V1.3: 11/20/99
;The length of the string descriptors is now correct.
;(Thanks, John Hyde)
;Changed the control_read routine to prevent error when sending a
;multiple of 8 bytes.
;(Thanks, Dave Wright)
;V1.2:
;added watchdog resets in wait loops,
;took out the watchdog reset in the 1-msec. timer ISR.
;V1.1:
;Clears the watchdog only in the main routine
;(so the watchdog will detect if the main routine crashes).
;Additions to the comments.
;V1.0:
;Clears the Watchdog timer on 1-msec. interrupt.
;(Not needed on the development board, but needed for stand-alone.)
;The Endpoint 1 ISR now sets bit 7 of Endpoint 1 TX config to 1.
;(The bit is cleared on EP1 interrupt.)
;======================================================================
;assembler directives (equates)
;======================================================================
;----------------------------------------------------------------------
;I/O registers
;----------------------------------------------------------------------
;I/O ports
Port0_Data: equ 00h ; GPIO data port 0
Port1_Data: equ 01h ; GPIO data port 1
Port0_Interrupt: equ 04h ; Interrupt enable for port 0
Port1_Interrupt: equ 05h ; Interrupt enable for port 1
Port0_Pullup: equ 08h ; Pullup resistor control for port 0
Port1_Pullup: equ 09h ; Pullup resistor control for port 1
;USB ports
USB_EP0_TX_Config: equ 10h ; USB EP0 transmit configuration
USB_EP1_TX_Config: equ 11h ; USB EP1 transmit configuration
USB_Device_Address: equ 12h ; USB device address assigned by host
USB_Status_Control: equ 13h ; USB status and control register
USB_EP0_RX_Status: equ 14h ; USB EP0 receive status
;Control ports
Global_Interrupt: equ 20h ; Global interrupt enable
Watchdog: equ 21h ; clear watchdog Timer
Timer: equ 23h ; free-running Timer
;GPIO Isink registers
Port0_Isink: equ 30h
Port0_Isink0: equ 30h
Port0_Isink1: equ 31h
Port0_Isink2: equ 32h
Port0_Isink3: equ 33h
Port0_Isink4: equ 34h
Port0_Isink5: equ 35h
Port0_Isink6: equ 36h
Port0_Isink7: equ 37h
Port1_Isink: equ 38h
Port1_Isink0: equ 38h
Port1_Isink1: equ 39h
Port1_Isink2: equ 3Ah
Port1_Isink3: equ 3Bh
;Control port
Status_Control: equ FFh
;----------------------------------------------------------------------
;Register bit values
;----------------------------------------------------------------------
;CPU Status and Control (Status_Control)
RunBit: equ 1h ; CPU Run bit
USBReset: equ 20h ; USB Bus Reset bit
WatchDogReset: equ 40h ; Watchdog Reset bit
; USB EP1 transmit configuration (USB_EP1_TX_Config)
DataToggle: equ 40h ; Data 0/1 bit
DISABLE_REMOTE_WAKEUP: equ 0 ; bit[1] = 0
ENABLE_REMOTE_WAKEUP: equ 2 ; bit[1] = 1
;----------------------------------------------------------------------
;Interrupt masks
;----------------------------------------------------------------------
;The timer-only mask enables the 1-millisecond timer interrupt.
TIMER_ONLY: equ 4h
;The enumerate mask enables the following interrupts:
;1-millisecond timer, USB Endpoint 0
ENUMERATE_MASK: equ 0Ch
;The runtime mask enables the following interrupts:
;1-millisecond timer, USB Endpoint 0, USB Endpoint 1, GPIO
RUNTIME_MASK: equ 5Ch
;----------------------------------------------------------------------
; USB Constants
; from the USB Spec v1.1
;----------------------------------------------------------------------
;standard request codes
get_status: equ 0
clear_feature: equ 1
set_feature: equ 3
set_address: equ 5
get_descriptor: equ 6
set_descriptor: equ 7
get_configuration: equ 8
set_configuration: equ 9
get_interface: equ 10
set_interface: equ 11
synch_frame: equ 12
; standard descriptor types
device: equ 1
configuration: equ 2
string: equ 3
interface: equ 4
endpoint: equ 5
; standard feature selectors
endpoint_stalled: equ 0 ; recipient endpoint
device_remote_wakeup: equ 1 ; recipient device
;----------------------------------------------------------------------
;HID-class descriptors
;from HID Class Definition v1.1 Draft
;----------------------------------------------------------------------
;Class-specific descriptor types from section 7.1 Standard Requests
HID: equ 21h
report: equ 22h
physical: equ 23h
;Class-specific request codes from section 7.2 Class Specific Requests
get_report: equ 1
get_idle: equ 2
get_protocol: equ 3
set_report: equ 9
set_idle: equ 10
set_protocol: equ 11
;----------------------------------------------------------------------
;USB buffer bytes
;----------------------------------------------------------------------
;Control Endpoint 0 buffer
Endpoint_0: equ 70h ; control endpoint
Endpoint0_Byte0: equ 70h ; Endpoint 0, byte 0
Endpoint0_Byte1: equ 71h ; Endpoint 0 byte 1
Endpoint0_Byte2: equ 72h ; Endpoint 0 byte 2
Endpoint0_Byte3: equ 73h ; Endpoint 0 byte 3
Endpoint0_Byte4: equ 74h ; Endpoint 0 byte 4
Endpoint0_Byte5: equ 75h ; Endpoint 0 byte 5
Endpoint0_Byte6: equ 76h ; Endpoint 0 byte 6
Endpoint0_Byte7: equ 77h ; Endpoint 0 byte 7
;Endpoint 0 SETUP packet bytes
bmRequestType: equ 70h
bRequest: equ 71h
wValue: equ 72h ; default wValue (8 bits)
wValueHi: equ 73h
wIndex: equ 74h ; default wIndex (8 bits)
wIndexHi: equ 75h
wLength: equ 76h ; default wLength (8 bits)
wLengthHi: equ 77h
;Endpoint 1 buffer
endpoint_1: equ 78h
Endpoint1_Byte0: equ 78h ; Endpoint 1, byte 0
Endpoint1_Byte1: equ 79h ; Endpoint 1 byte 1
Endpoint1_Byte2: equ 7Ah ; Endpoint 1 byte 2
Endpoint1_Byte3: equ 7Bh ; Endpoint 1 byte 3
Endpoint1_Byte4: equ 7Ch ; Endpoint 1 byte 4
Endpoint1_Byte5: equ 7Dh ; Endpoint 1 byte 5
Endpoint1_Byte6: equ 7Eh ; Endpoint 1 byte 6
Endpoint1_Byte7: equ 7Fh ; Endpoint 1 byte 7
;----------------------------------------------------------------------
; Variables stored in data memory
;----------------------------------------------------------------------
;USB status
remote_wakeup_status: equ 30h ;0=disabled, 2-enabled
configuration_status: equ 31h ;0=unconfigured, 1=configured
;idle_status: equ 33h ;support SetIdle and GetIdle
protocol_status: equ 34h ;0=boot protocol, 1=report protocol
;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
;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
temp: equ 25h
start_time: equ 21h
testbit: equ 22h
interrupt_mask: equ 20h
endp0_data_toggle: equ 23h
loop_counter: equ 24h
data_start: equ 27h
data_count: equ 28h
endpoint_stall: equ 29h
;======================================================================
;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 push the accumulator (because
; ipret pops it) and 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 and take appropriate action.
; Copy values to Endpoint 1's buffer for sending.
;----------------------------------------------------------------------
One_mSec_ISR:
push A
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
;Enable pullups on Port 1; disable the output DAC.
mov A, 0h
iowr Port1_Pullup
mov A, 0ffh
iowr Port1_Data
;Set the Suspend bit.
iord Status_Control
or A, 08h
iowr Status_Control
;The chip is now in Suspend mode.
;On exiting Suspend mode, the chip will begin
;executing instructions here:
nop
;Disable pullups on Port 1. Enable the output DAC.
mov A, 0ffh
iowr Port1_Pullup
mov A, 0h
iowr Port1_Data
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 buffer for transmitting to the host.
;Two bytes:
mov A, [Data_Byte0]
mov [Endpoint1_Byte0], A
mov A, [Data_Byte1]
mov [Endpoint1_Byte1], A
;Add more bytes if the report format specifies it:
; mov A, [Data_Byte2]
; mov [Endpoint1_Byte2], A
; mov A, [Data_Byte3]
; mov [Endpoint1_Byte3], A
; mov A, [Data_Byte4]
; mov [Endpoint1_Byte4], A
; mov A, [Data_Byte5]
; mov [Endpoint1_Byte5], A
; mov A, [Data_Byte6]
; mov [Endpoint1_Byte6], A
; mov A, [Data_Byte7]
; mov [Endpoint1_Byte7], A
;Other things to try:
;Set the value at Port 0 to equal byte 0 in Endpoint 1's buffer:
; iord Port0_Data
; mov [Endpoint1_Byte0], A
;Or set a value here and copy to Endpoint 1's buffer, byte 1:
; mov A, A5h
; mov [Endpoint1_Byte1], 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
;Set bits 4 and 7 to 1 enable transmitting.
;The low nibble is the number of data bytes (2).
or A,92h
iowr USB_EP1_TX_Config
Select:
;Enable Endpoint 1 interrupts.
mov A,[interrupt_mask]
or A, 10h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -