⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 max3420e_evkit2_democode.asm

📁 MAX的USB3420E芯片的技术应用文档
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	rjmp	clrstall
; set stall bit
	SETFLAG	ep3stall
	ori		MAX_Dat,bmSTLEP3IN
	rjmp	stl
clrstall:
	CLRFLAG	ep3stall
	andi	MAX_Dat,!bmSTLEP3IN
stl:rjmp	wregAS				; return from there
;
as:	ldi		MAX_Reg,rREVISION
	rjmp	rregAS					; do a dummy read just to set the ACKSTAT bit (return from rregAS)

; ----------
; Get Status
; ----------
Get_Status:
	ldi		MAX_Reg,rEP0FIFO	; in any case
	lds		temp,SUD+bmRequestType
	cpi		temp,0x80			; directed to device?
	breq	GS_RWU				; yes--device status bits are self-powered & remote wakeup
	cpi		temp,0x81			; directed to interface?
	breq	GS_IF				; yes--no status bits, just send 2 zero bytes
	cpi		temp,0x82			; directed to endpoint?
	breq	GS_HALT				; yes--only ep status byte is HALT bit
	rjmp	stall
GS_RWU:
;
; There are two status bits for a Device, b1=RWU_enabled and b0=Self_Powered.
; Both bits are zero: No RWU (as reported at enumeration), and we are bus powered.
; 
;	bst		flags,RWU_enabled	; RWU_enabled bit -> T bit
;	bld		MAX_Dat,1			; T bit -> into b1
	clr		MAX_Dat
sz:	rcall	wreg
	ldi		MAX_Dat,0			; second byte is 0
	rcall	wreg
	ldi		MAX_Reg,rEP0BC
	ldi		MAX_Dat,2			; byte count
	rjmp	wregAS				; return from there
;
GS_IF:
	ldi		MAX_Dat,0x00		; just send two zeros
	rjmp	sz					; send this byte then a zero byte & finish the transaction
;	
GS_HALT:
	lds		temp,SUD+wIndexL	; make sure it's directed to our only data endpoint, EP3-IN
	cpi		temp,0x83			; b7=1 for IN, EP=3
	breq	valid_ep
	rjmp	stall				; illegal request
valid_ep:
	bst		flags,ep3stall		; ep3stall bit -> T bit
	bld		MAX_Dat,0			; bit 0 is the status HALT bit
	rjmp	sz					; send this byte then a zero byte & finish the transaction
;
;-----------------
Get_Configuration:
;-----------------
	ldi		MAX_Reg,rEP0FIFO
	mov		MAX_Dat,configval	
	rcall	wreg
	ldi		MAX_Reg,rEP0BC
	ldi		MAX_Dat,1
	rjmp	wregAS				; set the ACKSTAT bit. Return from there.
;
;-----------------
Set_Configuration:
;-----------------
	lds		configval,SUD+wValueL	; config value in this byte
	mov		temp,configval			; so we can compare immediate
	cpi		temp,0
	brne	enable_suspend_IRQ		; if IF NE 0, enable suspend interrupt
	rjmp	as						; set the ACKSTAT bit and return
enable_suspend_IRQ:
	ldi		MAX_Reg,rUSBIEN			
	rcall	rreg
	ori		MAX_Dat,bmSUSPENDIE
	rjmp	wregAS					; return from there
;
;-----------------
Get_Interface:
;-----------------
; Respond to interface=0, report alternate setting=0 (our only alternate setting)
;
	lds		temp,SUD+wIndexL	; wIndexL=Interface index
	cpi		temp,0
	brne	stall2				; jump to Stall_EP0 from there
	ldi		MAX_Reg,rEP0FIFO
	ldi		MAX_Dat,0			; alternate setting = 0
	rcall	wreg
	ldi		MAX_Reg,rEP0BC
	ldi		MAX_Dat,1
	rjmp	wregAS				; return from there
;
; Jump target for relative branches to reach the 'stall' label
;
stall2:
	rjmp	stall
;
;-----------------
Set_Interface:		
;-----------------
;
; Our descriptor reported only one interface(0) with one AS(0)
;
	lds		temp,SUD+wValueL	; wValueL=AS, should be 0
	tst		temp
	brne	stall2				; not zero--error
	lds		temp,SUD+wIndexL	; wIndexL is interface
	tst		temp
	brne	stall2				; not zero--error
	rjmp	as					; return from there
;
;----------------------------------------------------------------
; Send a descriptor--Device, Configuration, String, HID or Report
;----------------------------------------------------------------
Get_Descriptor:
	CLRFLAG	UNIflag					; initial assumption--not a UNICODE string
	ldi		ZH,HIGH(DD*2)			; same page for all descriptors
	lds		reqlen,SUD+wLengthL		; assumes 64 byte maximum descriptor size
	lds		temp,SUD+wValueH		; descriptor type
	cpi		temp,GD_DEVICE
	brne	sd2
	ldi 	ZL,LOW(DD*2)			; get the device descriptor pointer
	lpm		desclen,Z				; length byts is DD[0]
	rjmp	send_dscr
;
sd2:
	cpi		temp,GD_CONFIGURATION
	brne	sd3						
	ldi	 	ZL,LOW((CD*2)+2)		; length byte is at offset 2 (3rd byte)
	lpm		desclen,Z				; rombyte=LengthL
	ldi		ZL,LOW(CD*2)			; point to beginning of config descriptor
	rjmp	send_dscr
;
sd3:
	cpi		temp,GD_STRING
	brne	sd4
	SETFLAG	UNIflag					; speculative
	lds		temp,SUD+wValueL
	cpi		temp,0
	breq	string0
	dec		temp
	breq	string1
	dec		temp	
	breq	string2
	dec		temp
	breq	string3
	rjmp	stall
;
string0:
	ldi		ZL,LOW(STR0*2)
	CLRFLAG	UNIflag
	rjmp	sd5
string1:
	ldi		ZL,LOW(STR1*2)			; the rest of these are UNICODE
	rjmp	sd5
string2:
	ldi		ZL,LOW(STR2*2)
	rjmp	sd5
string3:
	ldi		ZL,LOW(STR3*2)
	rjmp	sd5
;
sd4:cpi		temp,GD_HID
	brne	sd6
	ldi		ZL,LOW(HD*2)
sd5:lpm		desclen,Z			; fall through to send_dscr
;
; Send a descriptor. Send the lesser of requested and actual string length.
; First retrieve and send a byte, then test the 'stringflag' to see if it's a string descriptor.
;	If a string descriptor, send the first two bytes verbatim, then send the remaining bytes
; 	with a '0' appended to every byte (to account for the Unicode requirement).
; 
send_dscr:
	BRLTE	reqlen,desclen,ss1
	mov		reqlen,desclen
ss1:push	reqlen
	ldi		MAX_Reg,rEP0FIFO
	ldi		temp,0				; temp is character counter
ss2:lpm		MAX_Dat,Z+			; get next byte and bump pointer
	rcall	wreg	; send the character
	sbrs	flags,Uniflag		; test for Unicode string
	rjmp	not_string
	inc		temp
	cpi		temp,3				; nothing special for the first two chars
	brcs	not_string			; act like it's not a string for the first two chars
	ldi		MAX_Dat,0
	rcall	wreg	
	dec		reqlen				; we just sent an extra zero (Unicode)
not_string:	
	dec		reqlen
	brne	ss2
; 
; Finished stuffing the EP0 FIFO with the requested descriptor. Load the EP0 byte count
; register to enable the IN transfer.
;
	pop		reqlen
	ldi		MAX_Reg,rEP0BC
	mov		MAX_Dat,reqlen
	rjmp	wregAS				; return from there
;
sd6:cpi		temp,GD_REPORT
	breq	dord	
	rjmp	stall2				; illegal descriptor type was requested
;
; The report descriptor is different because it does not contain its own length field.
; The length is in the seventh byte of the HID descriptor
;
dord:
	ldi		ZL,LOW((HD*2)+7)	; length is 8th byte of HID descriptor (offset 7)
	lpm		desclen,Z			; read it
	ldi		ZL,LOW(RD*2)		; now point to the REPORT descriptor
	rjmp	send_dscr
;
;----------------------------------------------------------
; Send a keystroke over the interrupt endpoint EP3-IN.
; This routine is called when the EP3IN IRQ asserts, 
; at the time that the previously loaded keycode is 
; acccepted (ACK'd) by the host.
;
; The routine first examines the enable_send flag. 
; If enable_send = 0:
; It sends [00 00 00] to indicate "keys up".
;
; If enable_send = 1:
; It reads one encoded byte in FLASH memory and decodes this
; to send keystrokes as [SB,00,KC] where SB is the shift
; byte (02 for shift, 00 for lower case),and KC a HID-encoded
; keycode. The data is packed into one byte where the msb is the 
; shift indicator (shift=1), and the rest of the byte is
; the keycode.
;
; The routine first checks for a special code of 0xFF, which 
; tells it to send [08 00 0x15] to open the RUN menu. Then it 
; sends an ENTER code to launch the last app opened
; using the windows "Run" command.
;
; The text message to send is terminated by a 0. When this
; routine detects the 0, it resets the message pointer.
;
; The routine sends a "keys up" code [00 00 00] after every keycode.
;
;---------------------------------------------------------
send_keystroke:					; Send next HID character in HID_Message. Check for wrap (zero terminator).
;
	ldi		MAX_Reg,rEP3INFIFO	; we'll write this FIFO register three times
	bst		flags,Send_Flag		; T <- Send flag
	brtc	send_zeros			; Branch if Send_Flag(T)=0 (don't send)
	SKIP_ON_FLAG keyupflag
	rjmp	sk2
	CLRFLAG	keyupflag			; send zeros as "all keys up"
	rjmp	send_zeros
sk2:ldi		ZH,HIGH(KB_Message*2)	; *2 because Z counts bytes
	mov		ZL,pMessage
	lpm		temp,Z+				; get the next byte and bump the index
	mov		pMessage,ZL			; save the index for next time
;
	tst		temp				; check for a zero (AVR assembler pads odd byte DB statements with a trailing zero)
	brne	nozero
	rjmp	sk2					; skip the zero
nozero:
	cpi		temp,0xFF			; check for 0xFF message terminator
	brne	no_wrap				; it's not 0xFF--proceed
	ldi		pMessage,LOW(KB_Message*2)	; it's 0xFF--reset the message pointer
	rjmp	sk2					; go again
no_wrap:	
	SETFLAG	keyupflag			; next IN request send the all-keys-up code
;
	ldi		MAX_Dat,0			; speculative load--no shift
	sbrc	temp,7				; skip if b7=0 (non-shifted char)
	ldi		MAX_Dat,2			; shift character--send 02
	rcall	wreg				; 1st byte, 0(unshifted) or 2(shifted)
	ldi		MAX_Dat,0
	rcall	wreg				; 2nd byte, always a 0 (from HID report descriptor)
	andi	temp,0b01111111		; zero-out the MSB (shift indicator)
	mov		MAX_Dat,temp
sk:	rcall	wreg				; 3rd byte, the actual key code (or a zero) 
	ldi		MAX_Reg,rEP3INBC	; load the byte count
	ldi		MAX_Dat,3			; send 3 bytes & clear the IRQ
	rjmp	wreg				; return from there
send_zeros:
	ldi		MAX_Dat,0
	rcall	wreg	; first zero
	rcall	wreg	; second zero
	rjmp	sk					; third zero and byte count
;
; ------------------------------------------------------------------
; Read a MAX3420E register. Uses MAX_Reg(preserved), Updates MAX_Dat.
; Call 'rregAS' to set the ACKSTAT bit.
; ------------------------------------------------------------------
rregAS:
	seT
	rjmp	rr2
rreg:
	clT
rr2:mov		dat,MAX_Reg	; 000rrrrr
	lsl		dat			; 00rrrrr0
	lsl		dat			; 0rrrrr00 (R) 
	lsl		dat			; rrrrr000	(write bit is clear--b1)
	bld		dat,0		; rrrrr00T	(T=ACKSTAT bit)
	rcall	send_byte
; 
; Now read the MISO data
;
	SCK_LO
rd4:SCK_HI					; ready the next input bit
	sec						; speculatively set CY
	sbis	PINB,MISO		; skip if set
	clc
	SCK_LO
	rol		MAX_Dat			; shift CY into the data byte
	dec		bitcount
	brne	rd4
	SS_HI					; all done
	ret
;
; ----------------------------------------------------------------------------
; Write a MAX3420E register.Uses MAX_Reg(preserved),MAX_Dat(preserved)
; ----------------------------------------------------------------------------
wregAS:
	seT
	rjmp	wr2
wreg:
	clT
wr2:mov		dat,MAX_Reg	; 000rrrrr
	lsl		dat			; 00rrrrr0
	sec	
	rol		dat			; 0rrrrr01 (W) 
	lsl		dat			; rrrrr010	(write bit is set--b1)
	bld		dat,0		; rrrrr01T	(T=ACKSTAT bit)
	rcall	send_byte
;
; Now the data byte in Max_Dat
;
	mov		dat,MAX_Dat
	rcall	send_byte
;
	SCK_LO
	MOSI_LO
	SS_HI
	ret	
;					
send_byte:
	ldi		bitcount,8	; bit counter
;
	SS_LO
c1:	SCK_LO
	rol		dat			; thru carry
	brcc	c2
	MOSI_HI
	rjmp	c3
c2:	MOSI_LO
c3:	SCK_HI
	dec		bitcount
	brne	c1
	ldi		bitcount,8	; get ready for the data byte
	ret
CODE_END:


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -